Hugo is Good

Hugo’s landing page
Hugo’s homepage.

Hugo is a static site generator program and a mighty good piece of free software. This blog has been mostly powered by hugo since about 4 years ago beginning with version 0.44. Usually, my summary description of hugo is that it’s a blog templating system, but hugo has enough generality and versatility to be called a data templating system.

Lately, I’ve been catching up to some of its newer features, and after revisiting conundrums like the smart quotes edge cases — it’s great to see a lot of interesting details resolved. The Goldmark Markdown CommonMark compliant, the proposition of a highly compatible specification of Markdown. is clean.

If you’re early adopting software, sometimes you’ve got to take a primitive approach to using its interfaces since future changes may catch up to you in It’s difficult to experience big breaking changes with hugo though — the update paths are forgiving. degrees. I’m now on hugo version 0.94.2 and have extricated myself from a myriad of hacks with My premises begin with the notion that all software is unreliable and frustrating. effort. Writing posts in markdown was already easy, but now it’s even easier?

Let’s take a look at features this random blog uses or could use from Hugo’s feature set. In order not to make this too long, my micro blog hugo theme which uses semantic HTML (HyperText Markup Language) explores more of the specific features discussed below.

Markdown

The text file is king. Form separated from content, and content edited from a plurality of user interfaces — graphical or otherwise is hard to beat in my opinion. This article’s single source of truth is a Markdown text file that is transformed. You can At the bottom of each article is a link to the markdown source file. the raw text file that my system transforms to see the underlying markdown format for this article.

Diagrams

If desired, diagrams can be drawn on the fly as an ASCII (American Standard Code for Information Interchange) representation using the GoAT — the Go ASCII tool built into hugo. The ASCII representation is rendered to SVG (Scalable Vector Graphics). You can also shim in the more popular Mermaid diagrams using render code block hooks and JavaScript includes.

Drawing this for the first time was an interesting fiddle and dance with the vim editor. There are tools like ASCIIFlow (repository) that makes this sort of thing quicker, but Emacs in artist mode is probably the Emacs tends to have a lot of peculiar modes. Diff mode is one of my favorites. way.

c o n f i g . t o c r a t m o e s h l n s s e t o e m e u t e c n r s s h o t c / / u n / e i t g f p s m d o i o / a r g s _ g o . t g e / y s e s l a / n / a m h p y l u l o g a u o c t c - e s o i h / n s o _ f - l d i g d e g o e f . o r a j d . u s . p l o m n t n d g p u b l i c t t h h e e d d r r b s s l r s o o a i e i s i n n s n c s s t e e e g t t . e e e o l i . x m l l f e o h m a y y . . n t l p . . h h . m . c c t t h l x o o m m t m m m l l m l / / l p i o m s a t g s e / s h / " " " " " " u p B A A L R S g l a r r i S i o a s t t s S t - c e i i t e i e c c F s h T l l o e M - o e e e f e a g l m d p o d p C C A " " o e l o a r d r a n r t / . t t d i p e e " c n " n l g t e / " C a r d s "
My first attempt at arbitrarily mapping how hugo generates the static parts of my website.

Configuration Formats

Hugo makes use of TOML (Tom’s Obvious Minimal Language), YAML (YAML Ain’t Markup Language), and JSON (JavaScript Object Notation) as configuration formats for itself and its front matter data. YAML is probably the most popular format but hugo favours TOML is my favorite. .

In the front matter, TOML uses +++ delimiters, YAML, --- delimiters, and JSON {} delimiters. The typical hugo configuration can configure many options, and you can add pretty much anything to the config.toml, config.yaml, or config.json file.

yaml
---
baseURL:
theme: base
title: Base
languageCode: en-us

author:
  name: Opulene

menu:
  main:
  - name: Home
    url: /
    weight: 1
  - name: Data
    url: /data/
    weight: 2
  - name: Tags
    url: /tags/
    weight: 3
  - name: Archives
    url: /archives/
    weight: 4
  - name: JSON Feed
    url: /index.json
    weight: 5
  - name: RSS
    url: /rss.xml
    weight: 6

paginate: 1
summaryLength: 20

markup:
  highlight:
    anchorLineNos: true
    codeFences: true
    guessSyntax: true
    lineNos: false
    lineNumbersInTable: false
    noClasses: false
    noHl: false

taxonomies:
  tag: tags

outputFormats:
  html:
    baseName: index
    mediaType: text/html
  json:
    baseName: index
    mediaType: application/json
  rss:
    baseName: rss
    mediaType: application/xml

outputs:
  home:
  - html
  - rss
  - json
  section:
  - html
  - rss
  taxonomy:
  - html
  - rss
  term:
  - html
  - rss
  page:
  - html

By default, hugo sets up logic for tag and category taxonomies but tags are usually good enough for most people. Categories can be hidden with the taxonomies key as seen in the above code block by only showing tags.

Code Fences and Syntax Highlighting

Speaking of code blocks, hugo allows for a lot of flexibility when rendering code syntax highlighting. Hugo uses Chroma for syntax highlighting which is based on the Pygments Python syntax highlighter. Chroma supports a wide variety of languages and you can highlight specific lines.

yaml
---
markup:
  highlight:
    anchorLineNos: true
    codeFences: true
    guessSyntax: true
    lineNos: false
    lineNumbersInTable: false
    noClasses: false
    noHl: false

You can even configure hugo to generate class based tokens on the HTML output and use a separate CSS style sheet to colorize the tokens. No need to pull out the JavaScript hammer for code syntax highlighting.

Short Codes

Shortcodes allow for creating micro templates that are My content uses somewhat wieldly short codes for side notes that are based on a modified version of Dave Liepmann’s Tufte CSS. throughout a markdown text file. Hugo provides a set of built–in shortcodes for popular sites around the web. If you want, you could embed a GitHub Gist with a short code.

Render Hooks

Render hooks let hugo change specific markdown rendering behavior. For example, HTML output for section headings can be changed by altering the markup in layouts/_default/_markup/render-heading.html. This is a handy feature for controlling specific HTML output across the entire layout.

go-html-template
<h{{ .Level }} id="{{ .Anchor | safeURL }}">
  <a
    title="{{ .Text | safeHTML }}"
    href="#{{ .Anchor | safeURL }}">
    {{ .Text | safeHTML }}
  </a>
</h{{ .Level }}>

Output Formats

The custom output format is the most important feature in my opinion. If you take a look at the configuration file above, you’ll see that hugo can be parked onto multiple data types. HTML is not the only format you can work with — it can be anything. For example, it’s not too hard to get a bit barbaric and forge a JSON The proposition of the JSON Feed — a syndication format that is like RSS and Atom. using Hugo’s extension of the go template at layouts/_default/index.json.

go-html-template
{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "{{ .Site.Title }}",
  "home_page_url": "{{ .Site.BaseURL }}",
  "feed_url": "{{ .Site.BaseURL }}/index.json",
  "items": [
    {{- range $index, $data := where .Site.RegularPages ".Params.hidden" "!=" "true" -}}
    {{- if ne $data.Type "json" -}}
    {{- if and $index (gt $index 0) -}},{{- end }}
    {
      "id": "{{ md5 $data.Permalink }}",
      "url": "{{ $data.Permalink }}",
      "title": {{ $data.Summary | htmlUnescape | jsonify }},
      "summary": {{ $data.Summary | htmlUnescape | jsonify }},
      "date_modified": "{{ $data.Date | time.Format "2006-01-02T15:04:05Z" }}",
      "date_published": "{{ $data.PublishDate | time.Format "2006-01-02T15:04:05Z" }}",
      "_metadata": {
        "slug": "{{ $data.Slug }}",
        "type": "{{ $data.Type }}"
      },
      "author": {
        "name": "{{ .Site.Author.name }}"
      },
      "tags": [
        {{- range $tags, $tag := $data.Params.tags -}}
          {{- if $tags -}}
          ,
          {{- end -}}
          "
          {{- $tag | htmlEscape -}}
          "
        {{- end -}}
      ],
      "content_text": {{ $data.Plain | jsonify }},
      "content_html": {{ $data.Content | jsonify }}
    }
    {{- end -}}
    {{ end }}
  ]
}

Now my site now has a JSON Feed outlet that could be useful on the client side.

Headless Content Management

Static site generators in general offer the flexibility of using any administrative or presentation interface as the front end. This decoupling of the front from the back is sometimes called a headless content management system and in the wider marketing sphere, “JAMStack”.

For example, this article can be comfortably edited using the Editing an article in the vim editor. Editing an article in the vim editor. editor or through a Editing an article in the Cockpit CMS dashboard. Editing an article in the Cockpit CMS dashboard. based content management system like Cockpit CMS. If you’re clever enough, you can contort anything to act as your “headless” CMS (even utterly horrific content management systems (CMS) like WordPress) since a headless CMS at its source exposes an extremely flexible API (Application Programming Interface). A lot of headless CMS options are out there.

Conclusion

Hugo is a good static site generator, and has a lot of interesting use cases — hopefully, at some point I’ll take a closer look into hugo modules. Hugo modules tap into the general go module ecosystem, allowing you to mount the contents of modules as file directories or import them for use inside your project. Check out this article on the hugo module system.

30 March 2022 — Written
3 April 2022 — Updated
Thedro Neely — Creator
hugo-is-good.md — Article

More Content

Openring

Web Ring

Comments

References

  1. https://thedroneely.com/git/
  2. https://thedroneely.com/
  3. https://thedroneely.com/posts/
  4. https://thedroneely.com/projects/
  5. https://thedroneely.com/about/
  6. https://thedroneely.com/contact/
  7. https://thedroneely.com/abstracts/
  8. https://ko-fi.com/thedroneely
  9. https://thedroneely.com/tags/hugo/
  10. https://thedroneely.com/posts/hugo-is-good/#isso-thread
  11. https://thedroneely.com/posts/rss.xml
  12. https://thedroneely.com/images/mixing-php-into-hugo.png
  13. https://gohugo.io/
  14. https://www.thedroneely.com/posts/mixing-php-into-hugo/
  15. https://www.maximumethics.dev/blog/2021/03/smart-quotes/
  16. https://github.com/yuin/goldmark#readme
  17. https://commonmark.org/
  18. https://en.wikipedia.org/wiki/Markdown
  19. https://en.wikipedia.org/wiki/Early_adopter
  20. https://harrycresswell.com/writing/breaking-changes-upgrading-hugo/
  21. https://micro.thedroneely.com/m/tags/docs/
  22. https://www.thedroneely.com/git/thedroneely/canory/
  23. https://en.wikipedia.org/wiki/HTML
  24. https://thedroneely.com/posts/hugo-is-good/#markdown
  25. https://en.wikipedia.org/wiki/Text_file
  26. https://www.thedroneely.com/posts/hugo-is-good.md
  27. https://thedroneely.com/posts/hugo-is-good/#diagrams
  28. https://en.wikipedia.org/wiki/ASCII
  29. https://github.com/blampe/goat#readme
  30. https://go.dev/doc/
  31. https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
  32. https://github.com/mermaid-js/mermaid#readme
  33. https://gohugo.io/content-management/diagrams#mermaid-diagrams
  34. https://en.wikipedia.org/wiki/JavaScript
  35. https://www.vim.org/
  36. https://asciiflow.com/#/
  37. https://github.com/lewish/asciiflow#readme
  38. https://www.gnu.org/software/emacs/
  39. https://www.youtube.com/watch?v=cIuX87Xo8Fc
  40. https://www.gnu.org/software/emacs/manual/html_node/emacs/Diff-Mode.html
  41. https://thedroneely.com/posts/hugo-is-good/#configuration-formats
  42. https://toml.io/en/
  43. https://yaml.org/
  44. https://www.json.org/json-en.html
  45. https://gohugo.io/content-management/front-matter/
  46. https://thedroneely.com/posts/hugo-is-good/#code-block-619869a
  47. https://thedroneely.com/posts/hugo-is-good/#code-fences-and-syntax-highlighting
  48. https://github.com/alecthomas/chroma#readme
  49. https://pygments.org/
  50. https://www.python.org/
  51. https://thedroneely.com/posts/hugo-is-good/#code-block-2175c5a
  52. https://github.com/tdro/thedroneely.com/blob/cbf66d935d1952e52ca47997bcadd108257f1cda/public/css/syntax-highlight.css
  53. https://thedroneely.com/posts/hugo-is-good/#short-codes
  54. https://gohugo.io/content-management/shortcodes#use-hugos-built-in-shortcodes
  55. https://edwardtufte.github.io/tufte-css/
  56. https://github.com/gohugoio/hugo/tree/master/tpl/tplimpl/embedded/templates/shortcodes
  57. https://gist.github.com/discover
  58. https://thedroneely.com/posts/hugo-is-good/#render-hooks
  59. https://gohugo.io/templates/render-hooks/
  60. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements
  61. https://thedroneely.com/posts/hugo-is-good/#code-block-d58bb38
  62. https://thedroneely.com/posts/hugo-is-good/#output-formats
  63. https://gohugo.io/templates/output-formats/
  64. https://www.jsonfeed.org/version/1.1/
  65. https://en.wikipedia.org/wiki/RSS
  66. https://en.wikipedia.org/wiki/Atom_%28Web_standard%29
  67. https://godocs.io/github.com/gohugoio/hugo/tpl
  68. https://godocs.io/text/template
  69. https://thedroneely.com/posts/hugo-is-good/#code-block-bdda4ff
  70. https://thedroneely.com/index.json
  71. https://thedroneely.com/posts/hugo-is-good/#headless-content-management
  72. https://en.wikipedia.org/wiki/Headless_content_management_system
  73. https://jamstack.org/
  74. https://thedroneely.com/images/writing-with-vale.png
  75. https://thedroneely.com/images/cockpit-cms-post.png
  76. https://getcockpit.com/
  77. https://github.com/WordPress/wordpress-develop#readme
  78. https://en.wikipedia.org/wiki/API
  79. https://jamstack.org/headless-cms/
  80. https://thedroneely.com/posts/hugo-is-good/#conclusion
  81. https://gohugo.io/hugo-modules/use-modules/
  82. https://go.dev/blog/using-go-modules
  83. https://www.thenewdynamic.com/article/hugo-modules-everything-from-imports-to-create/
  84. https://thedroneely.com/abstracts/the-myth-of-the-rational-voter/
  85. https://thedroneely.com/posts/hugo-is-good/
  86. https://thedroneely.com/abstracts/the-fate-of-empires/
  87. https://git.sr.ht/~sircmpwn/openring
  88. https://drewdevault.com/2022/11/12/In-praise-of-Plan-9.html
  89. https://drewdevault.com/
  90. https://mxb.dev/blog/the-indieweb-for-everyone/
  91. https://mxb.dev/
  92. https://www.taniarascia.com/simplifying-drag-and-drop/
  93. https://www.taniarascia.com/
  94. https://thedroneely.com/posts/hugo-is-good#isso-thread
  95. https://thedroneely.com/posts/hugo-is-good#markdown
  96. https://thedroneely.com/posts/hugo-is-good#diagrams
  97. https://thedroneely.com/posts/hugo-is-good#configuration-formats
  98. https://thedroneely.com/posts/hugo-is-good#code-block-619869a
  99. https://thedroneely.com/posts/hugo-is-good#code-fences-and-syntax-highlighting
  100. https://thedroneely.com/posts/hugo-is-good#code-block-2175c5a
  101. https://thedroneely.com/posts/hugo-is-good#short-codes
  102. https://thedroneely.com/posts/hugo-is-good#render-hooks
  103. https://thedroneely.com/posts/hugo-is-good#code-block-d58bb38
  104. https://thedroneely.com/posts/hugo-is-good#output-formats
  105. https://thedroneely.com/posts/hugo-is-good#code-block-bdda4ff
  106. https://thedroneely.com/posts/hugo-is-good#headless-content-management
  107. https://thedroneely.com/posts/hugo-is-good#conclusion
  108. https://thedroneely.com/posts/webrings-with-openring/
  109. https://thedroneely.com/posts/gitea-in-a-sub-directory-with-nginx/
  110. https://thedroneely.com/archives/tags/
  111. https://thedroneely.com/posts/trying-out-this-website/
  112. https://thedroneely.com/archives/abstracts/
  113. https://thedroneely.com/projects/news-aggregator/
  114. https://drewdevault.com/2022/09/16/Open-source-matters.html
  115. https://mxb.dev/blog/make-free-stuff/
  116. https://thedroneely.com/sitemap.xml
  117. https://thedroneely.com/resume/
  118. https://gitlab.com/tdro
  119. https://github.com/tdro
  120. https://codeberg.org/tdro
  121. https://thedroneely.com/analytics
  122. https://thedroneely.com/posts/hugo-is-good#
  123. https://creativecommons.org/licenses/by-sa/2.0/
  124. https://thedroneely.com/git/thedroneely/thedroneely.com
  125. https://opensource.org/licenses/GPL-3.0
  126. https://www.thedroneely.com/
  127. https://thedroneely.com/posts/hugo-is-good/#