I’ve been using WordPress since 2011. It works well enough, but for me there are a few drawbacks.
It’s slow. It takes time to do anything from creating a post to previewing to deploying it. I prefer to edit text in a proper text editor, with the full array of keyboard shortcuts, so I usually end up copying and pasting anyways. But using the UI to do everything is cumbersome. Of course I could install a local instance of WordPress so I can preview locally. However, I would have to deploy everything, posts and images, every time. This seems inefficient for just adding a new post.
It’s hard to backup. I could export the WordPress content as an XML file, but this is only useful to WordPress. For a full manual backup, I would use Control Panel to export the database, then FTP into the site and download the entire WordPress content folder as an archive. This is time-consuming and a far cry from proper version control.
It’s hard to customize. There are probably a dozen plugins for anything I will ever want to do. While I could view and edit the plugin source, without an easy way to test it’s effectively a blackbox. Further, I wouldn’t want to have deal with PHP just to customize a plugin.
So it’s an easy to decision to put WordPress out to pasture. I looked at Jekyll and deploying on Heroku. Jekyll seems like a good choice because it’s used by GitHub, so it’s more likely to be developed and less likely to go away. I also checked out Ruhoh, which is created by a Jekyll developer to address some of its shortcomings. I really liked Ruhoh for the customizability, Mustache markup syntax and incremental page generation. I may go back to Ruhoh at some point. I finally settled on Octopress. It adds a theming engine and a host of productivity enhancements to Jekyll as well as beautiful syntax highlighting. It makes it trivially simple to deploy to GitHub Pages.
There are many good articles written about using Octopress. The documentation, for one, is a very good place to start. Here are just some of the issues I ran into along the way.
Importing from WordPress
I used Jekyll’s migration tools, specifically
hpricot to process a WordPress export XML file to generate posts and pages. The process worked quite well, although as expected some manual cleanups were necessary.
Setting up DNS
This is probably a no-brainer for many people, unfortunately I’m not among them. Since my blog is now hosted by GitHub Pages, I had to configure my DNS to point my domain to the new IP address. The process is quite clearly laid out in the documentation. In my case, I had to create an A record for my top-level domain,
yentran.org, to point to
188.8.131.52. I also created a CNAME record for the subdomain
www.yentran.org as an alias which points to the same address. I was concerned that my email address
firstname.lastname@example.org would be broken. It turns not to be the case. Email forwarding relies on a MX record, which continues to point to my ISP’s IP address. There’s also a wildcard record, which catches any unknown subdomain for which there is no matching A or CNAME record.
Previously I used NextGen gallery to manage images. NextGen stores images in separate folders, so it’s simple to copy them (rather than searching for them on my hard drive).
I now use Dropbox’s Public folder to host images. This allows me to easily manage images. In Lightroom (or any other image organizing software), I can export the images directly to Dropbox’s local sync folder and the images immediately becomes available for linking. If I want to modify images—such as resizing them—I can work directly with the Dropbox sync folder without having to make changes to the site.
I used Lightbox 2 jQuery plugin to display an image gallery. However, it doesn’t work with hotlinked images. I decided to roll my own.
I wrote a small Ruby + Thor utility to generate the necessary markup for images based on the Dropbox folder and append it to posts. Thor is awesome.
Blogging with Octopress
Everytime you add or modify a post or page, Jekyll regenerates the entire site. This is so that it can properly update the site metadata. However, this can take a long time, particularly if you have many posts and pages. Octopress provides a useful optimization tool. Type
rake isolate["post name"] moves all other posts except the specified post into a _stash folder, so that regeneration is significantly faster. Once you’re done, type
rake integrate to move the other posts back; just don’t forget to do this before deploying.
Octopress doesn’t provide an out-of-the-box way to display categories, but this can be easily done. I want display them as an aside (Octopress-speak for a sidebar plugin or partial). I based mine on Octostrap3’s Category List aside.
1 2 3 4 5 6 7 8 9 10 11
Each category in the
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Here’s the CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
On my travel pages, I want to have a hierarchy of links to different destinations:
USA Arizona Grand Canyon National Park Florida Cape Canaveral
It should be set up so that if I add a new destination, I wouldn’t have to hunt down all the pages containing the links in order add a new one. Luckily, with Jekyll all of the site’s metadata is stored in a single YAML file and accessible through the
site variable. In order to capture the navigation hierarchy, I added the following to
travel: usa: - name: "Arizona" url: az places: - name: "Grand Canyon National Park" url: grand-canyon-national-park - name: "Florida" url: fl places: - name: "Cape Canaveral" url: cape-canaveral
YAML is a really compact, highly readable format. In the block above, indentation denotes nesting,
: denotes a key-value pair and
- denotes a collection. The parser turns the above YAML into the following hash:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
After making modifications to
_config.yml, I could quickly examine them by firing up the interactive Ruby shell,
irb, then typing the following:
I can access the navigation metadata as follows:
site["travel"]returns a hash containing country objects
site["travel"]["usa"]returns an array of state objects
site["travel"]["usa"]returns the first element of the array, which is Arizona
site["travel"]["usa"]["name"]returns the text “Arizona” and
site["travel"]["usa"]["url"]the corresponding URL
site["travel"]["usa"]["places"]returns an array of locations in Arizona
site["travel"]["usa"]["places"]returns the object for Grand Canyon National Park, and so on
Jekyll makes it even nicer to work with the hash by turning keys into instance methods. So instead of writing
site["travel"]["usa"]["places"], I could also write
In order to generate the following HTML for the navigation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
I used the following Liquid code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Now if I want to add another destination, I’d only have to modify the YAML.
Octopress/Jekyll makes it easy and fun to tweak, hack and do so efficiently. I only wish I’d made the switch earlier!