My New Hugo Site

  1. Bash
    1. Filters
      1. grep
      2. Sed
      3. jq
    2. Shellspec
  2. Design
  3. Architectural Patterns
    1. Systemd
    2. Message Broker
    3. JSON-RPC
  4. Go
    1. Concurrency
    2. Web Applications
    3. Compound Data
    4. Json
    5. Go vs Erlang
  5. Prolog Cookbook
  6. Documentation
    1. Hugo
      1. Go Html Template
      2. Table of Contents
    2. HTML
    3. CSS
      1. Color
      2. Style Guides
      3. Layout
    4. Mathjax
  7. Visualization
    1. D3
      1. Venn Diagrams
    2. SVG
    3. Visjs
      1. Network
  8. Data
    1. Yaml
    2. Events
      1. JSON-LD
    3. JSON
      1. jCal
    4. SQL
  9. JavaScript

Hugo

Glossary

Page Bundles

Hugo broadly splits all pages into two types:

  1. List which have _index.md content files. These are also called branch bundles.
  2. Single which have index.md content files. These are also called leaf bundles.

Page kinds

The PAGE.Kind method shows any Hugo page to be one of four types:

  1. home (branch)
  2. page (leaf)
  3. section (branch)
  4. taxonomy (branch)
  5. term (branch)

All but “page” are considered branches, making their default template layouts/_default/list.html. Only “page” defaults to layouts/_default/single.html.

A minimalist layouts folder which can serve all 5 kinds is:

layouts
└── _default
    ├── list.html
    └── single.html

To keep things DRY: base templates and blocks

layouts
└── _default
    ├── baseof.html
    ├── list.html
    └── single.html

The above list.html and single.html duplicate the basic HTML5 skeleton which could be moved to baseof.html which would then be used by both of them.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ .Kind }} &mdash; {{ .LinkTitle | safeHTML }}</title>
  </head>
  <body>
  {{ block "main" . }}{{ end }}
  </body>
</html>

For each {{ bock "whatever" . }} there is a corresponding {{ define "whatever" . }}...{{ end }} in the template files.

List Pages

The list template file layout/_default/list.html is the default for numerous Hugo page types.

List pages typically range over the Pages, ie subdirectories, of wherever the _index.md file is located. There are various ways to sort the order in which the pages are listed.

{{ define "main" }}
  <ul>
  {{ range .Pages.ByLinkTitle }}
    <li>
      <a href="{{ .RelPermalink }}">{{ .Date.Format "2006-01-02" }} | {{ .LinkTitle | safeHTML }}</a>
    </li>
  {{ end }}
  </ul>
{{ end }}

Single Pages

{{ define "main" }}
  <h2>{{ .Title | safeHTML }}</h2>
  <div>{{ .Content }}</div>
{{ end }}

Overiding the defaults

Given how long the list for the various page kinds in Hugo’s template lookup order, my suggestion is start at the bottom and work up. If the generic list.html template needs something more specific, then use the second last filename. If a section or taxonony along with its pages or terms needs a more specific template, give it its own subdirectory in the layouts directory.

Taxonomy

layouts
└── _default
    ├── baseof.html
    ├── list.html
    ├── single.html
    └── taxonomy.html
<ul>
  {{ range .Data.Terms.Alphabetical }}
    <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li>
  {{ end }}
</ul>

Term

layouts
└── _default
    ├── baseof.html
    ├── list.html
    ├── single.html
    └── term.html

Hugo will use layouts/_default/term.html if it exists instead of layouts/_default/list.html.

I found it a little confusing that “term” is not a leaf considering from the perspective of a reader of a Hugo website, /section/page/ and /taxonomy/term/ are indistinguishable. With a bit more experience, thinking of term pages as lists made sense since whatever “term” might occur in several pages.

Taxonomy Templates

Regis Philibert

Hugo Data, a series

Each of the blocks in the baseof.html file could have corresponding define stanza in their home, list or single templates. If there isn’t a corresponding stanza, the baseof.html could contain default code to use.

{{ define "name" }}
...
{{ end }}

Home

File names

Historically layouts/index.html, but alternatively layouts/home.html which is handier to avoid confusion with index.html files in content directories. Better yet, layouts/_default/home.html to keep all the templating out of the root layout directory.

Can have separate baseof layouts/_default/home-baseof.html.

Taxonomies

The template can be layouts/_default/terms.html, or confusingly layouts/_default/taxonomy.html

taxonomy.html is the equivalent of single.html, and terms.html the equivalent of list.html. If terms.html is missing, hugo will use list.html. But if taxonomy.html is missing, it won’t default to single.html.

https://github.com/guayom/hugo-taxonomies

Configure Taxonomies

Default without editing hugo.json:

{
   "taxonomies": {
      "category": "categories",
      "tag": "tags"
   }
}

You need to provide both the plural and singular labels for each taxonomy.

So hugo.json edited to create artists and venues taxonomies:

{
  "baseURL": "http://localhost:1313/",
  "languageCode": "en-us",
  "title": "Seatavern v2",
  "buildFuture": true,
  "enableRobotsTXT": true,
  "markup": {
    "defaultMarkdownHandler": "goldmark",
    "renderer": {
      "unsafe": true
    }
  },
  "taxonomies": {
    "venue": "venues",
    "artist": "artists"
  }
}

Taxonomies are lists accessed by .Site.Taxonomies

{{ range $key, $taxonomy := .Site.Taxonomies.featured }}
...
{{{ end }}}

The landing page for a taxonomy is /tags/index.html, similar to a section /section/index.html

Page resources

Content

{{ with .Resources.GetMatch "schema.json" }}
  <<script type="application/ld+json">{{ .Content | safeJS }}</script>
{{ end }}

The content of the resource itself. For most resources, this returns a string with the contents of the file. Use this to create inline resources.

Data

Info from this discourse thread.

{{ $data := .Resources.GetMatch "schema.json" | transform.Unmarshal }}

It is documented at unmarshal a resource.

Frontmatter

It’s optional to include a resources entry in the frontmatter.

{
   "date": "2018-01-25",
   "resources": [
      {
         "name": "schema",
         "src": "images/schema.json"
      }
    ]
}

The resource cant then be loaded from its name instead of path:

{{ with .Resources.GetMatch "schema" }}
  <script type="application/ld+json">{{ .Content | safeJS }}</script>
{{ end }}

Configuration hugo.yaml

Dates

3 Content Types

1. Home

{{ .Page.IsHome }}

2. List

{{ .Page.IsSection }}

3. Single

{{ .Page.IsPage }}

Something frustrating for a newbie is figuring out which template is applied to what content:

jargon template content
home layouts/index.html ./_index.md
——– ——————– ————-

Front Matter

Hugo uses a number of key-value pairs, some of which can be set at the top of content files (eg foo.md), and others such as filename and section are read from disk.

---
title: A new post with the filename old-post.md
slug: "new-post"
---
hugo new site graph
cd graph
hugo new theme mytheme
tree ../graph

graph
├── archetypes
│   └── default.md
├── config.toml
├── content
├── data
├── layouts
├── resources
│   └── _gen
│       ├── assets
│       └── images
├── static
└── themes
    └── mytheme
        ├── archetypes
        │   └── default.md
        ├── layouts
        │   ├── 404.html
        │   ├── _default
        │   │   ├── baseof.html
        │   │   ├── list.html
        │   │   └── single.html
        │   ├── index.html
        │   └── partials
        │       ├── footer.html
        │       ├── header.html
        │       └── head.html
        ├── LICENSE
        ├── static
        │   ├── css
        │   └── js
        └── theme.toml

Note index.html, _default/list.html and _default/single.html are all empty files that need to be created from scratch.

Templates

./themes/mytheme/layouts/_default/baseof.html

<!DOCTYPE html>
<html lang="en">
{{ partial "head.html" . }}
  <body>
{{ partial "header.html" . }}
    <div id="content">
{{ block "main" . }}
{{ end }}
    </div>
{{ partial "footer.html" . }}
  </body>
</html>

The above is a wrapper for blocks such as {{ block "main" . }} and partials such as themes/mytheme/layouts/_default/head.html

 <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ .Title }}</title>
    <link href="https://fonts.googleapis.com/css?family=Courier+Prime&display=swap" rel="stylesheet">
  </head>

Page kinds

  1. Home (layouts/index.html)
  2. List (layouts/_default/list.html)
  3. Single (layouts/_default/single.html)

themes/mytheme/layouts/index.html

This looks for its content in ./content/_index.md

{{ define "main" }}
    <main aria-role="main">
      <header class="homepage-header">
        <h1>{{.Title}}</h1>
        {{ with .Params.subtitle }}
        <span class="subtitle">{{.}}</span>
        {{ end }}
      </header>
      <div class="homepage-content">
        <!-- Note that the content for index.html, as a sort of list page, will pull from content/_index.md -->
        {{.Content}}
      </div>
      <div>
        {{ range first 10 .Site.RegularPages }}
            {{ .Render "summary"}}
        {{ end }}
      </div>
    </main>
{{ end }}

Useless Use of IsSet Award

I cluttered my partials with code like

{{- if isset . "addressCountry" }}
    <meta itemprop="addressCountry" content="{{ .addressCountry }}" >
{{- end }}

before realising

This could be simplified to

{{- if .addressCountry }}
    <meta itemprop="addressCountry" content="{{ .addressCountry }}" >
{{- end }}

or better yet

    <meta itemprop="addressCountry" content="{{ .addressCountry }}" >