---
title: New template system in Hugo v0.146.0
linktitle: New template system
description: Overview of the new template system in Hugo v0.146.0.
categories: []
keywords: []
weight: 1
---

In [Hugo v0.146.0], we performed a full re-implementation of how Go templates are handled in Hugo. This includes structural changes to the `layouts` folder and a new, more powerful template lookup system.

We have aimed to maintain as much backward compatibility as possible by mapping "old to new," but some reported breakages have occurred. We're working on a full overhaul of the documentation on this topic – until then, this is a one-pager with the most important changes.

## Changes to the `layouts` folder

| Description                                                                                                                                                                                                                                                                                                                                                                                                           | Action required                                                                                                                                               |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| The `_default` folder is removed.                                                                                                                                                                                                                                                                                                                                                                                     | Move all files in `layouts/_default` up to the `layouts/` root.                                                                                               |
| The `layouts/partials` folder is renamed to `layouts/_partials`.                                                                                                                                                                                                                                                                                                                                                      | Rename the folder.                                                                                                                                            |
| The `layouts/shortcodes` folder is renamed to `layouts/_shortcodes`.                                                                                                                                                                                                                                                                                                                                                  | Rename the folder.                                                                                                                                            |
| Any folder in `layouts` that does not start with `_` represents the root of a [Page path]. In [Hugo v0.146.0], this can be nested as deeply as needed, and `_shortcodes` and `_markup` folders can be placed at any level in the tree.                                                                                                                                                                                | No action required.                                                                                                                                           |
| The above also means that there's no top-level `layouts/taxonomy` or `layouts/section` folders anymore, unless it represents a [Page path].                                                                                                                                                                                                                                                                           | Move them up to `layouts/` with one of the [Page kinds] `section`, `taxonomy` or `term` as the base name, or place the layouts into the taxonomy [Page path]. |
| A template named `taxonomy.html` used to be a candidate for both Page kind `term` and `taxonomy`, now it's only considered for `taxonomy`.                                                                                                                                                                                                                                                                            | Create both `taxonomy.html` and `term.html` or create a more general layout, e.g. `list.html`.                                                                |
| For base templates (e.g., `baseof.html`), in previous Hugo versions, you could prepend one identifier (layout, type, or kind) with a hyphen in front of the baseof keyword.                                                                                                                                                                                                                                           | Move that identifier after the first "dot," e.g., rename`list-baseof.html` to `baseof.list.html`.                                                             |
| We have added a new `all` "catch-all" layout. This means that if you have, e.g., `layouts/all.html` and that is the only template, that layout will be used for all HTML page rendering.                                                                                                                                                                                                                              |                                                                                                                                                               |
| We have removed the concept of `_internal` Hugo templates.[^internal]                                                                                                                                                                                                                                                                                                                                                 | Replace constructs similar to `{{ template "_internal/opengraph.html" . }}` with `{{ partial "opengraph.html" . }}`.                                          |
| The identifiers that can be used in a template filename are one of the [Page kinds] (`home`, `page`, `section`, `taxonomy`, or `term`), one of the standard layouts (`list`, `single`, or `all`), a custom layout (as defined in the `layout` front matter field), a language (e.g., `en`), an output format (e.g., `html`, `rss`), and a suffix representing the media type. E.g., `all.en.html` and `home.rss.xml`. |                                                                                                                                                               |
| The above means that there's no such thing as an `index.html` template for the home page anymore.                                                                                                                                                                                                                                                                                                                     | Rename `index.html` to `home.html`.                                                                                                                           |

Also, see the [Example folder structure] below for a more concrete example of the new layout system.

## Changes to template lookup order

We have consolidated the template lookup so it works the same across all [template types]. The previous setup was very hard to understand and had a massive number of variants. The new setup aims to feel natural with few surprises.

The identifiers used in the template weighting, in order of importance, are:

| Identifier         | Description                                           |
|--------------------|-------------------------------------------------------|
| Layout custom      | The custom `layout` set in front matter.              |
| [Page kinds][]     | One of `home`, `section`, `taxonomy`, `term`, `page`. |
| Layouts standard 1 | `list` or `single`.                                   |
| Output format      | The output format (e.g., `html`, `rss`).              |
| Layouts standard 2 | `all`.                                                |
| Language           | The language (e.g., `en`).                            |
| Media type         | The media type (e.g., `text/html`).                   |
| [Page path][]      | The page path (e.g., `/blog/mypost`).                 |
| Type               | `type` set in front matter.[^type]                    |

For templates placed in a `layouts` folder partly or completely matching a [Page path], a closer match upwards will be considered _better_. In the [Example folder structure] below, this means that:

- `layouts/docs/api/_markup/render-link.html` will be used to render links from the Page path `/docs/api` and below.
- `layouts/docs/baseof.html` will be used as the base template for the Page path `/docs` and below.
- `layouts/tags/term.html` will be used for all `term` rendering in the `tags` taxonomy, except for the `blue` term, which will use `layouts/tags/blue/list.html`.

## Example folder structure

```text
layouts
├── baseof.html
├── baseof.term.html
├── home.html
├── page.html
├── section.html
├── taxonomy.html
├── term.html
├── term.mylayout.en.rss.xml
├── _markup
│   ├── render-codeblock-go.term.mylayout.no.rss.xml
│   └── render-link.html
├── _partials
│   └── mypartial.html
├── _shortcodes
│   ├── myshortcode.html
│   └── myshortcode.section.mylayout.en.rss.xml
├── docs
│   ├── baseof.html
│   ├── _shortcodes
│   │   └── myshortcode.html
│   └── api
│       ├── mylayout.html
│       ├── page.html
│       └── _markup
│           └── render-link.html
└── tags
    ├── taxonomy.html
    ├── term.html
    └── blue
        └── list.html
```

[^type]: The `type` set in front matter will effectively replace the `section` folder in [Page path] when doing lookups.
[^internal]: The old way of doing it made it very hard/impossible to, e.g., override `_internal/disqus.html` in a theme. Now you can just create a partial with the same name.

[Example folder structure]: #example-folder-structure
[Hugo v0.146.0]: https://github.com/gohugoio/hugo/releases/tag/v0.146.0
[Page kinds]: https://gohugo.io/methods/page/kind/
[Page path]: https://gohugo.io/methods/page/path/
[template types]: /templates/types/
