Before we get started, let me ask you a question. What is the most common task you do when developing a WordPress theme (or any kind of website really)? What do you do so often that you don't even notice it - because it's in your muscle memory?

You refresh the browser. (Did not expect that one did you)

Well, what if I told you this can be automated and the browser can auto-refresh on its own whenever you make a change to a file? With Gulp, it's easy. And not only refreshing, you can automate sass compilation, file merging, syntax checks, deployment, you name it.

So, in this tutorial, I am going to show you how to set up Gulp and a few most common tasks that theme developers perform on a daily basis.


All the components that we are going to use in this tutorial rely on Node.js, which is the only requirement. It comes with a package manager called, unsurprisingly Node package manager, or NPM for short. Install Node then run $ npm -v to make sure it's running properly (it will give you version number).

Of course you should also have some kind of development environment for WordPress, be it VVV, HGV, MAMP or any other environment flavour of your choice. If it can run WordPress, you're good to go.

You'll also need a livereload extension for the browser you're developing in.

It's also advisable that you have at least hard of sass/scss (the difference is in the syntax, so I may choose either of the names going forward interchangeably)

Note: for the purpose of this tutorial I am going to set up a blank Underscores theme, but feel free to add the things you are about to learn to your existing one - you cannot do any harm.

What is Gulp

The official website says it's the streaming build system which are just fancy words for what is essentially a task manager. And by tasks I mean anything you need to do manually that could be automated (except for writing code that is, you can't avoid that). Some of the most common tasks you do when you're building a WordPress theme:

  • compile sass into CSS (if you use it)
  • compile Coffeescript into JavaScript (if you use it)
  • minify, concatenate, or lint (linting is a process of checking the code for poor coding practices) CSS and JavaScript
  • optimize images
  • create, delete, or zip files and folders
  • watch files for changes and…
  • refresh the browser if a file is changed - a task most commonly known as livereload. Bye-bye CMD + R.

From a more technical perspective, Gulp is a NPM package (that supports plugins), which means it needs Node.js to run.

What is Bower

Just like Gulp, Bower (initially developed at Twitter) is also an NPM package that manages frontend packages and their dependencies for you. What is a fronted package? jQuery is. Most of jQuery plugins are too - pretty much any JavaScript library that runs in the browser and usually comes with a CSS file (or more of them) is a frontend package. It's also my personal benchmark of quality; If a JavaScript library is also a NPM package it usually means the author follows modern practices and approaches. Not always, but often.

On our landing page for example, we use jQuery and a slider plugin (don't confuse it that with WordPress plugins) called Slick (for testimonials).

The problem Bower solves? Dependencies and outdatedness of those libraries/packages. You can easily run $ bower update and it'll automatically fetch the latest versions. Because I care about that. And you should too.

Install Gulp

Gulp requires two initial files in order to run: package.json and gulpfile.js so we're going to run the init script that creates the former (the latter you're going to have to create manually):

$ npm init .

It'll ask you a series of questions (just press enter if you don't know or are not sure) which will be transformed into a JSON configuration and saved into package.json. After some cleanup, my starting version looked like this:

  "name": "Kickstart",
  "version": "1.0.0",
  "description": "Underscores, enhanced with Gulp workflow",
  "main": "gulpfile.js",
  "author": "Tomaz Zaman <>"

Now, we need Gulp installed, so per it's documentation run $ npm install --save-dev gulp.

Now, that Gulp is installed, create a file in your theme root directory, named gulpfile.js and put the following in:

var gulp = require('gulp');

gulp.task('default', function() {


In order to test whether Gulp is installed properly, just run $ gulp - it'll run the default task (which does nothing for now), then exit.

Now, before we install any Gulp packages, we need to think about which tasks we'd like to automate:

  • I use sass, so we need a preprocessor which will make CSS out of it
  • I tend to separate JavaScript into multiple files (for clarity and organization) and I want to end up with one minified file
  • I'd like to know whether my JavaScript follows best practices
  • I like the browser to refresh automatically as I code.
  • I want Gulp to continue working when errors occur (by default it exits)

These are the basic requirements and some require more than one package, for example you need a watcher which will trigger the livereload when a file changes.

Let's install all of them in one go - run this command:

$ npm install —save-dev gulp-plumber gulp-watch gulp-livereload gulp-minify-css gulp-jshint jshint-stylish gulp-uglify gulp-rename gulp-notify gulp-include gulp-sass

(Don't worry if you've never heard of these packages, it'll become clear shortly)

Configure Gulp

Open gulpfile.js, which is where we'll spend the remainder of this tutorial. At the top, we need to require all the packages we installed in the previous step, so paste this in:

var gulp = require( 'gulp' ),
  plumber = require( 'gulp-plumber' ),
  watch = require( 'gulp-watch' ),
  livereload = require( 'gulp-livereload' ),
  minifycss = require( 'gulp-minify-css' ),
  jshint = require( 'gulp-jshint' ),
  stylish = require( 'jshint-stylish' ),
  uglify = require( 'gulp-uglify' ),
  rename = require( 'gulp-rename' ),
  notify = require( 'gulp-notify' ),
  include = require( 'gulp-include' ),
  sass = require( 'gulp-sass' );

Next, it's time to define the default error handler (gulp-plumber depends on it):

var onError = function( err ) {
  console.log( 'An error occurred:', err.message );
  this.emit( 'end' );

And now, finally, our first task which will compile sass into regular CSS (you're not still writing it by hand are you?):

gulp.task( 'scss', function() {
  return gulp.src( './scss/style.scss' )
    .pipe( plumber( { errorHandler: onError } ) )
    .pipe( sass() )
    .pipe( gulp.dest( '.' ) )
    .pipe( minifycss() )
    .pipe( rename( { suffix: '.min' } ) )
    .pipe( gulp.dest( '.' ) )
    .pipe( livereload() );
} );

Note: Don't worry if you don't know what pipe does, internally it's a function for streaming data (in our case files) while performing certain operations on that data in each step.

Let's look at this task we just defined; First, we tell it to take style.scss, register it with plumber (in case our sass has syntax errors) then compile it into regular CSS with sass() and finally writes it to the current directory. While we could stop there, I'm adding — for educational purposes — a few extra steps; After saving style.css it pipes it through a minificator, renames it to style.min.css, saves it, then finally reloads the browser.

Up until a couple of months ago, I used to use Compass for sass compilation, but it's really slow, which is why I switched to LibSass - an insanely fast, but slightly buggy option. You don't have to worry about it, since it's installed automatically with the gulp command above, so if you don't see any errors, it's working properly already.

Before we can test whether this task is working, we need the file /scss/style.scss, with the following example content:

$color: #36A9E1;

body {
  background: $color;

Now, the moment of truth. Run $ gulp scss and you should see your task creating two files in your root folder: style.css and style.min.css. Open the latter to see all the spaces and comments removed - which one you enqueue in WordPress depends whether you do minification on the server or not.

You probably don't want running this task every time you update a sass file, which is why we'll setup up the watch task:

gulp.task( 'watch', function() {
  livereload.listen(); './scss/**/*.scss', [ 'scss' ] ); './**/*.php' ).on( 'change', function( file ) {
    livereload.changed( file );
  } );
} );

As the last step, change the default task to look like this:

gulp.task( 'default', [ 'scss', 'watch' ], function() {

} );

Notice the two tasks in square brackets? Those are called dependant tasks and will run before the task which they are called in executes.

To test out whether everything is working properly run $ gulp (it'll keep running until you exit by pressing CTRL + C), open the WordPress site, and make sure to turn on Livereload extension on. Open the sample css file we created earlier, change the color to #78A30D and save the file. If your background changed from blue to green without the page refreshing, tap yourself on the back, job well done!

Note: In order to avoid this tutorial being any longer, I've deliberately left out JavaScript processing. But fear not, I created a gist with that included.

What about Bower?

Let's install the sass version of normalize.css via Bower. As with Gulp, you need to initialize the project by entering this command inside your theme root directory:

$ bower init .

Again, a couple of questions, you might as well just press enter through all of them and edit the created bower.json. Here's what mine looks like:

  "name": "Kickstart",
  "version": "1.0.0",
  "authors": [
    "Tomaž Zaman <>"
  "description": "Underscores + Gulp + Bower",
  "license": "MIT",
  "ignore": [

Then install Normalize:

$ bower install --save-dev normalize-scss

And import the newly installed file in your main sass stylesheet (scss/style.scss), so that it looks like this:

@import "../bower_components/normalize-scss/_normalize.scss";

$color: #36A9E1;

body {
  background: $color;

If you still have Gulp running, you should immediately see it in action, processing the new sass and creating new style.css. If not, run $ gulp and see the magic happen.


It may appear complicated at first but this kind of workflow is the future of not only WordPress theme development, but any kind of frontend development in general.

There are many theme authors out there who leverage the power of automation to significantly speed up their development workflow and this tutorial is all you need to get started. So no excuses - do it :)