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 Link to this heading
Page Kind maps directly onto the concepts covered in Content Structure:
home: the site's home pagepage: a single content page, formerly calledsinglesection: a section's list page, formerly calledlisttaxonomy: the list page for every term under a given taxonomy, for example/tags/term: the page for a single term under a taxonomy
Here's how the content/ directory structure maps to each page kind:
content
├── _index.md # Maps to layouts/home.html
├── docs
│ ├── _index.md # Maps to layouts/section.html
│ └── p1.md # Maps to layouts/page.html
│
└── tags
├── _index.md # Maps to layouts/taxonomy.html
└── my-tag.md # Maps to layouts/term.htmlPage Type Link to this heading
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 Link to this heading
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 Link to this heading
This section introduces the template categories under the layouts directory, including important content such as base templates and page templates.
layouts Directory Overview
Link to this heading
The layouts/ directory holds the templates that render your site. Here's the overall structure:
layouts/
├── baseof.html # Base template
├── 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/ # Configures how Markdown elements render (render hooks)
├── _shortcodes/ # Called from content pages, not a page template
└── _partials/ # Reusable fragments, not a page templateThis section covers everything inside layouts/.
Base Templates Link to this heading
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 (external link) 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 Link to this heading
Page templates map directly to each page kind:
layouts/home.htmllayouts/page.htmllayouts/section.htmllayouts/taxonomy.htmllayouts/term.html
Along with these fallbacks:
layouts/single.htmlis the fallback forpage.layouts/list.htmlis the fallback forhome,section,taxonomy, andterm.layouts/all.htmlis the fallback for every page template.
Other Templates Link to this heading
Beyond page templates, Hugo supports the following specialized template types:
- Sitemap (external link): the site map
- RSS (external link): feed content
- robots.txt (external link): crawler rules
- 404 (external link): content shown for missing pages
Render Hooks Link to this heading
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:
- Blockquote (external link)
- Code block (external link)
- Heading (external link)
- Image (external link)
- Link (external link)
- Passthrough (external link)
- Table (external link)
The _partials Directory
Link to this heading
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 argument . is the context passed in.
The _shortcodes Directory
Link to this heading
layouts/_shortcodes holds templates called from Markdown content, used to insert structured components such as embedded audio, video, or other HTML elements.
View Link to this heading
A view (external link) 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 Link to this heading
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 .
Link to this heading
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:
# Section page, German only
section.de.html
# Home page JSON output, German, v2.0.0 only
home.de._version_v2.0.0_.jsonThe available conditions are:
- language: language
- role: role (see Sites Matrix)
- version: version (see Sites Matrix)
- outputformat: (See Output Formats)
- mediatype: media type (external link)
- kind: kind
- type: type
- layout: layout
As of v0.161.0 (external link), you can also mark these more explicitly, for example home._outputformat_rss_.xml, section._language_de_.html, or baseof._kind_section_._language_de_.html.
Path Distance Link to this heading
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.
Support Overview Link to this heading
Support for the advanced lookup order varies by template type. The table below summarizes this:
| 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 | ❌ | ❌ | ❌ | Not applicable |
Complete Site Example Link to this heading
The following two examples show how every template type covered in this article comes together in a real project.
Simple Site Link to this heading
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 Link to this heading
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