| name | hugo-content-structure |
| description | This skill should be used when the user mentions "content organization", "frontmatter", "taxonomy", "archetype", "page bundle", "leaf bundle", "branch bundle", "_index.md", "section pages", "draft content", "related content", "hugo new", "content types", "tags", "categories", or any Hugo content structure questions. Provides comprehensive guidance on organizing Hugo content, writing frontmatter, configuring taxonomies, and using archetypes. |
Hugo Content Structure
Content Organization Patterns
Directory-Based Sections
Hugo organizes content into sections based on directory structure under content/:
content/
├── _index.md # Homepage content
├── blog/
│ ├── _index.md # Blog section list page
│ ├── first-post.md # Regular page
│ └── second-post/ # Page bundle
│ ├── index.md # Page content
│ └── hero.jpg # Page resource
├── docs/
│ ├── _index.md # Docs section list page
│ ├── getting-started.md
│ └── api-reference/
│ └── _index.md # Nested section
└── about.md # Top-level page
Key Principles:
- Each top-level directory under
content/ creates a section
- URL structure mirrors directory structure:
content/blog/post.md → /blog/post/
- Section names should be lowercase with hyphens
Section List Pages (_index.md)
Every section needs an _index.md file for its list page:
---
title: "Blog"
description: "Articles about web development and design"
---
Optional content that appears above the list of pages.
Without _index.md:
- Section list pages still render but have no custom title/description
- Cannot add content above the list
- Missing metadata for SEO
Page Bundles
Page bundles group a page with its resources (images, files). Two types exist:
Leaf Bundles (Single Pages)
content/blog/my-post/
├── index.md # Page content (note: index.md, not _index.md)
├── hero.jpg # Page resource
├── diagram.png # Page resource
└── data.json # Page resource
Use leaf bundles when:
- Post has associated images
- Post needs downloadable files
- You want to keep assets with content
Branch Bundles (Section Pages)
content/docs/
├── _index.md # Section list page (note: _index.md)
├── intro.md # Child page
└── advanced/
└── _index.md # Nested section
Critical Distinction:
index.md (no underscore) = Leaf bundle, single page with resources
_index.md (with underscore) = Branch bundle, section list page
Accessing Page Resources
In templates, access bundle resources:
{{ $hero := .Resources.GetMatch "hero.*" }}
{{ if $hero }}
<img src="{{ $hero.RelPermalink }}" alt="{{ .Title }}">
{{ end }}
{{/* All images */}}
{{ range .Resources.ByType "image" }}
<img src="{{ .RelPermalink }}">
{{ end }}
Frontmatter Fields and Schemas
Required Fields
Every content file needs at minimum:
---
title: "My Page Title"
date: 2026-01-07T10:00:00-08:00
---
Date Format: Always use RFC3339 with timezone. Hugo parses dates strictly.
Common Fields
---
title: "Complete Guide to Hugo"
date: 2026-01-07T10:00:00-08:00
lastmod: 2026-01-07T15:30:00-08:00
description: "Everything you need to know about Hugo static site generator"
summary: "A shorter summary for list pages"
draft: false
image: "featured.jpg"
tags: ["hugo", "static-sites", "web-development"]
categories: ["tutorials"]
author: "Jane Doe"
weight: 10
slug: "custom-url-slug"
aliases: ["/old-url/", "/another-old-url/"]
---
Field Reference:
title - Page title (required)
date - Publication date (required)
lastmod - Last modification date
description - Meta description for SEO
summary - Short summary for list pages (auto-generated if omitted)
draft - Set to true to hide in production
image - Featured image path (relative to page bundle or static/)
tags / categories - Built-in taxonomies
weight - Manual ordering (lower = first)
slug - Override URL slug
aliases - Redirects from old URLs
Custom Fields via Params
Add any custom fields; access them via .Params:
---
title: "Product Review"
params:
rating: 4.5
price: 299
featured: true
---
Access in templates:
{{ with .Params.rating }}Rating: {{ . }}/5{{ end }}
Type and Layout Fields
Control template selection:
---
title: "About Us"
type: "info"
layout: "about"
---
Template lookup order with type: "info" and layout: "about":
layouts/info/about.html
layouts/info/single.html
layouts/_default/about.html
layouts/_default/single.html
Taxonomy Configuration and Usage
Built-in Taxonomies
Hugo includes tags and categories by default. Use them in frontmatter:
---
title: "Learning Go"
tags: ["golang", "programming", "backend"]
categories: ["tutorials"]
---
Custom Taxonomies
Define additional taxonomies in hugo.toml:
[taxonomies]
tag = "tags"
category = "categories"
series = "series"
author = "authors"
show = "shows"
Syntax: singular = "plural"
Use custom taxonomies in frontmatter:
---
title: "Episode 42"
series: ["web-development-fundamentals"]
authors: ["jane-doe", "john-smith"]
shows: ["tech-talk"]
---
Taxonomy Templates
Create templates for taxonomy pages:
layouts/
├── _default/
│ ├── taxonomy.html # List of terms (e.g., all tags)
│ └── term.html # Pages with specific term (e.g., posts tagged "hugo")
└── tags/
├── taxonomy.html # Override for tags specifically
└── term.html
taxonomy.html - Lists all terms:
<h1>{{ .Title }}</h1>
<ul>
{{ range .Pages }}
<li><a href="{{ .RelPermalink }}">{{ .Title }} ({{ .Count }})</a></li>
{{ end }}
</ul>
term.html - Lists pages with a specific term:
<h1>Posts tagged "{{ .Title }}"</h1>
{{ range .Pages }}
<article>
<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
</article>
{{ end }}
Listing Taxonomy Terms in Templates
Display tags/categories on any page:
{{/* On a single page */}}
{{ with .GetTerms "tags" }}
<div class="tags">
{{ range . }}
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ end }}
</div>
{{ end }}
{{/* All site tags */}}
{{ range .Site.Taxonomies.tags }}
<a href="{{ .Page.RelPermalink }}">{{ .Page.Title }} ({{ .Count }})</a>
{{ end }}
Archetype Templates
Location and Purpose
Archetypes are templates for hugo new command:
archetypes/
├── default.md # Fallback for all content
├── blog.md # For hugo new blog/post-name.md
├── docs.md # For hugo new docs/page-name.md
└── review/
└── index.md # For page bundles: hugo new review/product-name
Default Archetype
---
title: "{{ replace .File.ContentBaseName "-" " " | title }}"
date: {{ .Date }}
draft: true
---
Content-Type Specific Archetypes
archetypes/blog.md:
---
title: "{{ replace .File.ContentBaseName "-" " " | title }}"
date: {{ .Date }}
draft: true
description: ""
tags: []
categories: []
image: ""
---
## Introduction
## Main Content
## Conclusion
Creating Content with Archetypes
hugo new about.md
hugo new blog/my-first-post.md
hugo new blog/my-bundled-post/
hugo new --kind blog posts/special-post.md
Dynamic Values in Archetypes
Available variables:
{{ .Date }} - Current timestamp (RFC3339)
{{ .File.ContentBaseName }} - Filename without extension
{{ .File.Dir }} - Directory path
{{ .Site.Title }} - Site title from config
Draft and Future Content
Draft Content Workflow
Mark content as draft during development:
---
title: "Work in Progress"
date: 2026-01-07T10:00:00-08:00
draft: true
---
Build Behavior:
hugo - Excludes drafts (production)
hugo -D or hugo --buildDrafts - Includes drafts
hugo server -D - Local development with drafts
Future-Dated Content
Content with dates in the future is hidden by default:
---
title: "Scheduled Post"
date: 2026-02-01T09:00:00-08:00
---
Build Behavior:
hugo - Excludes future content
hugo -F or hugo --buildFuture - Includes future content
- Useful for scheduling posts
Publishing Workflow
- Create with draft:
hugo new blog/new-post.md (draft: true from archetype)
- Write and preview:
hugo server -D
- Publish: Remove
draft: true or set draft: false
- Build:
hugo
Related Content Configuration
Configuration
In hugo.toml:
[related]
includeNewer = true
threshold = 80
toLower = true
[[related.indices]]
applyFilter = false
cardinalityThreshold = 0
name = "tags"
pattern = ""
toLower = true
type = "basic"
weight = 100
[[related.indices]]
name = "keywords"
weight = 80
[[related.indices]]
name = "date"
weight = 10
pattern = "2006"
Options:
threshold - Minimum score (0-100) to be considered related
includeNewer - Include content newer than current page
weight - Relative importance of each index
Using Related Content in Templates
{{ $related := .Site.RegularPages.Related . | first 5 }}
{{ with $related }}
<aside class="related">
<h3>Related Posts</h3>
<ul>
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
</ul>
</aside>
{{ end }}
Keywords for Better Matching
Add keywords to frontmatter for finer control:
---
title: "Advanced CSS Techniques"
tags: ["css", "web-design"]
keywords: ["flexbox", "grid", "animations", "transitions"]
---
Content Best Practices
Use Page Bundles for Posts with Images
Correct - Keep assets with content:
content/blog/my-post/
├── index.md
├── hero.jpg
└── diagram.png
Avoid - Separated assets:
content/blog/my-post.md
static/images/blog/my-post/hero.jpg # Hard to maintain
Image Handling
Always use shortcodes or partials for images:
{{</* figure src="hero.jpg" alt="Description" */>}}
Never use raw markdown images:
 <!-- Avoid: no processing, no responsive images -->
Taxonomy Consistency
Before creating new tags:
- Check existing tags: List at
/tags/
- Use consistent casing:
web-development not Web Development
- Prefer specific over generic:
hugo-templates over templates
- Check for similar tags to avoid duplicates
Frontmatter Schema Consistency
Maintain consistent schemas per content type. Document in archetypes:
title: ""
date:
description: ""
tags: []
image: ""
title: ""
date:
rating:
pros: []
cons: []
verdict: ""
Content Organization Tips
- Flat vs nested: Prefer flat structure unless you have clear hierarchy
- Naming: Use lowercase, hyphenated slugs:
my-great-post/
- Dates in filenames: Optional but helps sorting:
2026-01-07-post-title/
- Index pages: Always create
_index.md for sections you want to customize
- Headless bundles: Use
headless: true for content used only as data