Static Site Engine Battle Royale

We’re living in a time where everything old is made new again – with a twist. For instance, I can (and do) find tons of new bands who produce what can easily be called modern variations on 80s and 90s music (Haim and Haerts being the former and The Pains of Being Pure at Heart being an example of the latter). We have new movies like “Earth to Echo” which is just a modern E.T. and even the Teenage Mutant Ninja Turtles are back (in a new, creepily realistic, new form).

Even static web sites are back in full force. However, these are not the same old static sites that many of us used to build, painstakingly, by hand in tools like Dreamweaver 15 years ago. These static web sites include some of the dynamic aspects of a modern CMS using tools like Node.js (or Ruby), Markdown, templating engines and language subsets. You can even keep fully dynamic features like comments, search and more through a number of (usually free) service without sacrificing the blazing performance of a static site.

Thus, nowadays, a static site is a legitimate option for many content sites, especially blogs. However there are a number of available tool options and it can be hard to know which to choose. In this article, we’ll look at and compare three of these popular options: Jekyll; Harp; and Roots.

The Parameters of the Test

For the sake of this comparison, I am attempting to build a simple blog with the tool (actually, it is an attempt to replace my existing personal blog). I will work with the available template options to try to customize and create a simple blog. For this comparison, I will use whatever CSS, templating or other languages and tools that each static site engine provides by default (for example, where the default is LESS, I will use that, and where the default is Stylus, I will use that instead).

This site will also have some dynamic aspects beyond the basic blog posts. I will attempt to create several pages that rely on dynamic data to populate a list of items (in this case, dynamic lists of presentations, articles and videos). The dynamic data will be created in whatever format the engine uses by default (i.e. JSON or YAML).

Ok, let’s get started.

jekyll_logo

Jekyll

Jekyll was originally created by one of GitHub’s cofounders, Tom Preston-Werner, as a file-based CMS. Likely due to the fact that it is used to run GitHub pages, it is also the most popular of the static site solutions.

Install

Assuming you are on a Mac, the install is fairly easy via ruby gem (Windows not officially supported but there is a workaround). I did have to use sudo.

sudo gem install jekyll

Initially I ran into the following error:

Failed to build gem native extension.

Based upon some research into other people hitting this error, I ran…

sudo gem update --system

While this didn’t immediately help, I may also have been suffering from a limited connection while traveling. Once I was on my home network, the installation went smoothly from this point.

Creating a Project

Creating a new project is pretty simple. First cd into the directory where you want to create the project files and enter:

jekyll new projectname

Now cd into your project folder and start the web server:

jekyll serve

At this point, you can open the default blog page at localhost:4000. The basic page looks pretty simple, as you can see below:

jekyll_default_site

I should note that you can start the server with a bunch of options including changing the port (-p), watching for changes (-w), base URL to use (-b) and much more. Your pretty much going to want to use the watch option during development as doing otherwise requires you to restart the server to see changes.

You’ll want to begin by editing some of the basic metadata defaults inside the _config.yaml file including your site name, email and so on. One thing to be aware of is that, even if you have the watch option on, changes to the configuration require that you stop and restart your server.

Working in Jekyll

While Jekyll feels extremely powerful, I found the getting started experience a little rough around the edges. The documentation gets very detailed very quickly, and, while it covers all the details, it is a bit on the overwhelming side for a noob.

On the plus side, you don’t need any special knowledge of CSS preprocessors or JavaScript language subsets like CoffeeScript to get started. Even the templating language, Liquid, is mostly just HTML with added logic and output tags. I personally found it pretty straightforward (and well documented). The default site design was simple but was responsive and included a responsive nav that uses a hamburger icon for the phone layout – a nice touch.

A pet peeve of mine is static sites that don’t include an RSS feed, but the default template includes RSS by default.

Adding custom data was also a breeze. While Jekyll supports data in JSON, it uses YAML by default. While my existing data was in JSON, there’s a nice JSON to YAML converter that work in Node via the command line or in the browser.

I’d never worked with YAML before, but I found it very easy, and much faster to write than JSON. For example, here’s some data respresenting a snippet of my publications:

-   name: "Adobe Developer Connection"
    articles: 
      - 
        title: "Node.js command-line tools for front-end development"
        URL: "http://www.adobe.com/devnet/html5/articles/nodejs-command-line-tools-for-front-end-development.html"
      - 
        title: "HTML, CSS and JavaScript code editing with Edge Code"
        URL: "http://www.adobe.com/devnet/edge-code/articles/code-editing-with-edge-code.html"
      - 
        title: "Browser testing across devices with Adobe Edge Inspect"
        URL: "http://www.adobe.com/devnet/edge-inspect/articles/browser-testing-across-devices-with-adobe-edge-inspect.html"

I placed my data in a file called publications.yaml inside the _data folder. I was then able to access it on the publications page I was building, loop through it and display it using this simple snippet of code:

{% for publication in site.data.publications %}
    <h3>{{publication.name}}</h3>

    {% for article in publication.articles %}
        <p><a href="{{article.URL}}">{{article.title}}</a></p>
    {% endfor %}
{% endfor %}

If you are running the local Jekyll server, any mistakes you make trying to access data (or in creating your Liquid templates in general) usually gives a fairly detailed error message. This makes debugging easy.

Overall

Ease of Install: Good. It does a good job of covering the details, but often feels a bit overwhelming for a beginner.

Getting Started: Very good. Once I figured out how the tool worked (which required a bit of reading), getting a basic site up and running was trivial.

Language Support: Good. It’s mostly just HTML, CSS and JavaScript. Liquid templates are pretty simple and straightforward and very well documented. YAML is a nice data format for custom data. Languages like LESS, Sass, Jade, CoffeeScript and more are supported via community plugins.

Extensibility: Very Good. You can write your own plugins or install one of the many community built ones (see the docs for details)

Documentation: Good. Once you get comfortable they are very good – I just felt they weren’t the most beginner friendly.

Project Health: Very good. The GitHub project seems active and well maintained and the community is large and active.

Another item worth mentioning, but not one of my comparison criteria, is that Jekyll has an import tool that can help you transition from a number of other blog options.

harp_logo

Harp

Harp was created by some of the same developers who helped create PhoneGap and now run a company called Chloi. Harp’s emphasis is its flexibility, including a wide range of supported languages, as well as it’s quick and easy getting started option via the commercial Harp Platform option, which allows you to easily publish via DropBox.

Install

Harp is installed as a global install via npm.

sudo npm install -g harp

Creating a Project

To start, cd into the directory where you would like your project created and then do:

harp init projectname

I wasn’t connected to the internet the first time around (on a plane), so it used the default template automatically. The default template is Jade for the HTML templating language and LESS for the CSS. However, you do have the option of choosing a custom template via the boilerplate option:

harp init -b <github-username/repo>

There are some additional boilerplates available in the Harp boilerplates GitHub repository. For example, I wanted to start a new blog, so I used the following:

harp init harpsite -b harp-boilerplates/hb-blog

This gives a default blog with a homepage and posts that looks like the screenshot below.

harp_blog_default

Harp supports Markdown, EJS, Sass, Stylus and CoffeeScript by default. Of course, you can just use straight HTML, CSS and JavaScript if you like.

Now cd into your project directory and run harp server and this will start a web server (the default port 9000 but you can specify a port via the -p option) where you can run the project. Harp will display the contents even though they are not yet compiled.

Working in Harp

Overall I found the experience of working in Harp pretty intuitive. Creating a simple blog with subpages was straightforward enough using the default blog template. Posts can be written in Jade or Markdown (or straight HTML as well), and just adding a file into the posts folder and editing the _data.json file is all you need to add a post.

The default template uses Jade for templating and LESS for CSS. Both are easy enough to learn and have solid documentation. I don’t love Jade, personally, as I find it not much easier to read than straight HTML, but creating simple layouts was easy enough. I was able to do some basic tweaks to the deault layout (via the _layout.jade file), to make my site a little more my own.

It was nice to see that the RSS file was automatically created for my new blog with the blog template. A lot of static sites overlook this.

One difficulty I had was in adding some dynamic contents in to other pages. Harp automatically reads in a _data.json file in a folder and makes the data available in the public variable. However, the documentation on how to format the JSON and access it was thin (in fact, overall, Harp documentation felt thin). Thus, I encountered situations where my JSON was valid, but there didn’t seem to be a way to access it from within the Jade template.

In the end, after some experimentation and reformatting my JSON, I got things to work well. For example, here is a snippet of my publications JSON data:

...
"pub5": {
  "name": "Adobe Developer Connection",
  "articles": [
      {
        "title": "Node.js command-line tools for front-end development",
        "URL": "http://www.adobe.com/devnet/html5/articles/nodejs-command-line-tools-for-front-end-development.html"
      },
      {
        "title": "HTML, CSS and JavaScript code editing with Edge Code",
        "URL": "http://www.adobe.com/devnet/edge-code/articles/code-editing-with-edge-code.html"
      },
      {
        "title": "Browser testing across devices with Adobe Edge Inspect",
        "URL": "http://www.adobe.com/devnet/edge-inspect/articles/browser-testing-across-devices-with-adobe-edge-inspect.html"
      }fupdating_extension.html"
      }
    ]
},
"pub6": {
  "name": "Onward Search Blog",
  "articles": [
      {
        "title": "Breaking into a Front-end Development Career",
        "URL": "http://blog.onwardsearch.com/2012/11/breaking-in-to-a-front-end-development-career/"
      }
    ]
},
...

The arbitrary structure names you see (i.e. pub5) were what seemed to allow me to properly access the data from the template. For example, below is the Jade template that loops through and displays the publications data.

h2 Publications

each publication in public.publications._data
    h3= publication.name

    each article in publication.articles
        p
            a(href="#{article.URL}") #{article.title}

Compiling was just a matter of calling harp compile from the command line. The files from my public folder were compiled automatically into the www folder.

Overall

Ease of Install: Very good. Assuming you have Node.js installed, you’ll likely hit no issues.

Getting Started: Good. The process worked well. Even installing the default template when offline works.

Language Support: Very Good. While I don’t find Jade the easiest option if you are a beginner, it certainly isn’t terribly difficult. LESS is easy enough as well. However, Harp supports a wide array of other options that most everyone should be happy.

Extensibility: Minimal. Other than adding templates, I didn’t see a way to add plugins or additional language support.

Documentation: Poor. Beyond getting started, the documentation seemed fairly thin.

Project Health: OK. There doesn’t seem to be a lot of activity on the Harp GitHub project lately, but there was activity a few months ago.

roots_logo

Roots

Roots was created by Jeff Escalante. The project seems to have a goal of being powerful without being heavy handed via its ease of installation, clean and minimal default templates and simple deployment tasks built-in.

Install

Roots is also installed via npm, so the install is simple (note that I needed the sudo to get the install to work properly):

sudo npm install roots -g

The first time I ran this, it came up with error that I needed developer tools which were not yet installed. However, I was prompted to do the install and, once complete, the Roots install worked fine.

Creating a Project

First, of course, cd into the directory where you would like to create your project. To create a new project using the default template simply enter:

roots new projectname

As a side note, you do need to have an Internet connection to complete this as it will try to load the default template via GitHub. This usually isn’t a problem, but it is an issue that came up for me in my initial testing.

To get the server up and running, you can simply enter the command roots watch which will start a server (the default is port 1111) and, as a nice little touch, even open the page in your default browser. The default template is extremely simple, looking like the screenshot below.

default_roots_site

Any changes made to the site will automatically be reflected in the browser without needing to refresh (using LiveReload).

As you can see, the default site is extremely basic. It doesn’t have anything that you might need if you are starting a blog, for instance. It is basically just a directory structure and a few basic files for starting a full static site completely from scratch.

However, if you look in the command line tool documentation or watch the dynamic content video (or if you look at the templates in the global config, you’ll see that there are some predefined templates , including one for a basic blog. To create a blog, use the following command:

roots new projectname --blog

The layout is still pretty basic however, as you can see below.

roots_default_blog

Working in Roots

One of the first things to consider is that default stack is Jade, CoffeeScript and Stylus, though you can work in straight HTML, JavaScript and CSS (there is also support for EJS). If you don’t like that stack, you probably shouldn’t use Roots. It can support other languages via plugins, but there are none that I could find already available.

As I noted in the prior section, given the simplicity of the default layouts, Roots seems best suited for wants to code the site from the ground up rather than start with a template.

As a side note, I tried copying some of the Harp templates using Jade and then converting the Less using a converter but this turned out to be imperfect and, for my simple use case, more work than it is worth.

It is worth noting that even the default blog template does not include RSS, so you’ll need to build that on your own.

Dynamic content was complicated, or, at the very least, sparsely documented. The documentation does cover he concept of locals which are variables set in the app.coffee file and are available throughout the site (it is worth noting that changing locals required that I restart the server even if I was using the watch option). It also covers loading things like a list of blog posts in a folder. However, I could not find how to load either JSON or YAML and then use that data (I tried some solutions but none worked as I thought).

Looking at this GitHub Issue, I am left with the impression that perhaps loading dynamic content via JSON or YAML is not yet available.

Some nice features of Roots include the ability to deploy it to Express and Rails. Or, if you use Heroku, Roots has simple built in command line options that make it easy to deploy your site there.

Overall

Ease of Install: Very good. Even the one dependency that was required that I did not have was prompted for install.

Getting Started: OK. The default templates are very basic and aren’t that different from starting from scratch, short of a few sample lines of code.

Language Support: OK. Assuming you like CoffeeScript, Stylus and Jade (or EJS), you’ll be happy. Other languages can be added via plugins, but none seem to exist yet.

Extensibility: Good. There is documentation for building plugins, which seem relatively simple.

Documentation: Good. The docs provide detailed command line options and a good getting started walkthrough in both text as well as a series of short videos.

Project Health: Questionable. There appears to have been minimal activity within the past 6 months on the GitHub project.

Conclusion

Both Harp and Roots offer some really interesting options, but, in my opinion, Jekyll still seems to be the most robust solution available. The one caveat is, of course, if you are on Windows, this could be an issue (though, perhaps the unofficial Windows support will work for you).

If you are interested in learning more about building static apps, the Field Guide to Static Apps offers a lot of resources and tutorials.

Comments

  • If anyone is struggling with Jekyll on Windows, take a look at http://hexo.io/ – its very close to a jekyll port, but on a JavaScript/Node stack, follows the same front-matter and markdown text for posts and has very simple content migration from an existing jekyll/octopress static site.

  • Just an FYI: as of version 2.0, Jekyll supports Sass and CoffeeScript natively; no need to install additional plugins: http://jekyllrb.com/news/2014/05/06/jekyll-turns-2-0-0/

  • Thanks for the write-up Brian. We’ve been a less visibly active on the main Harp repository recently, but we are going to have another version out this week. We’re very committed to it still.

    I’m sorry the documentation wasn’t as helpful as it could be, if you have feedback on more specific things that seemed lacking, I will make sure they are improved. The docs are really important to us. It sounds like our `_data.json` section (http://harpjs.com/docs/development/metadata) was insufficient?

    • remotesynth

      That is very good to hear. Harp was really nice and offered some cool features others didn’t. Based on my limited experience, the documentation for the custom data was limited. I ended up having to go through trial and error to find a JSON format that worked, even though other formats were all valid JSON. I’d love to see debugging improvements as well – this would have made that experience less complicated as it might have been obvious what I’d done wrong.

  • Andy Matthews

    Brian, I’ve used Cactus before and it seems pretty slick. I’d be interested in an addendum to this article which covers that; using the same criteria and scale.

    • remotesynth

      Thanks Andy. I’d never heard of Cactus before. I’ll check it out.

      • Andy Matthews

        Great. It actually even has a Mac desktop app (paid) that lets you manage multiple installs, publish, etc. http://cactusformac.com/

  • Andy Matthews

    I just found one that I’d never heard of before. It’s called Hugo (http://hugo.spf13.com/). Sounds pretty interesting.