Hugo: Afterthoughts

Having managed to produce this site using the Hugo static site generator, it’s time to reflect and collect my impressions.

Part 6: Closing Thoughts — The Good, the Bad, the Rest

This is the extent to which I have researched Hugo, in order to feel comfortable applying it to my problems. I’m sure there is more — but that’s all I needed, and therefore all I know. (And even that is most likely not entirely accurate.) Should I ever need to learn more, I may add to this write-up.

It’s time to take inventory of my impressions of working with Hugo so far: the Good, the Bad, and All That.

The (Mostly) Good…

  • I like the idea of a “static website”, although it does take a little getting used to that there is no URL rewriting at runtime. The inability to respond to user input is, of course, a fundamental limitation, which is more painful than I had anticipated. (Very few sites are really, truly, completely static!)

  • I like the idea of writing content in flat text files, using a lightweight data format, but I am not convinced about Markdown. It’s never good if the input format is fundamentally less expressive than the intended output — the mere existence of short codes (a blatantly hackish workaround) or the (even more hackhish) technique of embedding “pass-through” HTML demonstrate Markdown’s inadequacy. Moreover, in the present case, there are two output formats: HTML and LaTeX (at least for someone like me who needs MathJax), requiring even more hackish (and probably brittle) workarounds. I think the ultimate realization is that a contemporary web experience, including color and layout, not to mention MathJax, requires a different, more expressive input format.

  • I like the clear separation of content and presentation: content is kept as Markdown, presentation is (almost entirely) left to templates. No lock-in: it should be fairly easy to take the content to another platform if necessary or desired.

  • I like the “cascade” in the template lookup: to customize a theme, I don’t need to touch the original files, but can simply override them in the project’s theme directory. I also appreciate how this decouples any customizations from upgrades to the original theme (at least in principle).

  • I like the built-in support for metadata: tag collections, sitemaps, and so on. It’s too bad that they only exist as internal data structures, and are not written to file (where they would be available for use by external add-on tools).

  • I actually like the frontmatter, and the ability to add configuration details right in the content itself, without the need to touch a separate configuration file. The downside is that configuration details are potentially scattered around widely. I try to limit the use of frontmatter only to configurations specific to the piece of content they are part of, and put global settings into the global configuration file. (A mechanism for directory-level configuration files, like Apache’s .htaccess, would be a nice-to-have.)

  • I like the built-in development server, and the live-reload functionality, but neither is essential. A nice-to-have.

  • I like that (once the entire set-up and configuration is complete!) adding content is indeed very, very simple.

  • Finally, Hugo often gets credit for being fast: that doesn’t matter to a small site (like mine) with a few dozen pages, but I can see that it’s nice for a larger installation. Even for a small site, it’s nice that rebuilds are essentially instantaneous.

The (Mostly) Bad…

  • Hugo is too difficult to understand. The amount of time I spent to get even to my current, limited level of understanding is nowhere short of ridiculous. Given what Hugo tries to accomplish, it is too complex; and the documentation, although extensive, is fragmented, and does little to help a mere user make sense of Hugo.

  • Hugo’s reliance on opaque rules and implicit conventions makes it very difficult to understand and predict its behavior. This is where the documentation’s lack of a comprehensive, conceptual overview is most painfully felt.

  • Hugo relies on implicit rules and conventions in an attempt to dispense with the need for explicit configuration. Unfortunately, understanding and manipulating all the implied rules and conventions causes more pain (and more uncertainty) than some reasonable amount of explicit configuration would. Moreover, I find that the explicit configuration keeps sneaking in by the back door: No piece of content without frontmatter! At that point, I could dispense with all the opaque black magic around conventions and rules, and instead rely on minimal, but explicit configuration to begin with.

  • The “list-and-page” metaphor seems too restrictive for general applications. It does not allow to combine two or more pieces of content on the same page, making it impossible, for example, to create contemporary, rich portal page. (Also notice how many of the themes look alike: austere personal web pages with a text-centric blog. How much complexity would really be required to support just that?)

  • Hugo provides few creature comforts. The tooling is rudimentary. Some of the out-of-the-box defaults (such as the draft: true default archetype) help neither the beginner nor the advanced user. The absence of a built-in theme that is guaranteed available and guaranteed compatible is particularly painful.

  • The absence of diagnostics deserves a separate, dishonorable mention. If things don’t go as planned (which, because of all the implied rules, happens a lot — in particular in the beginning), there is no way of finding out what’s wrong. In particular, it should be possible to receive a warning whenever Hugo decides to ignore certain files in the source tree, rather than just discarding them silently.

  • I am ambivalent regarding the choice of Go (Golang) as implementation language. Its main advantage (for this project) is the high execution speed, which is indeed nice, and a little bit the sense that it is all more than just “a bunch of scripts”. On the downside stands the extreme closedness of the application binary, both with respect to runtime inspection as well as extensibility. By design, Go does not offer a plugin or extension mechanism. (This has changed, very recently.) Runtime integration of Go tools is supposed to occur via HTTP: fine for server applications, but inconvenient for a desktop app. One consequence seems to be that a lot of logic moves into the templates, because they provide a user-space method to add behavior. But as probably many people who have worked with template engines will agree, that’s not a good place for application logic! (And that’s not even mentioning Go’s strange add-on language for template logic, with its mixture of Lisp and Unix pipeline syntax.)

  • I worry how safe it will be to rely on Hugo in the long run. Hugo has already seen a number of false starts and feature set changes. It depends on a large number of external libraries (close to 100). Finally, running Hugo requires a theme, with its own set of updates (or lack thereof). There seems to be lots of potential for either surreptitious or catastrophic version skews, incompatibilities, or other behavior changes. Given the history and state of the project, I am not confident that the Hugo project will isolate or protect the end user effectively from these risks.

In Conclusion

I am glad my site is up; Hugo has been helpful in getting me there.

But I feel that it required too much, in fact way too much effort for what should have been a relatively simple exercise. At this point, I’ve made the investment, and I hence will stick with it for a while, but I can’t help thinking that there has got to be an easier way!