Skip to main content

Introduction

View SourceEdit this page (external link)

This article assumes you already have a basic understanding of programming languages, so it won't introduce programming concepts from scratch. Instead, it builds on that foundation to introduce Hugo's syntax.

The examples in this article are based on a basic sample site, initialized with the following commands:

hugo new project my-site --format yaml
cd my-site
hugo new theme test
echo "theme: [\"test\"]" >> hugo.yaml

hugo new theme test creates a theme skeleton at themes/test/. You'll make your theme changes in this folder.

Understanding the Project Structure Link to this heading

See Project Structure for everything outside the layouts directory, and Template System for what goes inside it.

Parallel Rendering Link to this heading

Hugo renders multiple pages at the same time. Keep this in mind so you don't end up writing code with race conditions. You won't run into this issue often, but it's important enough to call out early.

Your First Template Link to this heading

layouts/home.html:

layouts/home.html
{{ $v1 := 3 }}
{{ $v2 := 4 }}
<p>{{ add $v1 $v2 }}</p>
<p>7</p>

Everything inside {{ }} gets evaluated. Everything outside it is output as-is.

Variables Link to this heading

layouts/home.html
{{ $price := 100 }}
{{ $price = 120 }}
{{ $price = "On sale" }}
{{ $price }}
On sale

Use := to declare a variable and = to assign a new value. You can reassign the same variable multiple times, and even change its type along the way. Here, $price goes from a number to a string.

Functions Link to this heading

layouts/home.html
{{ add 1 2 3 }}
{{ strings.ToLower "HUGO" }}
6
hugo

Functions have no connection to objects. They're stateless: given the same arguments, a function always returns the same result, no matter which template calls it.

Context Link to this heading

Context represents "the content at your current position." For example, in the base template baseof.html:

{{ . }}

This prints the current page's filename. From there, each template determines what information it receives based on the context passed to it. You'll see calls like this in baseof.html:

{{ partial "head.html" . }}

This passes the current page (.) as context into the head.html template.

Similarly, {{ block "main" . }}{{ end }} passes the current page (.) into a layout block named "main". That block is defined with {{ define "main" }} in the page, home, section, term, and taxonomy templates under layouts. In other words, the context inside {{ define "main" }} in each of these five layout templates is also the current page.

Methods Link to this heading

Anything called after a . is a method. It's bound to whatever object the . represents as context, so the same method returns different results depending on the context.

layouts/home.html
<h1>{{ .Site.Title }} / {{ .Title }}</h1>

.Site.Title first calls .Site to get the site object, then calls .Title on that object.

Store the about page as a variable, then call its .Title method:

layouts/home.html
{{ $about := .Site.GetPage "/about" }}
{{ $about.Title }}

Switching Context Link to this heading

layouts/home.html
<h1>{{ .Title }}</h1>

{{ range slice "Apple" "Banana" }}
  {{ . }}<br>
{{ end }}

{{ with "Orange" }}
  {{ . }} / {{ $.Title }}
{{ end }}
<h1>My Site Title</h1>
Apple<br>
Banana<br>
Orange / My Site Title

Inside range and with, . switches to the current element or value. Use $ to access the outermost context of the current template, so $.Title refers to the .Title method on that outermost context, which is the current page's .Title.

Pipes Link to this heading

Without a pipe:

layouts/home.html
{{ strings.ToLower "Hugo" }}
{{ mul 6 (add 2 5) }}

With a pipe, the value on the left passes to the right as the last argument:

layouts/home.html
{{ "Hugo" | strings.ToLower }}
{{ 5 | add 2 | mul 6 }}

Both forms produce the same result:

hugo
42

Comments Link to this heading

Go template comments don't appear in the output:

layouts/home.html
{{/* This won't be output */}}

HTML comments are output as-is in the final HTML:

layouts/home.html
<!-- This will be output to the HTML -->

Trimming Whitespace Link to this heading

layouts/home.html
Start
{{ if true }}
  true
{{ end }}
End

This renders as:

Start

  true

End

Use {{- -}}, or {{- /* */ -}} for comments, to trim whitespace across lines:

layouts/home.html
Start
{{- if true -}}
  {{- print " %s " "true" -}}
{{- end -}}
End

This renders as:

Start true End

Lifecycle Link to this heading

A variable's lifecycle is scoped to the current template, not the entire current page. If you declare a variable inside a context block, it's destroyed once that block ends.

Incorrect:

layouts/home.html
{{ with "foo" }}
  {{ $x := 1 }}
{{ end }}

{{ $x }}

Correct:

layouts/home.html
{{ $x := 0 }}
{{ with "foo" }}
  {{ $x = 1 }}
{{ end }}

{{ $x }}

Accessibility settings

Font size