Nothing. Timber is meant for you to build a child theme on. Like the Starkers or Boilerplate theme it comes style-free, because you're the style expert. Instead, Timber handles the logic you need to make a kick-ass looking site.
Timber is great for teams of designers and developers working together. At Upstatement not everyone knows the ins-and-outs of the_loop(), WordPress codex and PHP (nor should they). With Timber your best WordPress dev can focus on building the .php files with requests from WordPress and pass the data into .html files. Once there, designers can easily mark-up data and build out a site's look-and-feel.
Well, it's free! And it's GPL-licensed, so use in personal or commerical work. Just don't re-sell it.
Like where twentyeleven and twentytwelve live. Timber will live at the same level.
/wp-content/themes /twentyeleven
/twentytwelve
/timber
git clone --recursive [email protected]:jarednova/timber.git
This is important! --recursive is needed so that the Twig submodule is also downloaded. Having trouble with the recursive stuff? Skip to step #4 to download Twig
That's cool, you should, but developer lectures are lame. Grab the zip and stick it in the themes directory (so timber lives in the same folder as twentyeleven and other thems you may have)
We'll also need to grab Twig. Download the zip and replace the Twig folder inside of timber (please note: cAsE sEnSeTiVe). Confirm this file structure:
/wp-content/themes/timber/Twig/composer.json
/wp-content/themes/timber/Twig/lib
Optional but strongly recommended
Pull the child-theme
folder from timber
into your main themes
directory
You should now have
/wp-content/themes/child-theme
Feel free to rename this to something ... cool
Use the child theme from the step above.
You'll want to copy single.html from timber to your child theme's views folder. You should now have:
wp-content/themes/my-child-theme/views/single.html
Brilliant! Open it up.
{% extends "base.html" %}
{% block content %}
{% if post.banner_image %}
<img src="{{post.banner_image}}" class="blog-banner-image" alt="{{post.post_title}}" />
{% endif %}
<div class="content-wrapper">
<article class="post-type-{{post.post_type}}" id="post-{{ID}}">
<section class="article-content">
<h1 class="article-h1">{{post.post_title|editable(post.ID, 'post_title')}}</h1>
<h2 class="article-h2">{{post.subtitle}}</h2>
<p class="blog-author"><span>By</span> {{ post.author_data.display_name }} <span>•</span> {{ post.display_date }}</p>
{{post.post_content|wpautop|raw}}
</section>
<section class="article-comments">
{{comments}}
</section>
</article>
</div> <!-- /content-wrapper -->
{% endblock %}
<h1 class="article-h1">{{post.post_title}}</h1>
This is now how we now call stuff from the WordPress API. Instaed of this familiar face:
<h1 class="article-h1"><?php the_title(); ?></h1>
This is how WordPress wants you to interact with its API. Which sucks. Because soon you get things like:
<h1 class="article-h1"><a href="<?php get_permalink(); ?>"><?php the_title(); ?></a></h1>
Okay, not too terrible, but doesn't this (Timber) way look so much nicer:
<h1 class="article-h1"><a href="{{post.permalink}}">{{post.post_title}}</a></h1>
It gets better. Let's explain some other concepts.
{% extends "base.html" %}
This means that single.html is using base.html as its parent template. That's why you don't see any <head>
, <header>
, or <footer>
tags, those site-wide (usually) things are all controlled in base.html. If they're not? no prob, you can make single extend base-single.html or just include all the markup inside of single.html.
{% block content %} / {% endblock %}
If you were to peak into base.html you would see a matching set of {% block content %} / {% endblock %}
tags. single.html is replacing the content of base's {% block content %}
with its own.
Yeah baby!
Let's crack open index.php and see what's inside:
$data = get_context();
$data['posts'] = PostMaster::loop_to_array();
render_twig('index.html', $data);
This is where we are going to handle the logic that powers our index file. Let's go step-by-step
$data = get_context();
This is going to return an object with a lot of the common things we need across the site. Things like your nav and sidebar you'll want to start with each time (even if you over-write them later). You can do a print_r($data);
to see what's inside or open-up functions.php to inspect for yourself
$data['posts'] = PostMaster::loop_to_array();
We're now going to grab the posts that are inside the loop and stick them inside our data object under the posts key. What's this PostMaster business? It's a helpful class full of shortcuts to handle frequent WordPress tasks. Read more in the Wiki Docs
render_twig('index.html', $data);
We're now telling Twig to grab index.html and send it our data object.