Versioning
Versioning serves multiple doc versions. Each version maps to a content directory and gets its own URL prefix.
How It Works
Hugo builds one site per version declared in versions. Each site mounts only the content directories whose sites.matrix.versions constraint matches that version.
Configuration
Declare versions
Add a versions block to hugo.yaml. Each key is a version name.
defaultContentVersion: v2.0.0
defaultContentVersionInSubdir: false
versions:
v1.0.0: {}
v2.0.0: {}defaultContentVersion: which version serves the unprefixed URLdefaultContentVersionInSubdir:falseserves default at/docs/,trueat/v2.0.0/docs/versions: declares all available versions; each key must match a content directory name
Mount content directories
Each module.mounts entry maps a versioned source directory to the shared content target.
module:
mounts:
- source: content/v2.0.0
target: content
sites:
matrix:
versions: [v2.0.0]
- source: content/v1.0.0
target: content
sites:
matrix:
versions: [v1.0.0]source: local directory containing that version's contenttarget: alwayscontent. Hugo merges all mounts into one virtual content treesites.matrix.versions: semver constraint selecting which version sites receive this mount**: all versions>= v2.0.0: v2.0.0 and above< v2.0.0: below v2.0.0
When two files share the same path, the first mount takes precedence.
Enable the switcher
params:
versionSwitcher: truePer-page version scoping
Restrict a page to specific versions using sites.matrix.versions in its front matter.
---
title: New Feature
sites:
matrix:
versions: '>= v2.0.0'
---sites.matrix.versions: semver constraint scoping this page to matching version sites- omitting this key makes the page visible on every version site that receives its mount
Content Structure
Organize versioned content under directories that match the version names declared in versions.
content/
âââ en/ # not versioned
â âââ blog/
âââ v1.0.0/ # versioned
â âââ docs/
â âââ feature-a.md
âââ v2.0.0/ # versioned
âââ docs/
âââ feature-b.mdLanguage content and version content coexist in the mount list.
Full Example
The official Hugo example demonstrates a working multi-version site with four versions and cascading mount overrides.
With Multiple Languages
With multiple languages, Hugo generates one site per language à version combination. The mounts must specify both dimensions.
Directory structure
Versioned docs are nested inside each language directory.
content/
âââ en/
â âââ v1.0.0/
â â âââ docs/
â âââ v2.0.0/
â â âââ docs/
â âââ blog/ # not versioned
â âââ authors/ # not versioned, en-only
âââ zh-cn/
âââ v1.0.0/
â âââ docs/ # partial translation is fine
âââ v2.0.0/
â âââ docs/
âââ (other non-versioned content)Module mounts
module:
mounts:
# versioned docs: zh-cn translation (must come before en fallback)
- source: content/zh-cn/v2.0.0
target: content
sites:
matrix:
languages: [zh-cn]
versions: [v2.0.0]
- source: content/zh-cn/v1.0.0
target: content
sites:
matrix:
languages: [zh-cn]
versions: [v1.0.0]
# versioned docs: en as fallback for all languages
- source: content/en/v2.0.0
target: content
sites:
matrix:
languages: ['**']
versions: [v2.0.0]
- source: content/en/v1.0.0
target: content
sites:
matrix:
languages: ['**']
versions: [v1.0.0]
# non-versioned content: zh-cn first (wins on path collision)
- source: content/zh-cn
target: content
files:
- '! v1.0.0/**'
- '! v2.0.0/**'
sites:
matrix:
languages: [zh-cn]
versions: ['**']
# non-versioned content: en shared across all languages
- source: content/en
target: content
files:
- '! authors/**'
- '! v1.0.0/**'
- '! v2.0.0/**'
sites:
matrix:
languages: ['**']
versions: ['**']
# en-only authors
- source: content/en/authors
target: content/authors
sites:
matrix:
languages: [en]
versions: ['**']Notes:
languagesandversionsinsites.matrixare AND conditions.- zh-cn mounts come before their en equivalents. The first mount wins on path collision, so zh-cn translations take precedence over the en fallback.
- Non-versioned mounts use
versions: ['**']so blog, authors, and other pages appear in every version site. - The
filesexclusion list prevents non-versioned mounts from double-mounting versioned subdirectories. Add! vX.Y.Z/**for every new version.
Adding a version
To add v3.0.0:
- Create
content/en/v3.0.0/docs/and optionallycontent/zh-cn/v3.0.0/docs/. - Add
v3.0.0: {}underversions. - Add two mount entries (zh-cn and en) with
versions: [v3.0.0]. - Add
- '! v3.0.0/**'to thefileslist in both non-versioned mounts.