Advanced
Hugo Modules deep-dive
Pinning versions, replacing locally, and overriding individual files.
Hugo Modules are the modern way to consume themes. They give you version pinning, easy upgrades, and — most powerfully — the ability to override individual files without forking the theme.
Pinning a version #
hugo mod get github.com/splunk/hugo-theme-splunk-workshop@v0.1.0Hugo writes the resolved version to your go.mod. Future hugo build and hugo server invocations use that exact version. Available tags are on the releases page
.
To upgrade everything:
hugo mod get -uTo upgrade just this theme to the latest tag:
hugo mod get -u github.com/splunk/hugo-theme-splunk-workshopTo pin to any specific version:
hugo mod get github.com/splunk/hugo-theme-splunk-workshop@vX.Y.ZLocal development with replace
#
When you’re developing a fix to the theme alongside your site, point the module at your local checkout:
# In your site's hugo.toml
[module]
[[module.imports]]
path = "github.com/splunk/hugo-theme-splunk-workshop"
[[module.replacements]]
path = "github.com/splunk/hugo-theme-splunk-workshop"
replacement = "/Users/you/code/hugo-theme-splunk-workshop"Now your site renders against your local theme checkout. Save a file in the theme; your site reloads. When you’re done, remove the [[module.replacements]] block (or comment it out) and the module pin reasserts itself.
Overriding individual files #
Hugo’s union filesystem means any file in your site overrides the same file in the theme. So if you want a custom header without forking:
your-site/
└── layouts/
└── partials/
└── header.html # ← yours wins over the theme'sHugo’s resolution order:
- Your site’s
layouts/ - Theme’s
layouts/
Same goes for assets/, static/, i18n/, data/, and archetypes/. Your file is used; the theme’s file is ignored.
This is the cleanest way to customize the theme — no fork, no patch, just create a same-named file in your site.
Don't override what you don't have to
Every file you override is a file you’ll have to maintain when the theme updates. Override the smallest unit possible — usually a partial, not a full layout. And document why in a comment at the top of the file.Submodule alternative #
If Go modules aren’t an option (corporate firewalls, build constraints, preference), git submodules give you a similar setup minus the version pinning:
git submodule add https://github.com/splunk/hugo-theme-splunk-workshop.git \
themes/hugo-theme-splunk-workshop
git submodule update --init --recursiveIn hugo.toml:
theme = "hugo-theme-splunk-workshop"To upgrade to the latest:
cd themes/hugo-theme-splunk-workshop
git pull origin main
cd ../..
git add themes/hugo-theme-splunk-workshop
git commit -m "chore: bump theme"The submodule pins to a specific commit, so it has version-control benefits — just less ergonomic than hugo mod.
