Dave Perrett

Static Blogging the Jekyll Way

company, html5, jekyll, programming, ruby, sass, web

In building the new site, I decided to take the opportunity to try out something new. I’ve been using WordPress to power my blog for about 5 years, and while it has served me well, I wanted to try out something different. The main criteria for choosing a new blogging platform were :

  • It should serve true static pages, with no need for server-side processing.
  • It should be easy to store the entire site in Git.
  • It should support the concept of layouts - I wanted to have a single ‘template’ file that blog posts could easily inherit from.
  • It should support MarkDown or Textile for formatting posts, since I want to keep away from posting raw HTML as much as possible.
  • It should support comments.
  • I should be able to deploy updates to the site with a single command.

By patching together a few different open-source technologies, I’ve been able to achieve the above and more.

Jekyll

After trying out several different static site generators, I settled on Jekyll. In its own words :

Jekyll is a simple, blog aware, static site generator. It takes a template directory (representing the raw form of a website), runs it through Textile or Markdown and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server.

Jekyll has a healthy community built around it, and has a plugin system, which I figured would allow me to work around any shortcomings I came across. The fact that Jekyll is used to power GitHub Pages also helped sway my decision, since I know it isn’t going to go away anytime soon.

I won’t go into how to get your first Jekyll site going here, but the documentation on GitHub is excellent, and there’s a nice getting started guide to help you jump straight in.

Custom Jekyll Plugins

I ended up writing several custom Jekyll plugins to provide things that aren’t included by default :

  • A short generator to create a google-compatible XML sitemap automatically.
  • A generator to create category pages automatically (for example the Ruby category).
  • A more in-depth generator that takes git repositories, and automatically builds project pages for them using the README file, along with downloadable zipped copies of the projects themselves (for example, the jquery-simple-color plugin page). I only have a couple of these projects up at this point, but have quite a few queued up to release when time permits, so I wanted the process to be automated as much as possible.

The plugin documentation is a little sparse, but there are a couple of examples to get you going. I’ll be releasing the source of my own custom generators over the next couple of weeks, so stay tuned to RSS if you want more information.

HTML5 Boilerplate

Since this is the first site I’ve built with HTML5, I decided to use HTML5 Boilerplate as a starting-point, which bills itself as the professional badass’s base HTML/CSS/JS template for a fast, robust and future-proof site .

Overall it works very nicely, although things still look a bit wacky on Internet Explorer (my fault, not BoilerPlate’s). We’re serving the site with Nginx, so we miss out on some of the Apache .htaccess goodness that comes with HTML Boilerplate, but overall it’s nice and easy to dive in and get started with.

One minor niggle is that the meta tag for triggering Google Chrome Frame in IE doesn’t validate, which doesn’t really affect anything one way or the other, but it’s always nice to get the green tick from validator.w3.org.

Boilerplate was a cinch to get running with Jekyll - just a matter of dropping the CSS and JavaScript files in the right places, and editing the main layout.

Compass/Sass

After using Compass and Sass on a couple of projects in the past I was determined to use them again this time.

Compass is a stylesheet authoring framework that makes your stylesheets and markup easier to build and maintain. With compass, you write your stylesheets in Sass instead of CSS. Using the power of Sass Mixins and the Compass community, you can apply battle-tested styles from frameworks like Blueprint to your stylesheets instead of your markup.

The Compass/Sass combo is a huge time-saver when building CSS-heavy sites, and even on a reasonably minimal site like this it helps keep things nicely organized, readable and maintainable. Compass was relatively easy to get running with Jekyll - Bjorn Arild Maland has a few tips that helped here.

The fact that Compass was designed to work with ruby/rails was an added bonus here, since it allowed me to handle all common Jekyll and Compass tasks in the same Rakefile.

Pygments

Jekyll uses Pygments to do code syntax highlighting. Again I was pleasantly surprised how easy this was to integrate, since it’s written in Python rather than Ruby. Installation on Leopard is as simple as :

1
$ sudo easy_install Pygments

Once it is installed, you need to generate the CSS required for highlighting :

1
$ pygmentize -S default -f html > _sass/3rd_party/pygments/default.scss

This generates the default color scheme, and drops it into a folder inside sass (you may want to organize your SASS files differently). Once you have the CSS installed, you can highlight code in your posts by wrapping it in highlight_ tags :

1
2
3
 highlight ruby 
...code goes here...
 endhighlight 

Pygments supports a bunch of languages, and it doesn’t look terribly difficult to add your own if the need arises.

Rake

Being a huge fan of automation, I used Rake to script some of the common tasks involved with running the site. These shortcuts handle tasks like compiling the CSS, compiling the HTML, cleaning all build products, generating pygments CSS, and deploying the site.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
namespace :jekyll do

  desc 'Delete generated _site files'
  task :clean do
    system "rm -fR _site"
  end

  desc 'Run the jekyll dev server'
  task :server do
    system "jekyll --server --auto"
  end

  desc 'Clean temporary files and run the server'
  task :compile => [:clean, 'compass:clean', 'compass:compile'] do
    system "jekyll"
  end

end

namespace :deploy do
  desc 'Deploy to production'
  task :prod => ['dev:off'] do
    system "cap deploy"
  end

end

namespace :compass do

  desc 'Delete temporary compass files'
  task :clean do
    system "rm -fR css/*"
  end

  desc 'Run the compass watch script'
  task :watch do
    system "compass watch"
  end

  desc 'Compile sass scripts'
  task :compile => [:clean] do
    system "compass compile"
  end

end

namespace :pygments do

  desc 'Delete pygments CSS files'
  task :clean do
    system "rm -f _sass/3rd_party/pygments/*.scss"
  end

  desc 'Generate pygments CSS'
  task :compile => [:clean] do
    system "mkdir -p _sass/3rd_party/pygments"
    system "pygmentize -S default -f html > _sass/3rd_party/pygments/default.scss"
  end

end

namespace :dev do

  desc 'Un-publish old posts to speed up development'
  task :on => ['jekyll:clean'] do
    system 'find . -name "*.textile" -exec sed -i "" "s|^published: true|published: false|g" {} \;'
    system 'find . -name "*.yml" -exec sed -i "" "s|^published: true|published: false|g" {} \;'
  end

  desc 'Re-publish old posts for deployment'
  task :off => ['jekyll:clean'] do
    system 'find . -name "*.textile" -exec sed -i "" "s|^published: false|published: true|g" {} \;'
    system 'find . -name "*.yml" -exec sed -i "" "s|^published: false|published: true|g" {} \;'
  end

end

Capistrano

I’ve used Capistrano on several projects in the past, and was very keen to use it again.

Capistrano is an open source tool for running scripts on multiple servers; its main use is deploying web applications. It automates the process of making a new version of an application available on one or more web servers, including supporting tasks such as changing databases.

Again, Capistrano was very easy to get going with Jekyll. I had to write a simple deploy.rb script to push the site to production :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
require 'capistrano/ext/multistage'
set :stages, %w(production)
set :default_stage, "production"

set :application, "recursive-design"
set :domain, "#{application}.com"

f = "config/passwords.yml"
unless File.exists?(f)
  abort "Couldn't find config/passwords.yml"
end
set :passwords, YAML::load(File.open(f))

set :deploy_via, :copy
set :repository, "_site"
set :scm, :none
set :copy_compression, :gzip

set :use_sudo, false

namespace :deploy do

  desc <<-DESC
  A macro-task that updates the code and fixes the symlink.
  DESC
  task :default do
    transaction do
      compile
      update_code
      symlink
    end
  end

  task :update_code, :except => { :no_release => true } do
    on_rollback { run "rm -rf #{release_path}; true" }
    strategy.deploy!
  end

  desc "Compile the site and CSS. "
  task :compile do
    system "rake dev:off"
    system "rake jekyll:compile"
  end

end

… and a supporting production.rb file :

1
2
3
4
server "#{domain}", :app, :web, :db, :primary => true

set :user, passwords['production']['user']
set :deploy_to, "/var/www/#{domain}"

… as well as a passwords.yml containing login information for the production server.

Once Capsitrano and Rake are set up, deployment is as simple as doing a

1
$ rake deploy:prod

This cleans out all the old build products, rebuilds the site and associated CSS, grabs all my projects from Git, builds pages for them and adds a link to the latest zipped-up version, and pushes everything to the production server.

Disqus

Since Jekyll only generates static HTML, there is no support for comments. Luckily Disqus offers a great (free!) service to provide comments to your site via embedded JavaScript.

My only gripe with the service is that it has proved impossible to import all the comments from the old WordPress site into Disqus - I’ve tried their WordPress plugin, a direct upload of the XML exported by WordPress, as well as a site crawl, and nothing seems to have worked. I haven’t gotten around to contacting them about this yet, so possibly there’s a simple way to do it that I’m missing. For new content though, Disqus works great.

Feedburner

Once again I’m using FeedBurner to serve the RSS feed - it gives some nice stats, and looks a little better than a plain feed. Again, this was fairly straightforward to get running with Jekyll - I posted a how-to several weeks ago laying out how to get it all going.

So what’s the verdict?

With services like Disqus appearing, pure-static sites are now a viable option for blogging. I love being able to write in a regular text editor instead of the WordPress WYSIWYG editor, and love the safety-net that keeping everything in Git provides. Jekyll is extremely light-weight and pluggable - I don’t think getting Compass and Pygments going with WordPress would have been quite as straightforward.

Re-building the site (and researching the various options beforehand) really drove home to me how many great, open-source projects there are these days - the fact that I could just plug in all these disparate pieces to build a site in a weekend was a pleasant surprise.