Adam Caudill

Security Leader, Researcher, Developer, Writer, & Photographer

Five Years with Hugo

A look back at 5 years of experience publishing with Hugo.

During a break over Christmas 2020, I rebuilt this site, moving from WordPress to Hugo. After more than 5 years of publishing with Hugo, I’d like to share what I’ve learned, what’s worked, what hasn’t, and why for once, I’m happy with the platform I’m using.

This review builds on two recent articles, Five Hundred, a retrospective of 500 posts to this site, and Lessons Learned from 20 Years & Why You Should Blog, a look back at 20 years of publishing here, and the value of writing & blogging more generally. In this post, I will be diving into publishing with Hugo specifically, what’s good, what’s not, and what you should think about if you are considering it.

Writing Friction #

In the Lessons Learned post I spoke about the need to carefully consider the friction of the tools you use, as any bit of friction can reduce the motivation and time dedicated to writing. As such, I should address this first and foremost.

In 2012, I moved to Octopress, and away from WordPress, there were a variety of reasons for this, though security and performance were major factors. By the end of 2015, I moved back to WordPress. The reason? Friction. With static state generation, the process of creating a new post was slower, took more time & effort, and as a result, I did so less frequently.

By 2020, I was ready to embrace that friction. When I switched from WordPress to Hugo, I knew that each post would take more time, that I wouldn’t post as often. Yet, this isn’t a flaw for me, it’s a feature.

During the 2010s, I posted here 146 times, with an average length of 817 words. So far, in the 2020s, I’ve posted 52 articles, with an average length of 1,629 words. I post less often, though each sees greater effort and more depth, each is a greater investment to ensure that it’s worth the time to read.

While I will loudly caution people to watch for friction, and warn that it can lead to less motivation to spend limited free time writing, it’s not always a flaw. If you are already going to spend several hours (or more) on an article, the additional friction of using a static generator really does become insignificant.

Hugo works great if you don’t mind the friction; at this point, the friction isn’t a problem for how I write today.

Markdown All The Things #

Hugo supports various formats for content, though the best support is for Markdown, and is what this site uses exclusively. When I switched this site from WordPress to Octopress in 2012, I had manually converted a decade’s worth of content to Markdown from the HTML that WordPress generates. Thankfully, after that all content has been in Markdown.

Even when I switched from Octopress back to WordPress, I took advantage of the fact that WordPress supports Markdown as well. This made later moves much, much easier.

I could explain why you do want to write in Markdown, for a variety of reasons, though Anil Dash recently documented the success of Markdown quite well, as such, you should read his article if you want a deeper dive.

Themes & Design #

Hugo has a rich collection of themes available, many of these are remarkably well designed and impressive contributions from their talented designers. I selected a clean and simple theme, Kiera, and spent a week extending it, expanding the features, redesigning the home page, adding the sidebar, and countless other changes.

Hugo builds on the Go Template system, which allows the themes to be quite robust and flexible, supporting extensive embedded logic. While this doesn’t offer the degree of flexibility that I would truly like – such as having full access to Go1 - it does work well and can do almost anything one would need.

The template files are HTML2, and easy to edit and customise for your particular desires, it’s one of the easier and more pleasant templating systems that I’ve worked with.

Frequent Changes #

The team behind Hugo are constantly working to improve the framework, fix bugs, add features, improve flexibility, and address design constraints. As I write this, on the 10th day of January, there have already been 4 releases this year.

This constant change does come at a price though, as there is a steady stream of new deprecation warnings that are added, signalling the future change or removal of some feature. There are also infrequent but very real breaking changes that slip in, without any clear warning. Over the last 5 years, there’s been at least two of these breaking changes each year, leaving the site broken in some way.

Thankfully, most of these breaking changes have been in less important areas, or places where I’m leveraging functionality that’s very much non-standard (as is my wont to do).

To help detect these issues, I’ve found it to be quite useful to use two different GitHub Actions jobs in the repository that houses this site, one performs a build against the version of Hugo that I’m currently using, and the other builds against the latest version. While this won’t catch all issues, it does surface many issues before they start breaking deployments.

Hosting #

To keep the costs low, avoid maintaining another server, and ensure good performance, I opted to use Cloudflare Pages to host the site. This integrates cleanly with GitHub, it supports preview URLs, including for branches, which is an ideal way to get feedback before publishing, and allows me to write on any device, even without a local build environment, as it’s built on Cloudflare’s servers.

While there are quite a few providers that now offer similar services for static or otherwise edge-deployed sites, at the time Cloudflare offered the best features and the lowest price.

One beauty of Hugo and other static generators is that the site can be hosted anywhere. I intentionally don’t perform any edge compute, so this site could be hosted on a Raspberry Pi if I wanted. This adds great flexibility to move the site should the need arise, without needing to change or rebuild anything.

Easy Extensibility #

One thing I love about Hugo and other static generators, is that I can easily extend the build process to add new functionality that isn’t part of the framework itself. I’ve done this to add automated related content, generating content stats, and others. This allows you to achieve things that would normally require a dynamic website, or even perform more compute-intensive operations that simply couldn’t be performed in real-time in a server.

This allows you to think outside of the box in a way that would be difficult, and build rich and innovative features. It also allows you to extend these custom features without being bound to the framework. An example of this is the fairly simple content stats script mentioned above, which counts simple things like the number of words. Today, that has expanded, and even includes details such as Flesch reading ease score or the hapax legomenon count. It’s evolved, and without needing to touch the framework itself.

What else would I use? #

If I was to rethink my use of Hugo, if I was to switch again, what would I use? After having used many platforms & frameworks, there are a few (and only a few) candidates I’d consider:

  • Ghost - This would be my first choice, and the most likely thing I would move to. It’s very clean, easy to use, minimal friction, and an overall great writing experience.
  • Jekyll - This is a very robust static generator, well designed, and extremely flexible. It has most of the benefits of Hugo, though does have some sharp edges in my experience.
  • WordPress - This is the classic and ubiquitous option, well established, massive collection of themes available, huge plugin ecosystem. While I was once a big fan of WordPress, it has evolved in ways that seem to be more suited being a CRM for more complex sites, and less focused on being a great writing platform3.

There are many, many other options, though most of them I would avoid for one of two reasons:

  • Platform Lock-in – I don’t want my writing to be restricted to a single platform that’s eagerly waiting for the next payment. Of the options here, all can be self-hosted.
  • Writing not a Priority – Any framework or platform used needs to be focused on writing and making it easy and pleasant to actually write. There are dozens of other static generators, but many are too focused on other use cases to be good for writers.

Will I switch again? #

This is a great question, and I’ve no idea. My writing habits may change, my needs may shift again, but for now, Hugo is ideal for my needs.

I’ve become quite a fan of Hugo, built at least a dozen sites using it, and I don’t plan on switching to anything else for the foreseeable future. If you are re-evaluating your writing platform, I would wholeheartedly recommend Hugo.


  1. With the Hugo Modules system, you can bring in the full power of Go, though this does create a more complex build environment. For my uses, I’ve avoided that level of complexity. ↩︎

  2. While the files are HTML, the embedded Go Template code is obviously not standard HTML, and thus unlikely to receive proper syntax highlighting. As the code can be rather complex, this can make reading it somewhat difficult. There is a plugin for VSCode that addresses this, though it’s sadly broken and abandoned; I’ve forked the project to correct the worst issues. ↩︎

  3. For those familiar with the WordPress history, Project Gutenberg represented a substantial shift in focus and approach, and one that I’ve never cared for. It added undue complexity to the writing experience, which, with the complexity that has grown over the years as it’s evolved into a more general purpose CRM, makes it less and less fit for a dedicated writing platform. ↩︎

Adam Caudill


Related Posts