Hugo
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.
{{ $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>
{{< 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.
{{ 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.
---
Title: "Feature xyz"
Author: "technicallyawriter"
Description: "Feature xyz is the solution to all your problems. You'll soon forget all your troubles."
---
## 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 }}