Zalgorithm

Go template basics

Hugo uses the Go text/template and html/template packages. The text/template package is for generating textual output. The html/template package is for generating HTML output (safe against code injection).

A rough overview of Go HTML templates

The templates are made up of HTML and actions or template actions. Actions are wrapped in double curly braces: {{ }}.

Taking {{ .LinkTitle | lower }} as an example:

The context or cursor

. (the dot) is the context or cursor. It represents the current data object that’s being worked with.

Methods and fields

LinkTitle is a method that’s associated with a struct that computes or returns something. For example, in Go, the Page struct might look like this (note that the Hugo code is here: https://github.com/gohugoio/hugo):

type Page struct {
    Title string        // Title is a field
    Date  time.Time     // Date is a field
}

The LinkTitle method (is likely) associated with the Page struct. Something like this:

func (p *Page) LinkTitle() string {
    // Does some processing and returns a string
    return processTitle(p.Title)
}

The action might also contain a field. For example, if . is a Page, the Title field might be accessed like this:

{{ .Title }}

The pipe operator

The action {{ .LinkTitle | lower }} contains a pipe. The pipe operator (|) passes the output that’s on the left as an input to what’s on the right.

The use of the term pipeline in the Go template documentation

This has confused me a few times:

{{range pipeline}} T1 {{end}}
 The value of the pipeline must be an array, slice, map, iter.Seq,
 iter.Seq2, integer or channel.

It would probably help to read the docs from the start. I don’t think pipeline is being used in the same sense as the pipe operator. From the docs:

A pipeline is a possibly chained sequence of “commands”. A command is a simple value (argument) or a function or method call, possibly with multiple arguments…

In this context “pipeline” means an expression that produces a value.

The term pipeline also seems to get used to refer to functions that are chained together with the pipe operator.

Functions

In the action {{ .LinkTitle | lower }}, lower is a function. It’s a buit-in Hugo/Go template function that converts text to lowercase.

Variable assignment

A variable assignment example from the Hugo terms.html template:

{{- $page := .page }} {{- $taxonomy := .taxonomy }}
{{- with $page.GetTerms $taxonomy }}
  {{- $label := (index . 0).Parent.LinkTitle }}
  <div class="terms">
    <div>{{ $label }}:</div>
    <ul>
      {{- range . }}
        <li><a href="{{ .RelPermalink }}">{{ .Name }}</a></li>
      {{- end }}
    </ul>
  </div>
{{- end }}

In the code above the := operator is used to assign .page to $page and .taxonomy to $taxonomy.

Is the lack of whitespace between the cursor and methods significant?

The lack of whitespace between . and LinkTitle is not significant. It’s a coding convention.

Whitespace control

Whitespace control is done with hyphens (-) at action boundaries:

{{- .LinkTitle -}}  // trims whitespace before and after
{{- .LinkTitle }}  // trims whitespace before
{{ .LinkTitle -}}  // trims whitespace after

Conditional code execution

Similar to normal code:

{{ if .Title }}
  <p>{{ .Title }}
{{ else }}
  <p>This page doesn't have a title
{{ end }}

The range function

{{- range . }}
  {{ .Name }}
{{- end }}

In the code above, . is the “pipeline” in the technical sense that I referred to above. It’s the expression that produces the collection to range over. The cursor (.) expression is the current context.

References

Go Standard Library Documentation. “text/template.” December 2, 2025. https://pkg.go.dev/text/template.

Go Standard Library Documentation. “html/template.” December 2, 2025. https://pkg.go.dev/html/template.

Hugo Documentation. “Introduction to templating.” November 16, 2025. https://gohugo.io/templates/introduction/.

Tags: