Hugo

So, about that Hugo thing.

As I mentioned recently, I’ve rebuilt this blog in Hugo, which was an adventure and a half, and I want to say a few things about how that ended up.

You probably don’t know, both because I never told most people and because you never had a reason to care, that this blog was built with Pelican for years. However, first thing I heard of Hugo, I wanted to try it and maybe switch to it, because one of the major issues with Pelican for me was how it could take a considerable time to rebuild the whole thing, and required its own environment to work. This made it relatively difficult to set up continuous integration on my own server, which is an aging mini-ITX motherboard with the CPU welded onto it, and burdened with lots of other jobs to boot.

So now, years later, I have made the switch, and here are some things I must say in retrospect.

Most of the quirks of Hugo seem to be driven by the collision of two opposing facts:

  • It is written in Golang, which means that it is naturally less flexible than something written in interpreted languages. For that, it’s ridiculously fast – fast enough to render the entire site so quickly, that it makes sense to run it on a live server to rebuild the source tree when changes are detected, and pair it with a separate system to edit the source files in parallel. You can have a dynamic CMS for the price of a static one, if you want.
  • It has acquired a large userbase of non-technical users, driven in a large part by the fact that being a single executable, like most Golang programs, it’s trivial to install. In the scientific writing community, who know their way around the command line because they have to, not because they want to, the pool of users who could deal with Markdown because they do it in R anyway, but had issues installing things onto their system was significant.

As a result, we see a rather monstrous program that tries to do everything involved in creating a static site – up to and including Javascript transpilation, never mind deploying to S3! – which, nevertheless, does not offer much of anything in terms of debugging its internals, or let you run external programs to do something for any reason, because it’s a security risk. Because some idiot could install a theme from somewhere and then it would delete their files.

And you do need to debug the internals, if only because it’s built around Go templates, which are very much an acquired taste, and a template language like no other I’ve encountered. What, would you think, is the difference between .Site, site, and $.Site? All of these point at the same structure, but there’s a need for the three of them because some of them are only accessible in some contexts, but not others.

This is compounded by rather poor documentation, which isn’t offered as a single document, so you have to go online to search in it, and it doesn’t really explain the relationship between all the internal objects in a concise way, you have to dig that out. While the defaults are, in most cases, sensible, going away from them can suddenly turn out to be tricky.

Which means that the skill required to use it as intended is very minimal, while the skill required to make it do something to your exacting specifications can be very high – but at least, with the way how fast it is, turnaround time is negligible, so the process of hammering it into submission is more satisfying than frustrating, when you can do it at all.

For me, the most annoying thing about Hugo that I can’t currently figure out how to fix is the absence of a transliterating slugify function – something that would turn “привет” into “privet”. When writing in Russian, you want to avoid having Cyrillic in URLs, even though you’re technically allowed to, because it comes out as unreadable url-encoded mess when people copy URLs from the browser to paste them elsewhere. For Hugo, there’s no function that will do this, and there’s no way for me to substitute one without compiling my own version, or figuring out how to do this using only the building blocks available as part of Go templates. Which is probably possible. But even if it is, it’s definitely a swimming contest in a Turing tarpit.

At the same time, you can do clever things like sucking in metadata for your pages from JSON files, or exporting an entire database into YAML and having Hugo build pages based on that, and it’s easier than it would be with most other static site generators I can think of. The whole thing is powerful, but skewed.

Would I recommend using Hugo?

If you already have a set of legacy data like a Wordpress blog dump or Jekyll pages, then probably not: Whether you can do what you want – even if it is a thing you believe simple and natural to want, like previous / next links that point to the nearest post in the same category or tag – depends on whether Hugo agrees with you, and it may, surprisingly, not. For no obvious reason. I’m hearing good things about Eleventy, so you might look into that, but hearing good things from the JavaScript crowd is no guarantee of actual usability.

If you don’t have legacy data and have no legacy URL structure to conform to, however, and if you have no specific preconceptions regarding what the files must be named, and which pages must and must not exist, grab someone’s ready made theme and go for it, you’ll have a great time.

I am using Hugo myself, now, and I plan to keep doing so, so there’s that.