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/.