Roots — a delightful Static Site Generator. Get started in 20 minutes.

When I tried to use a Static Site Generator (SSG) for the first time, I really struggled to find something which was easy to set up, easy to deploy and easy to update. They all seem to require a in-depth understanding of their configuration in order to use, which can sometimes alienate those who have a lower level of skill.

In this tutorial, we’ll run through a delightful SSG called Roots, which I was introduced to by James. We’ll get through an installation, get a basic website built and then get it live by deploying it on GitHub Pages, which is free to use.

If this tutorial ever falls behind, Roots is made by Carrot Creative, and the

GitHub repository is here. The current version at the time of writing is 4.1.0.

Edit 19 May 2016:
* Updated for Roots 5.0.0
* Jade has now become Pug
* Note: Roots is soon being depreciated in favor of a new project, Spike. Once it is closer to (or has hit) version 1.0.0, I will write a new post for it.
Image for post
Image for post

If you don’t already, you’re going to need Node.js installed on your system. This comes bundled with the Node Package Manager (npm), which lets us install over 250,000 packages easily using our terminal, with about 700 new packages being added every day. Open up your terminal and type the following:

npm i roots -g

The i command means install, and the -g flag installs the package globally, so we don’t need to reinstall it for every new project we would like to set up.

And, well, that’s it. Roots is now installed on our system.

Image for post
Image for post

Getting up a new project is also super easy. cd into the directory you’d like to create your project in and type:

roots new project-name

You’re going to be asked some questions about your website — everything you type now can be changed, so don’t worry too much about it being final.

Let’s run through the most important parts of the project setup.


The app.coffee file contains all of the settings for the project. We’ll run through some of the basic configuration options later, which includes using roots extensions. This file is written in Coffeescript, which is a Javascript preprocessor. This means that the nicer, cleaner code we write in this file will be turned into a plain Javascript file before being executed. Again, don’t worry too much about this — we’ll cover it later.


The assets folder contains the static elements used in our project — this includes images, CSS and Javascript files. We can create new folders in here, such as files/, which can be used in our project later. Let’s leave it as is comes for now.

If you do poke around though, you may notice that the CSS folder doesn’t contain CSS files, but instead .styl files. Like Coffeescript, Stylus is a preprocessor — but this one is for your stylesheets. We’ll change this to a more common preprocessor later, but if you want to use Stylus, you can find the documentation here.


This is the folder which contains our actual pages which the user will see. Like everything else, these are being generated using a preprocessor called Pug. I really like Pug as it provides some extra features such as variables, directives (for/if statements) and partials. We’ll run through how to use Pug with Roots later.

Image for post
Image for post

Roots comes with a simple command to run a local web server, compiling your assets as they change and automatically refreshing the page. Make sure you’re in the directory created by roots new and type:

roots watch

If you head over to localhost:1111, you’ll see the site!

You may notice a new directory appear — public/ — you shouldn’t ever edit the contents of this folder as it is your complete, compiled website. If you change the contents of public/ and then something changes in your assets/, it may wipe your changes, which is never fun.

Image for post
Image for post

One of the biggest things that confuses people is working with preprocessors. Here’s the rundown of the most critical Pug (previously Jade) you need to know in order to work with Roots…

Sidenote here, Pug files still use the .jade extension during the transition between the Jade and Pug names. Once the situation is updated, I will update this post.


Pug doesn’t use HTML tags to explain where elements are in relation to one another, but instead uses indentation. If something is indented underneath another element, then it is inside of it’s parent.

Image for post
Image for post
Whether you use 2 spaces, 4 spaces or tabs, it doesn’t matter — as long as you choose one method and stick to it!


You may have also noticed that the tags look nothing like HTML at all. The easiest way to explain how Pug files map to their HTML output is through comparison..

You can define classes and IDs using CSS syntax, and define multiple attributes by comma separating them.


So far, we haven’t really touched Pug features and rather just the differences between writing Pug and HTML. By far the most useful feature of Pug, and the one which is used in the default Roots project, is layouts. Whatever the website you are building, there are always some elements of a page which stay the same on every page — examples include <head> tags, headers and footers. This is where layouts come in.

The file at views/layout.jade contains the project’s doctype, head tag (with meta and title tags) and a body tag. These exist and are the same no matter which page you are on, which makes this file a layout. Note the placement of block content as being inside of the body tag.

Now let’s head over to views/index.jade. In this file we extend the layout, meaning that we are going to render it, and then we also have a block content. Anything indented inside of the block content line will be inserted in the place of the line on views/layout.jade.

Image for post
Image for post

You can have multiple layouts, and layouts inside of other layouts, which can be useful if you have multiple page types in your site (blog, work, content, etc), which have different layouts, but still want to use a global header or footer, for example.


In the file views/index.jade, you may have noticed “:marked”. This simply means that anything indented inside of it will be Markdown and will be rendered into HTML. This is a Pug feature known as ‘filters’ if you’d like to read more into it.

Markdown is not intended to be a way to structure your webpages, but it is meant to structure your content. An example of when this may be useful is inside of a blog post.

Daring Fireball has a great Markdown reference which you can use if you want to learn more about it.

Image for post
Image for post
Image for post
Image for post

In the layout file, you may notice that there are two lines:

!= css()


!= js()

These are the combined output of the .coffee and .styl in assets/js and assets/css. They will be compiled into a single .css file and single .js file (in alphabetical order) which will ease the number of HTTP requests we’re making for individual files. We’re going to talk more about editing the preprocessors and functionality of this straight after we deploy our basic website.

Image for post
Image for post

Carrot, the creators of Roots, have built a nifty deployment tool for static websites called Ship. Unfortunately as of Roots 5.0.0, Ship has been depreciated, but we can install is from npm and use it with the ship command.

npm i ship -g

Before we continue, head over to GitHub and create a new empty repository for your website.

Let’s walk through how it’s used and what it does. Head over to your terminal and type ctrl+c in order to stop your local server. Then type in the following command:

ship public -to gh-pages

This is the command to push the website to GitHub Pages. It will ask you for three pieces of information:

  • Your GitHub username
  • Your GitHub password
  • Your repository. If your username is example and your repo is called website, your answer would be example/website

Your public/ folder will be pushed to the repository’s gh-pages branch. We are a go! If you want to deploy to other services, check out the documentation for ship.

Now, a couple of things which you need to be aware of…

Your ship.conf file

Using the roots deploy command creates a ship.conf file in your project root with your username and password in plaintext. This should NEVER be shared. Please make sure you edit the .gitignore file which roots automatically creates and add a new line containing the following:


Do this before you commit anything. If you’ve already pushed up the ship.conf file, please delete it and change your GitHub authentication details now.

Pushing your development files to GitHub

Using roots deploy only pushes public/ to the gh-pages branch. If you also want a copy of your development files version controlled (which you should), I’m going to show you the git commands to make this happen. I’m not going to explain every line, but if you need a git starter, visit try.github.io — it will be the best spent half hour in your career as a developer.

First time you commit:

git initgit remote add origin https://github.com/{{username}}/{{repo}}.git

Every change you want recorded (this doesn’t update the actual website)

git add — allgit commit -m “message which explains what you have changed”git push origin master

Every time you want a change live (this does update the website)

ship public -to gh-pages

Using custom domains

I’ll refer you to this guide from GitHub, which will talk through the specifics of setting up a custom domain with GitHub Pages, but you’re going to need to create a file called CNAME in your public/ folder and make it live with roots deploy.

Image for post
Image for post

So far, we’ve briefly looked at the app.coffee file and mentioned the three preprocessors used by default in Roots. Let’s run through how to change them.

Stylus to Sass

If you’ve read my earlier posts, you’ll know I’m a big fan of the CSS preprocessor Sass. If you want a run through of how to get started — check out this post which I wrote a few months back.

Firstly, let’s delete these lines from our app.coffee as they are packages which are Stylus-specific:

axis = require ‘axis’
rupture = require ‘rupture’
autoprefixer = require ‘autoprefixer-stylus’

Let’s also get rid of the Stylus configuration:

use: [axis(), rupture(), autoprefixer()]
sourcemap: true

Next up, let’s install Sass so we can include it in this project. Open up your terminal and type in the following:

npm install -g node-sass -s

The -s flag saves the dependency in the package.json file so it will install for other users if they grab your codebase.

Next, let’s require Sass. You can see us requiring the pipeline extensions at the top of app.coffee, and we’ll include Sass in very much the same way. Add this line at the top of your document:

sass = require ‘node-sass’

Finally, let’s configure Sass. The first thing to do is let the CSS Pipeline extension know that it’s now looking for .scss files rather than .styl files. Simply change “css_pipeline(files: ‘assets/css/*.styl’)” to “css_pipeline(files: ‘assets/css/*.scss’)”.

Coffeescript to vanilla Javascript

If you don’t want to use Coffeescript and want to use another preprocessor — use the above example as a guide, but if you want to remove the need for one all together and just use normal Javascript syntax, all you need to do is change the extension in the JS Pipeline configuration and remove these lines:

sourcemap: true


A tl;dr

Install with npm install roots — you’ll need Node.js installed

New project with roots new {{projectname}}

Local web server with roots watch

Deploy with ship public -to gh-pages — remember to not share the newly formed ship.conf. The public/ directory is the one which actually gets pushed.

Default preprocessors are Pug, Coffeescript and Stylus.

Written by

Javascript development and technical events.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store