Automating Tag List Pages with Hugo Taxonomies
Learn how Hugo's taxonomy system automatically creates paginated tag list pages, eliminating manual HTML maintenance and keeping large tag collections consistent.
11 Aug 2026, 16:04 UTC

The problem with manual tag pages
On a static site each new tag usually means a new HTML file that you have to create, keep in sync, and update whenever a post is added or removed. As the number of tags grows the maintenance burden becomes a source of errors and duplicated markup.
Thesis: let Hugo do the work
Hugo’s built‑in taxonomy system generates a list page for every tag automatically. You declare the taxonomy once, add tags to your content front matter, and Hugo renders /tags/<tag>/ pages with pagination and sorting — no hand‑crafted files required.
1. Declaring the taxonomy
In config.yaml (or config.toml) add a taxonomies block. The key is the plural name you want in the URL; the value is the singular term used in front matter.
taxonomies:
tag: tags
category: categories
Now every post can include a tags array in its front matter:
---
title: "Understanding Hugo Pipelines"
date: 2026-09-15
tags: ["hugo", "pipelines", "performance"]
---
2. Providing a layout for the generated lists
Hugo looks for a template in layouts/_default/taxonomy.html first, then falls back to layouts/taxonomy/tag.html. A minimal list with pagination looks like this:
{{ define "main" }}
{{ .Title }}
{{ $paginator := .Paginate (where .Pages "Type" "posts") 10 }}
{{ range $paginator.Pages }}
- {{ .Title }} — {{ .Date.Format "Jan 2, 2006" }}
{{ end }}
{{ template "_internal/pagination.html" . }}
{{ end }}
The .Paginate call sets the page size (10 items per page) and returns a Paginator object that the internal pagination template turns into previous/next links.
3. Sorting and customising the order
By default Hugo orders pages by Date descending. To sort alphabetically or by a custom front‑matter field, chain .ByTitle or .ByParam "weight" before pagination:
{{ $pages := .Pages.ByTitle }}
{{ $paginator := .Paginate $pages 10 }}
Worked example: a tiny demo site
- Create a new site:
hugo new site demo && cd demo - Add the taxonomy block to
config.yaml(as shown above). - Create two posts:
hugo new posts/first.md # edit front matter → tags: ["go", "static"] hugo new posts/second.md # edit front matter → tags: ["go", "templates"] - Add the
taxonomy.htmllayout from section 2 underlayouts/_default/. - Run
hugo serverand openhttp://localhost:1313/tags/go/. You’ll see both posts listed, paginated at ten per page (only one page here).
The generated /tags/go/index.html contains the exact markup from the layout, with correct links and pagination controls — no manual HTML was written for that tag.
Trade‑off: build‑time only
Taxonomy pages are static artifacts produced during the build. Adding, renaming, or removing a tag requires a full rebuild to reflect the change. In a CI pipeline this is usually trivial (the next deploy rebuilds the site), but if you need instant tag updates without a deploy you’ll need a dynamic layer (e.g., a server‑side search index) on top of Hugo.
Actionable closing
Declare your taxonomies once in the site configuration, add tags to each post’s front matter, and provide a single taxonomy.html layout with pagination. Hugo will then generate consistent, paginated tag list pages for every tag you ever use — keeping the site maintainable as the tag set grows. Verify locally with hugo server, then let your CI pipeline run hugo --minify on each push to keep the published site in sync.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.