Blogging with Jekyll: Static sites without the hassle
I just switched this website over to use Jekyll, the static website generator.
I’ve tried various approaches to managing my site content over the years. On one end of the scale, which I’ll label “big and heavy”, I used to run a custom content management system in CakePHP that had a MySQL database, an admin panel, user accounts, a WYSIWYG editor and all that stuff. It worked OK but this kind of “big functionality” doesn’t come for free. Making sure your database backups are working properly, migrating your site to a new server if you ever change web hosts, keeping up-to-date with software versions in the hope you don’t get your site compromised, trying to get your WYSIWYG editor to not chew up the formatting on your code snippets; all of these headaches can add up to make it feel like using and maintaining the system is as much effort as actually writing the content.
On the other end of the scale, I recently enjoyed going back to basics and converting my site to plain old static HTML. It’s a great feeling being able to update the site by doing a quick edit, then saving and deploying the changes via Git. No logins, no admin panel interfaces getting in the way, just your favourite text editor and a version control system. But the static HTML approach only really works well for a single-page site. As soon as you try to get multiple pages in there – as I did when I started blogging again – things get laborious. You end up manually duplicating your site header and footer into every page, or having to write the title of your new blog post multiple times: once in the post itself, once in the blog listing page, maybe elsewhere. And then once you’ve duplicated that content you spot the typo that means you have to repeat the process. You probably won’t bother with things like a sitemap.xml
file because that means even more laborious duplication of content, and that’s the way madness lies. I did use a little bit of automation to ease the process, so for example I would write my blog posts in Markdown and I had a couple of mappings set up in Vim to automatically export that to HTML and wrap it in my site’s header and footer. It was far from perfect though, and thought that I as a human was having to process things manually that a computer could be doing is abhorrent.
Jekyll occupies the perfect middle ground between these two extremes. You get the joy of publishing content simply, by editing an HTML file or writing a blog post as a plain text file. But you also know that Jekyll is watching over your work and willing to step in right before things get messy: it compiles your templates and Markdown files into a static site automatically so you never again have to experience the drudgery of maintaining static HTML.
Here are some smart things it does:
- It’s aware of layouts, so you only need to define your site header and footer once and this gets included around each page.
- You can write your posts as plain text files (in the Markdown format) and simply save them to a directory called
_posts
. - It’ll infer sensible things from your posts’ file names, so if you save your blog posts with a naming format like
2014-01-25-test-post.markdown
it will infer a publication date of January 25th 2014 and a title “Test Post”. - It’ll do syntax highlighting for you if you want it to.
- If you reference external content like GitHub gists it will present them in sensible ways.
- You can add plugins to do pretty much anything else you like. I’ve added an XML sitemap generator and an RSS feed generator.
Very quick start
It’s very quick to get going with. As they suggest on the Jekyll homepage:
gem install jekyll
jekyll new awesome-site
cd my-awesome-site
It’s then worth starting the Jekyll server in “auto-regeneration” mode, which will watch your files and recompile the site if anything changes:
jekyll serve --watch
The site should then be accessible at http://localhost:4000.
What’s it doing?
The gist of it is, everything in my-awesome-site
gets bundled into a static website and copied into the _site
directory. To create that static bundle, Jekyll does a few things:
- Copies files over, processing any templating code it finds embedded in the HTML, so for example
Paul Herron, Web Developer
gets replaced with your site name. - Looks in the special folder called
_layouts
for any layouts to wrap your page content in. - Looks in the special folder called
_posts
for any posts in Markdown format. These are your blog posts. Jekyll is quite smart about inferring information from these, so if your post is named something like2014-01-25-test-post.markdown
it’ll infer that the publication date is 25th January 2014 and the title is “Test Post”. - Looks in the special folder called
_plugins
for any plugins you included.
If you’re already maintaining your site as static HTML files, it’s really quick to convert it into a Jekyll site. For example, my old static site had a simple index.html
page with some info about me, followed by a listing of recent blog posts. It was just a matter of dropping that file (and its accompanying CSS and JS files) into the Jekyll directory, and replacing the hardcoded listing of blog posts with something dynamic:
All that information about the blog posts was fetched automatically from the markdown files found in the _posts
directory.
Deploying it
Part of the appeal of using Jekyll is that because you end up with a static HTML site, there’s no need to have any special software running on the server. So to deploy the site you only need to get these static files onto the server. You may already have your Jekyll site under version control with Git, and that makes it easy to pull your updates live.
The way I did this was to edit the .gitignore
file that Jekyll generates automatically, choosing to unignore the _site
directory. I’m happy to commit the compiled site alongside my changes to the overall project.
Making it live is then just a matter of cloning the entire repo onto the server and pointing the server at the _site
directory. In my case on Nginx that looks like:
server {
listen 80;
server_name paulherron.com;
root /home/www/paulherron/_site;
}