Posted: Tue, 19 July 2011
When I [recently switched my
blog](/~mpalmer/blog/2011/07/01/metablogging.html) over to
[Jekyll](https://github.com/mojombo/jekyll) as my blog/site generation
platform, one of the driving forces was implementing comments. I've been a
comment-free blogger for years, but I've just decided to change my opinions
on things and see what happens. (Turns out: you get some cool comments.
And a *lot* of spam.)
However, the standard advice when it comes to handling comments with Jekyll
"cloud" commenting service). Not being one to stand for the conventional
wisdom, and given that I'm allergic to "the cloud", I decided to go a
different way -- an [all-static comment handling system for
First off, you need a way to render comments inside Jekyll. This was
disturbingly easy with Jekyll's plugin system. With around 30 lines of
Ruby, it was done. It simply reads a pile of YAML files from a `_comments`
directory, and adds them to the individual blog post objects in the
templating system, which can then be iterated over when rendering a post.
Obviously, you need to also adjust your blog post templates to suit. This
is fairly straightforward; just render each of `page.comments` in a list.
Adding a comment submission form is also necessary, and similarly trivial.
The only "moving part" in this whole system is the bit of code that handles
comment form submissions. The simplest way to handle it, which is what I've
gone with, is a few lines of PHP that writes the contents of the form out as
YAML and e-mails it to me. Although I'm not a fan of PHP for web
applications, this is sort of job is where PHP excels -- it's ubiquitous,
trivial to deploy, and easy to understand (in small doses). Using a CGI or
anything larger (like, say, a sinatra app) would be massive overkill.
Since I'm still a control freak at heart, I'm hand-moderating all comments
by the simple expedient of having all blog comments e-mailed to
me[^comment-email], and I have to import them into the blog and re-upload.
Mutt makes this trivial; I've got a script that I trigger by pressing 'C'
(for comment) that pipes the message to `formail` to strip the RFC2822
header, then drops the rest into my blog's `_comments` directory. A quick
`rake upload` and they're published.
[^comment-email]: A side-bonus of running all my blog comments through my
e-mail is that all of the comment spam gets handled through my existing
spam filter, so there's no new complexities. The stuff that bogofilter
is *really* sure is spam just goes straight to `/dev/null`, while the
slightly-less-sure stuff goes into an IMAP folder I ignore except when
I'm extra-super-bored. Interestingly, bogofilter was already
pre-trained and ready to go on my blog spam -- it caught most of the
spam straight away, with no additional training from me, and after being
trained on two examples, it's now going great guns auto-flushing the one
persistent spammer who hammers one particular old post a couple of times
a day with link farms.
If you're not as obsessive as me about hand-moderating your comments, it
wouldn't be hard to write a slightly different PHP script that commits the
comment directly to a git repo[^comment-antispam] and re-renders the site.
All you'd have to do when you wanted to make a new post is merge those new
comment commits from the "live" git repo and go to work. This would then be
a completely static site (with all the performance benefits that implies)
with immediate-gratification comments.
[^comment-antispam]: I'd strongly recommend having some sort of anti-spam setup
before you blindly render the comments onto your site, lest your
comments list looks like complete balls within a matter of days.
So, if you're suspicious of the cloud, or just want to be the cool kid whose
blog comments load even when people have turned cookies off, check out my
[Jekyll static comments