After 7 years of serving my blog/website with WordPress, I thought it was time to try
something else. One of my biggest gripes about WordPress (apart from having to
hold my breath on each version update) is that writing posts through a web UI
isn't very handy: it's slow, inconvenient for complicated posts (especially if
you're used to your favorite editor), you can't write while offline, and the
versioning is limited (compared to real versioning systems). So, I decided to
give static blog generators a try, and ended up converting my blog to Nanoc
(after a brief stopover at Jekyll). Result: I can now write my posts
in VIM, use Markdown syntax for writing, preview my posts live using tools
such as Marked and MarkdownPad, preview the site using Nanoc's built-in
HTTP server, easily customize my site with some Ruby code, and keep everything
versioned with Git. And of course move it on Amazon S3 in case my
blog really hits off and starts getting million hits a minute (which should be any
In case you're interested in the details of how I converted from WordPress to Nanoc
(including code), read on.
Before settling on Nanoc, I first gave Jekyll a try. However, Jekyll always had a very
ad-hoc feel to it, with filled with decisions that didn't always work for me, and lots of
untransparent magic going on behind the screen, which also didn't always work for me. Nanoc
is a lot cleaner, powerful, more extensible, and easier to understand what's going on.
Luckily, the post format of Jekyll is compatible with Nanoc,
so the steps for migrating directly from WordPress to Nanoc should be the same.
Here's roughly what I did:
- First of all, I got the posts out of the WordPress database using
Vito Botta's WordPress-to-Jekyll script (with some minor changes). This script pulls out
the posts as HTML, with metadata prepended as YAML front matter (which is what both Jekyll and Nanoc
use). (See an Example Post)
- Although WordPress posts use HTML for markup, the markup omits
<p> paragraph tags (as they are added
automatically for empty lines), which means rendering them as HTML doesn't look as it's supposed to.
Fortunately, if you treat the HTML files as Markdown (and use RDiscount as your posts filter), the
result ends up as expected: the HTML markup is preserved, but paragraphs have been added in the right places.
- For the layout, I just reused the Twenty Ten theme I was using before. WordPress does
a good job at separating presentation and structure, so I just mimicked the
<div> structure in my
layout files, copied the CSS files unaltered.
- One thing you can't do with a static blog is serve comments, so I moved the comments to
Disqus. Before getting rid of WordPress, I installed the Disqus Plugin to
do a one-time import of all comments. Using the WordPress ID and URL (pulled by the script mentioned
earlier, and put in the YAML front matter of the converted posts), you can reconstruct the right ID for
keeping your comments intact on the new site. (See the Disqus Template)
- In order for the front page to show excerpts instead of full posts, I use a filter
(and a helper) to strip everything
up to the
<!-- more --> tag, put this into a separate nanoc representation, which in turn is
used when populating the paginated blog pages.
- For the tags and categories, I use another helper to generate the list of categories
and tags for each post, and to generate a page for each category/tag containing all the posts
for that tag (and their RSS feeds)
That's it for the basic functionality. Then, there's some sugar coating and extra stuff, such as:
- A tag cloud in the sidebar, using a helper.
- Support for Twitter cards. I added a rule to make a ‘filtered_contents’ snapshot after applying the
Markdown filter, and use this snapshot in the ‘head’ section of the layout, as you can see in
- Embedded my Git repositories using CGit, by splitting up a rendered dummy page (again using a
simple filter), and using these resulting pages as header/footer for CGit. It doesn't look
perfect yet though (diffs are too wide for the layout for example).
- Since the CGit integration isn't perfect yet, I added a filter to rewrite all internal
Git urls to point to my GitHub repositories. If I decide to switch back to my own (or another) public
Git interface, I won't need to touch my posts.
- Embedding image galleries using Galleriffic (although I dropped my galleries recently)
- An update_software task for auto-generating all
my Software project pages from the
README files in the
project Git repositories.
For the nitty gritty details, you can have a look at the code (and some example content)
in my Git repository.
Update (2015-06-14): I changed the theme of my blog again. You can read more about it
here, with some more information about optimizations here.