Hugo

Hugo logo

Hugo is a fast and powerful plain text static site generator. Don’t let the simplicity of the syntax fool you, though. Hugo has a high ceiling for configuration, since it leverages the Go programming language. This software’s main strengths are its templating and ability to parse content for shortcodes and methods.

And since Hugo is open source, I can experiment with it for free in personal projects, if I choose. This is a huge advantage compared to pricey proprietary tools like Flare.

Plain text

Hugo was my first step away from Flare and into the world of plain text static site generators. With plain text, your source code is much easier to read. This makes aspects of version control, like comparing diffs and merging branches, much less complex.

AsciiDoc woes

My time with Hugo taught me a hard lesson about AsciiDoc support, though. While Hugo supports AsciiDoc, it requires additional configuration to run somewhat smoothly.[1] [2] Your selected theme must also consider AsciiDoc support (most don’t) to take full advantage of CSS rules expecting Markdown.

This ultimately pushed to me try Antora, which natively supports the AsciiDocs syntax.

Shortcodes

Just as the name suggests, shortcodes use quick and clean syntax to refer to more complex functions. This maintains docs readability without sacrificing complexity. A one-line {{< shortcode >}} can run dozens of lines of code behind the scenes. By abstracting away this complexity in a dedicated file, Hugo lets you centralize the management of shortcodes, while keeping them simple to reference and read.

Here’s a standard example of a shortcode. It creates a custom alert depending on alert type.

Dedicated file at layouts/shortcodes/alert.html
{{ $type := .Get "type" | default "note" }}
{{ $content := .Inner | markdownify }}

{{ $titleMap := dict
  "info" "Note:"
  "success" "Success:"
  "warning" "Warning:"
  "danger" "Danger:"
}}

<div class="alert alert-{{ $type }}">
    {{ with index $titleMap $type }}
        <h4>{{ . }}</h4>
    {{ end }}
    <div class="alert-content">
        {{ $content }}
    </div>
</div>
Reference this alert shortcode in Markdown file and specify "type"
{{< alert type="warning" >}}
Warning alert text here.
{{< /alert >}}

Templates

Since Hugo’s templating engine is based on the Go programming language, it’s robust enough to handle complex use cases. For example, see the below code block that uses if and elseif conditional logic to display either a description, summary, or a default, fall-back value if nothing else is set.

Complex conditional logic in Hugo template
{{ if isset .Params "description" }}
    {{ index .Params "description" }}
{{ else if isset .Params "summary" }}
    {{ index .Params "summary" }}
{{ else }}
    {{ .Summary }}
{{ end }}

Flexibility is an asset, and the ability to fine-tune templates to handle a variety of scenarios is an advantage with Hugo. Who wants to manage several different templates when one does the trick?

Front matter

Hugo pages use front matter to set values you can parse and refer to as metadata in a variety of ways. Standard values for front matter are Title, Description, Date, and Author for example. You can further define metadata in front matter however best suits your needs.

Two notable features that make use of front matter are the .GetPage method for content reuse and taxonomies for grouping similar content.

.GetPage method

Reuse content you’ve already written by grabbing it with the .GetPage method in Hugo. For example, say you want to reuse an existing feature description in your release notes. By storing this description in the feature page’s front matter, you only need to maintain it there. You can reference it in the release notes as a parameter.

Feature xyz’s front matter defined on feature page
---
Title: "Feature xyz"
Author: "technicallyawriter"
Description: "Feature xyz is the solution to all your problems. You'll soon forget all your troubles."
---
Reuse existing description for release notes
## Feature XYZ

{{ with .Site.GetPage "/feature-xyz/_index.md" }}
    {{ with .Params.description }}
        <p class="feature-description">{{ . }}</p>
    {{ end }}
{{ end }}

<!-- Rest of the release notes content -->

Taxonomies

Group similar content with taxonomies like "tags." Hugo automatically generates a page at /tags/<tag-name>/ for each tag you define. Setup a workflow where users can explore tags by completing the following steps.

First, define a "tags" taxonomy in your hugo.toml file like so:

taxonomies
  tag: "tags"

Then, add whatever tags you’d like to a content page, for example "best practice."

---
Title: "Feature xyz"
Author: "technicallyawriter"
Description: "Feature xyz is the solution to all your problems. You'll soon forget all your troubles."
Tags: "best practice"
---

Finally, update your page template to display a page’s tags. If a user clicks the "best practice" tag, they’re redirected to /tags/best-practice/ which lists all pages with this tag assigned in the front matter.

{{ with .Params.tags }}
    <p>Tags: {{ range . }}<a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}">{{ . }}</a> {{ end }}</p>
{{ end }}