Moving to Hugo

As we've previously established there are a lot of static site generators. Some are more popular than others, and Hugo happens to be among the more popular ones.

Because fiddling with the tools you use to write a blog always captures more of my interest than actually writing a blog, I have recently moved from Lektor—the static site generator that my website was previously based on—to Hugo.

Okay, maybe that's not entirely true—I had a number of reasons to move from Lektor.

The whys

Lektor is a fine static site generator. It fit the approach that I wanted to take very well, which is why I selected it in the first place. It is, however, not the most popular static site generator around.

As I continued to use Lektor, I ended up running into limitations which would have to be hacked around. Some of these are inherent in the design, and would require larger rewrites to eliminate; some were bugs which could be patched, but were not yet in a release, or not merged at all.

I would not wish to assign blame to the individual maintainers of Lektor here—I'm not a fan of describing contributor–maintainer relationships in adversarial terms. However, the fact that Hugo is the more popular of the two pieces of software works in its favor here—it ends up better maintained, and thus more polished.

Differences

Lektor makes few assumptions about what a static site should be. To use it, you define some models (think classes), and build some templates to display instances of those models. Lektor does not even make the assumption that a model should have a main body field with text—you'll have to define one yourself if you need it. You could think of this as the statically-typed approach to static site generation.

Hugo, on the other hand, is far more of a blog CMS. It makes the assumption that things are either single pages, or parts of series, and that they all have a main text body, plus some possible extra metadata. There aren't any models or types to define, and Hugo will generally infer what a thing is based on its path. It's an approach more akin to dynamic typing.

There are advantages to either approach: Lektor's way forces you to actually define what a blog is before you can start writing one, but it allows for more flexibility if you want to customize the structure of your site. Hugo's way is very good for letting you get a blog going with very little configuration, and while Hugo allows for some flexibility, doing things out of the ordinary can get complicated.

Porting

Despite the differences, porting my site from Lektor to Hugo did not turn out to be that difficult. My site was, after all, already mostly a blog plus some static pages.

The content itself was already in Markdown, so it was just the matter of rewriting the front matter (metadata) of individual articles to something parsable by Hugo. The extended builds of Hugo have SASS built in, which made processing stylesheets even easier than with Lektor. Hugo doesn't need models defined ahead of time, so the one thing left was the templates.

Hugo uses Go's templates, and it's roughly what you would expect from a modern double-braces template system. While at times it feels less streamlined than Jinja (the template engine used by Lektor), it isn't terribly difficult to get used to. It has your usual reusable blocks which can be fed parameters, helpful functions for sanitizing input, and such. The un-streamlined parts manifest in places like defining dictionaries, or in the sometimes unclear error reports concerning your templates. Other than that it did not take me particularly long to get used to the templating system.

Odds and ends

Hugo works with a set of assumptions, and since I already had a site built on a slightly different set of assumptions, I would have to figure out ways to get Hugo to work the way I wanted.

For example, I had an Atom feed on my old website, and wanted an Atom feed under the same path with the new site. While I did not expect the IDs to be the same, I wanted the path to remain the same, which may confuse a feed reader a bit, but won't make it report it can't find the feed at all.

Hugo does not support Atom out of the box—it opts for RSS instead. That's okay, though, because there is a plugin. Easy so far.

There was a small problem, though: feeds are expected to be another format in which a listing page can be emitted. As a consequence, they are emitted under a specific path. This path is defined by global configuration—either in your site's global configuration, or the plugin's global configuration. The problem was, my original feed wasn't under index.xml, which Hugo emitted, but under feed.xml. So, to solve this problem I had to define a new output format, tell it that it should emit a feed.xml, and then ask Hugo to output the blog article listing both in HTML, and in my customized output format.

A bit hacky, and perhaps less expressive than Lektor, but workable.

The everyday experience

Of course, the point of static site generators is to make it easy to author content without having to worry about presentation.

Lektor offered an interesting advantage here: its local live preview server came with an editor which could be used to write content in your browser, similar to how it is done with a hosted CMS like Wordpress. Because models are defined ahead of time, the admin UI knows what fields to present for you to fill out. The problem is that I never actually used that feature. I am sure there are some people who appreciate it, but I do not count myself among them.

On the other hand, Hugo offers some other advantages. While Lektor does have shortcode support, it is less smooth than I would want. Lektor shortcodes are defined in an ini file, the definition has to be on one line, and Lektor's Markdown parser does not like Markdown inside explicit HTML elements. By comparison, Hugo shortcodes are a much better experience, which I appreciate—I make frequent use of <figure> elements, for example.

The verdict

Is Hugo a good static site generator? Yes. A lot of people use it successfully in different ways, and it enjoys that popularity for a reason. While its documentation may be a bit intimidating at first, the way Hugo projects work makes sense, and if you're coming from a different static site generator, Hugo should not be too big of a shock.

Hugo fills its niche—that of a static site generator that doesn't focus strictly on blogs—pretty well. While you may not be able to immediately tell if it fills your requirements, it is worth checking out.