Peter Chng

Hugo: First Impressions

I recently switched from using WordPress as the basis for my site/blog to Hugo, a static-site generator. Overall, it meets my needs, and it appears to be flexible enough should I wish to make the site any more complicated. (Which isn’t likely, since one of my objectives was to move to a light-weight platform not requiring so much overhead/thought/maintenance)

However, I did find the learning curve to be a little steeper than expected, and some of the documentation to be ambiguous. These are some of my first impressions related to that.

Things I liked

First, a warning: I have no experience with other static-site generators (SSGs). My selection process was basically this:

  1. Search for some information about popular SSGs.
  2. Do some “comparison shopping” on StaticGen.
  3. Picked Hugo based on the fact that it was fast, and easy to install using homebrew on WSL.

Getting started with Hugo this way was very fast, and I appreciated how quick static site generation was, as well as the speed of the development server, which allows you to preview your content before you actually generate the output and deploy it to your server. (The development server uses a WebSocket connection to automatically signal your browser to reload the page once the server detects any changes)

This “out of box” experience was definitely top-notch, and was one reason I picked it.

Learning Curve

Hugo is definitely more complicated than I expected, however, some of this complexity stems from the flexibility it provides out of the box. It appears to me that Hugo can be used to build a website with almost any structure, though I suspect most people will just be using it for a basic blog like I am.

Because of this flexiblity, understanding how to change/configure things means you will have to understand how Hugo manages content and how that ties together with its templates or themes. Having a decent understanding is necessary should you want to really customize how your website looks. Thus, the flexibility of the content and templating system is both a blessing and a curse.


You’ll probably spend most of your time on customizing/making a theme/template, so picking a proper theme to start from (I don’t recommend building one from scratch, since that would be an even steeper learning curve) is pretty important.

With Hugo, you install new themes just by using git submodule ... to clone theme repo into your overall git repository that encompasses your site. Hugo’s creators have already encouraged this as a standard, and it’s a great way to leverage something like git instead of building their own theme tool.

I suggest first picking a really simple theme, and using that as your starting point for customization. I picked this Blank theme, and found it straightforward enough to understand. I would not recommend going for a more complex theme starting out, unless that theme provides you with exactly what you want and you do not have to customize it. Otherwise, you will be spending a lot of time reading documentation trying to understand what is going on.


The documentation appears to be extensive, but can be ambiguous or unclear at times. Here are a few examples:

Sections vs. Types

For example, within the topic of Content Management, there are two concepts: Sections, and Types. Any piece of content will have both a section and a type, from what I can see. Roughly speaking, these are the definitions:

  • Section: Defined by the file/directory structure. For example, if you have content at ./content/blog/, then that content will have a section value of blog. It is an example of content metadata. This cannot be changed.
  • Type: This is another piece of metadata about the content, however, it can be explicitly set in the “front matter” of content. (Front-Matter is just how you embed metadata in content file like a Markdown .md file, usually at the start of the file)
    • A content file at ./content/blog/some-post will automatically be assigned a type of blog, but this can be overridden by the type set in the front matter of the content.

Despite a clear difference between Section and Type, the two appear to be used interchangeably, even within Hugo’s own documentation, as seen here:

To list the most relevant pages on the front page or similar, you should use the site.Params.mainSections list instead of comparing section names to hard-coded values like “posts” or “post”.

{{ $pages := where site.RegularPages "Type" "in" site.Params.mainSections }}

This example conflates Type and Section, and as a result, a few themes I checked out also did this.

This adherence to types and sections can also cause issues if a theme isn’t setup properly to handle different types. For example, some themes allow you to specify the sections (really the type) to display, (in case you didn’t put your content under ./post but instead under ./blog or similar), but may have inadvertently hard-coded defaults into the template, as seen here

Template naming conventions

One other ambiguity I encountered was regarding templates for types. In the documentation, they mention:

Create a directory with the name of the type in /layouts. For creating these custom layouts, type is always singular; e.g., events => event and posts => post.

However, on the same page and in other examples, we are given examples of putting content under something like posts, which is plural:

Therefore a new file created at content/posts/ will automatically be assigned the type posts

If you follow this example, your content will have a default type of posts (plural), but the layouts will only be applied if the type is post (singular). This was confusing.


Lastly, while Hugo appears to have sensible defaults, they are sometimes not well-documented. For example, site.Params.mainSections is often used by themes to decide which content to show on some “main” page. If it’s not defined in your config.toml, it defaults to the section with the most pages.

Closing Thoughts

Overall, things were more complex than I thought, but a lot of it stems from the extreme flexibility Hugo offers. Comparing to what I remember about setting up and customizing WordPress (albeit back in 2006), it’s roughly on par, though the initial setup/configuration was far easier. However, since I believe that you should Always Be Learning, I didn’t mind having to put in the effort.