Beef up WordPress Theme Dev with Twig and Gulp

*Icon made by Freepik from is licensed under CC BY 3.0

presented by

Hi! I'm Eric

Front End Developer.

PHP Developer.

Consultant for Cardinal Solutions

Technology is awesome.



New CSS features get implemented regularly.


JavaScript is moving to a yearly release cycle.

PHP 7, just around the corner!

WordPress is over

12 years old

As a Front End Dev

Keeping up with the latest && greatest can be difficult

Task Runners?

Atomic Design?

Style Libraries?

So... Twig?

Cleaner markup

Component driven

Developer Experience

Clearer syntax

Twig - Syntax

Twig has 3 forms of tags.


{% ... %} // logic


{{ }} // print


{# #} // comment

{% extends "base.twig" %}

{% block content %}

  {# Loop through posts #}

  {% if posts %} 
    <ul class="posts">
      {% for post in posts %}
        <li class="post post-{{ post.ID }}">{{ post.title }}</li>
      {% endfor %}
  {% else %}
    <p>No posts yet!</p>
  {% endif %}

{% endblock %}

Twig - Readability

Dot notation.

{% extends "tease.twig" %}

{% block content %}

  <h2 class="h2">
    <a href="{{ }}">{{ post.title|capitalize }}</a>
  <p>{{ post.get_preview(25)|escape }}</p>

  {% if post.thumbnail.src %}
    <img src="{{ post.thumbnail.src }}" />
  {% endif %}

  {% for i in 1..12 %}
    Option {{ i }}
  {% endfor %}

{% endblock %}

Clear helper filters

{% if 'Fabien' starts with 'F' %}

{% endif %}

English reading logic,

comparison functions

and built in filters.

Twig - Readability

    if ( in_array( get_post_type(), array( 'post', 'attachment' ) ) ) {
      $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';

      $time_string = sprintf( $time_string,
        esc_attr( get_the_date( 'c' ) ),
        esc_attr( get_the_modified_date( 'c' ) ),

        '<span class="posted-on"><span class="screen-reader-text">%1$s </span><a href="%2$s" rel="bookmark">%3$s</a></span>',
          _x( 'Posted on', 'Used before publish date.', 'twentyfifteen' ),
          esc_url( get_permalink() 
    {% if fn('get_post_type') in ['post', 'attachment'] %}
      <span class="posted-on">
        <span class="screen-reader-text">Posted on </span>
        <a href="{{ post.permalink }}" rel="bookmark">
          <time class="entry-date published updated" datetime="{{ fn('get_the_date', 'c')|e }}">
            {{ }}
    {% endif %}



Twig - Component Driven

If all your data is being injected into a template, it means you are no longer tied down to that data source.


$context = Timber::get_context();

$context['random'] = 'asfsadf';

$templates = array( 'index.twig' );

// inject the $context directly to twig
Timber::render( $templates, $context );
// index.twig

<h1>{{ random|capitlize }}</h1> 
<!-- Renders as: <h1>Asfsadf</h1> -->

This index.twig will always

render as expected when

$data['random'] is passed to it.

Twig - Component Driven

  public static function render( $filenames, $data = array(), ... ) {

    $output = self::compile( $filenames, $data, $expires, $cache_mode, true );
    $output = apply_filters( 'timber_compile_result', $output );

    echo $output;

    return $output;

Since Twig processes and builds the view of our page for



Component Driven

We can tie our templates together in parallel to our designed front end patterns.

Yay! Twig!

Let's use it in WordPress!



// single.php

// this essentially becomes a Controller

$context = Timber::get_context(); 
$context['foo'] = 'Bar!'; 
$context['post'] = new TimberPost(); 

Timber::render('single.twig', $context);

Start treating your .php files like controllers in an MVC site
use PHP to generate and alter

content as necessary to feed to

your twig templates


Timber comes with Class objects

that help instantiate and load

common WordPress objects.

So.. Gulp?


Streaming Build System

  • Easy to learn
  • High Quality
  • Efficient
  • Easy to use





Node Package Manager

Comes bundled with Node


`npm init`

`npm install --save-dev gulp`

`npm install --save-dev gulp-sass`

Coworkers / teammates can just do `npm install`after we do the initial setup of our package.json




Packages installed with NPM will get saved to node_modules folder.

We will want to add package.json to version control. 

Make sure we remove node_modules from our version control and let our team members `npm install` based off of the package.json.



Where we set up tasks for Gulp, and where we build out our script tasks.

As needed `npm install --save-dev` additional plugins to help handle and streamline your asset pipeline. 



Read instructions carefully when using a gulp plugin you have not used yet, if necessary feel free to browse it's repository source code.

Don't forget to var plugin = require('gulp-plugin'); in your gulpfile to use new plugins.



Run gulp in terminal

Now you have

all you need to

do all the things!

Twig Implementation via Timber

PostCSS, Sass,

New JS features via Babel,

Codestyle enforcement/ Linting,

and more!

Beef up WordPress Theme Dev with Twig and Gulp

By Eric Katz

Beef up WordPress Theme Dev with Twig and Gulp

Want to get into the latest and greatest in Front End development for your WordPress websites? This presentation will talk about re-organizing your theme development process by streamlining your build process with Gulp (http://gulpjs) and beefing up your templates with Twig (via Timber Will have some template comparisons and go over some best practices for Sass, JS coding style and using Twig.

  • 2,513
Loading comments...

More from Eric Katz