This article introduces Hugo's template lookup mechanism, which determines which template applies to each page. Three core concepts drive this mechanism: page kind, page type, and the layout manually specified in front matter. Once you understand these core concepts, we'll walk through the full template classification, then explain the complete lookup order. Two examples at the end will tie everything together.
Page Kind
Hugo defines five kinds:
home: the site's home pagepage: a single content page, formerly calledsinglesection: a section list page, formerly calledlisttaxonomy: a list page for all terms under a taxonomy, such as/tags/. Hugo generates this automatically if no content file existsterm: a page for a single term under a taxonomy, such as/tags/hugo/. Hugo generates this automatically if no content file exists
Mapping between the content/ structure and page kind:
content/
├── _index.md # home
├── posts/
│ ├── _index.md # section
│ └── my-post/
│ └── index.md # page
└── tags/
├── _index.md # taxonomy (optional)
└── hugo/
└── index.md # term (optional)Mapping between the layouts/ structure and page kind by default:
layouts/
├── home.html # home
├── section.html # section
├── taxonomy.html # taxonomy
├── term.html # term
└── page.html # pagePage Type
After Hugo determines the page kind, it determines the page type, which decides which set of templates to use within that kind.
For example, pages of the same page kind under content/posts/ and content/movies/ can use different templates through different types:
layouts/
├── movies/
│ ├── page.html # page template for movies
│ └── section.html # section template for movies
├── home.html
├── section.html
├── taxonomy.html
├── term.html
└── page.htmlType defaults to the name of the directory containing the content. For example, content/movies/p1/index.md defaults to type movies. You can also set it explicitly through the type field in front matter:
---
title: 'My Post'
type: 'posts'
---Layout
Beyond kind and type, you can specify a template filename directly through the layout field in front matter:
---
title: 'My Post'
layout: 'custom'
---This maps to:
layouts/
├── custom.html # set by layout: custom
├── home.html
├── section.html
├── taxonomy.html
├── term.html
└── page.htmlThe layout field takes precedence over kind- or type-based resolution.
A simple way to think about the three:
- Page kind identifies the page type, such as a tag list or a regular post.
- Page type further narrows this down, letting different types use different templates.
- Layout is set manually in front matter, suited to standalone pages like about or privacy.
Template Categories
This section introduces the template categories under the layouts directory, including important content such as base templates and page templates.
Base Templates
A base template is baseof.html, the shared outer structure for all page templates. It typically defines common elements such as html, head, and body, keeping the site consistent and easier to maintain.
A base template typically calls the block function, which Hugo replaces with the matching section from a page template when the following conditions are met:
- The page template contains a
defineaction - The page template contains no content that would render directly
If these conditions aren't met, Hugo ignores the base template and renders the page template on its own. Examples of correct and incorrect usage follow:
<!DOCTYPE html>
<html lang="{{ site.Language.Locale }}">
<body>
<main>
{{ block "main" . }}
This content gets replaced by the matching
define "main" action in the page template
that applies this base template.
{{ end }}
</main>
</body>
</html>{{ define "main" }}
This content replaces the block "main" action
in the base template.
{{ template "inlineTemplate" }}
{{ end }}
{{/* Only whitespace and comments are allowed outside define actions */}}
{{ define "inlineTemplate" }}
Inline define is allowed here because it doesn't render directly.
{{ end }}layouts/baseof.html is identical to the correct example, but the page template contains content that would render directly.
{{ define "main" }}
This content can't replace the block, because the line below
contains content that would render directly (<!-- Foo -->).
As a result, the home page doesn't apply baseof.html,
and the template renders blank.
{{ end }}
<!-- Foo -->Page Templates
Page templates map one to one with page kinds. Common page templates include:
layouts/
├── baseof.html
├── page.html # kind: page
├── home.html # kind: home
├── section.html # kind: section
├── taxonomy.html # kind: taxonomy
├── term.html # kind: term
├── single.html # fallback for page
├── list.html # fallback for home / section / taxonomy / term
├── all.html # final fallback for every page template
├── _markup/ # controls how Markdown elements render (render hooks)
├── _shortcodes/ # called from content pages, not a page template
└── _partials/ # reusable sections, not a page templateWhere:
singleis the fallback when nopagetemplate existslistis the fallback when nohome,section,taxonomy, ortermtemplate existsallis the final fallback for every page template
Other Templates
Beyond page templates, Hugo supports the following specialized template types:
- Sitemap: the site map
- RSS: feed content
- robots.txt: crawler rules
- 404: content shown for missing pages
Render Hooks
Render hooks let you customize how Hugo converts specific Markdown elements to HTML, such as customizing the output of images, links, or headings. Render hooks live under _markup/ and support the following types:
The _partials Directory
layouts/_partials holds reusable template fragments, invoked with the partial function. To render layouts/_partials/head.html:
{{ partial "head.html" . }}The first argument is the template name, and the second (.) is the context passed in.
The _shortcodes Directory
layouts/_shortcodes holds templates called from Markdown content, used to insert structured components such as embedded audio, video, or other HTML elements.
View
A view template automatically applies a different template depending on the page, rather than always rendering through one fixed template the way partial does.
View templates render through the .Render method, and follow the same lookup order as other Hugo templates.
Lookup Order
The basic priority order is as follows:
- A
layoutset manually in front matter - A dedicated template for the page kind (home, section, taxonomy, term, page)
- The
singlefallback for page, or thelistfallback for home / section / taxonomy / term all.html, the final fallback
This covers only the basic concepts. Hugo's actual lookup rules go further: filenames can chain multiple conditions with ., and the directory depth of a template also affects priority. Both are covered below.
Chaining Conditions with .
A filename separated by . lets a single template filter on multiple conditions at once, such as language, output format, or page kind. Separate each condition with . in the filename:
home.rss.xml → applies only to RSS output for the home page
section.de.html → applies only to the German section page
baseof.section.de.html → the baseof base template for the German section pageConditions include:
- language: language
- role: role (see Sites Matrix)
- version: version (see Sites Matrix)
- outputformat: (See Output Formats)
- mediatype: media type
- kind: kind
- type: type
- layout: layout
As of v0.161.0, you can also mark these more explicitly, for example home._outputformat_rss_.xml, section._language_de_.html, or baseof._kind_section_._language_de_.html.
Support for each condition varies by template type:
| Template Type | Page Kind | Output Format | Language | Path Distance |
|---|---|---|---|---|
| Base template | Yes | Yes | Yes | Yes |
| Page template | Yes | Yes | Yes | Yes |
| Render hook | ❌ | Yes | Yes | Yes |
| Shortcode | ❌ | Yes | Yes | ❌ |
| Partial | ❌ | ❌ | ❌ | ❌ |
| View | ❌ | ❌ | ❌ | ❌ |
See below for path distance.
Path Distance
The closer a template's path is to the content being rendered, the higher its priority, and path distance takes precedence over filename conditions. Hugo only compares filename conditions when path distance is equal.
For example, given both layouts/movies/page.html and layouts/page.de.html, when rendering a German page under content/movies/, page.de.html matches an additional condition (language), but Hugo still picks movies/page.html, since its path is closer.
Complete Site Example
The following two examples show how every template type covered in this article comes together in a real project.
Simple Site
The most basic site needs only one base template, plus one page template per page kind.
layouts/
├── baseof.html
├── home.html
├── page.html
├── section.html
├── taxonomy.html
├── term.html
├── _markup/
│ └── render-image.html
├── _partials/
│ ├── header.html
│ └── footer.html
└── _shortcodes/
└── audio.htmlComplex Site
A larger site may need dedicated templates and render hooks for specific types or sections, and use view templates to render the same content differently depending on context.
layouts/
├── baseof.html
├── home.html
├── page.html
├── section.html
├── taxonomy.html
├── term.html
├── all.html
├── custom.html
├── movies/
│ ├── page.html
│ ├── _views/
│ │ └── card.html
│ ├── section.html
│ ├── _markup/
│ │ └── render-image.html
│ └── action/
│ ├── page.html
│ └── _markup/
│ └── render-image.html
├── films/
│ ├── _views/
│ │ └── card.html
│ ├── page.html
│ └── section.html
├── _markup/
│ └── render-image.html
├── _partials/
│ ├── header.html
│ └── footer.html
└── _shortcodes/
└── audio.html