Home / Alt manpages / hugo-mod(1)

  • hugo-mod(1)
  • User command
  • linux

Manage Hugo Module Dependencies Without Losing Track of Them

hugo mod turns a Hugo site into a proper Go module, and this guide walks the whole lifecycle end to end. You will initialise the module, add a dependency, inspect the graph, tidy the metadata, verify what got downloaded and optionally vendor it locally. Allow ten to twenty minutes for a small site, plus download time for anything you add.

The examples target the installed Hugo 0.123.7, built on 17 March 2026. Run everything from the directory holding your site's hugo.yaml, hugo.toml or hugo.json. These commands change project files or the module cache, so commit or copy your work before touching dependency versions.

Before you start

Check your tools and project directory first:

$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2026-03-17T19:51:14Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3+esm2
$ command -v go
/usr/bin/go
$ command -v git
/usr/bin/git
$ pwd
/home/you/src/my-site

Your paths and build metadata will differ. The parent hugo mod command says most operations need Go 1.12 or newer plus a version-control client, usually Git. Skip those tools entirely for a site that only uses modules inside themes, or one that already vendors its modules.

Checkpoint

Do not continue until hugo version identifies the binary you actually mean to use, and you are sitting in the right project directory.

1. Initialise the project as a module

Initialisation creates the Go module metadata Hugo leans on for dependency resolution. Give it the real module path when the directory name does not make that obvious:

$ hugo mod init example.com/acme/my-site
go: creating new go.mod: module example.com/acme/my-site

The path is an identifier, not a download instruction. Use wherever this project is published or consumed, such as your Git hosting path. Hugo will guess it if you omit the argument, but an explicit value avoids a rename later.

Check the result before doing anything else:

$ sed -n '1,40p' go.mod
module example.com/acme/my-site

go 1.XX

The Go directive comes from the installed toolchain and can vary. If go.mod already exists, stop and read it rather than running initialisation on autopilot: this command establishes a module, it does not repair an existing one.

2. Add one dependency at a time

Use hugo mod get to resolve a module. This example leans on Hugo's own documented test module as a stand-in; swap it for whatever your site actually needs:

$ hugo mod get github.com/gohugoio/testshortcodes
go: added github.com/gohugoio/testshortcodes v0.3.0

Exact version and messages depend on what the module has released. Append a version when you want a particular one:

$ hugo mod get github.com/gohugoio/[email protected]

For repeatable work, pin a reviewed version or tag rather than pulling an unbounded update. hugo mod get updates the module files and downloads source into Hugo's cache; it does not make anything visible in the site's output until your configuration mounts or uses those components.

Update direct dependencies on purpose. This asks for the latest possible versions of direct dependencies, while ./... also processes module paths recursively:

$ hugo mod get -u
$ hugo mod get -u ./...

Warning

Version updates can change layouts, partials, assets or configuration a module supplies. Review the diff and build the site before committing anything. If an update goes wrong, restore the reviewed go.mod and go.sum from version control and build again; do not start deleting files by hand to try to undo it.

Checkpoint

Record the change:

$ git diff -- go.mod go.sum
$ git status --short

3. Inspect the dependency graph

Run the graph command from the module directory:

$ hugo mod graph
example.com/acme/my-site github.com/gohugoio/[email protected]

Each line names a parent and a dependency. The real graph can include indirect modules, replacement information, disabled modules and an in-themesdir entry. For a vendored dependency, the graph reports whatever version sits in the vendor tree, which may not match what is written in go.mod.

If the graph comes back wrong, check you ran it from the intended module tree and that the project's module path matches the files you inspected. Reach for the inherited --config, --configDir, --themesDir and --source options only when your site deliberately keeps those locations elsewhere.

4. Tidy and verify the downloaded source

Once the site builds with the components you intend, clear the unused entries from the Go metadata:

$ hugo mod tidy
$ git diff -- go.mod go.sum

Tidy can remove entries that looked useful but the current module graph no longer needs. Review its diff; it is a project-file change, so it needs no root privileges.

Then check the cached dependencies have not changed since download:

$ hugo mod verify
all modules verified

Successful output varies, but the command should exit with status 0. A verification failure means the local cached source no longer matches its recorded checksums. Investigate the cache and the machine before reaching for the cleanup option: hugo mod verify --clean deletes the module cache entries that fail verification. That is reversible by downloading them again, though it needs network access and is no substitute for understanding why they changed.

5. Vendor when you need a repository-local copy

Vendoring copies imported module dependencies into _vendor inside the project. Hugo prefers that directory when resolving components, so it gives builds a local copy you can inspect and commit:

$ hugo mod vendor
$ find _vendor -maxdepth 2 -type f | head
$ git status --short

Do not edit files inside _vendor as your first move. To override a vendored file, create the matching path in the project root, the way Hugo documents. Modules below themes are never vendored.

Warning

Vendoring can add a large tree to the repository. Check its size, licence obligations and review policy before committing it. To undo a vendor operation, remove the generated _vendor directory only once you have confirmed it holds none of your own work, then restore the working tree or regenerate it from the reviewed module files. The command itself needs no sudo.

When local edits need to be seen instead of the vendored copy, the parent command's --ignoreVendorPaths option can ignore matching vendor paths. Use a narrow glob for a known module, not a blanket setting you have not actually tested.

6. Clean the cache only with a reason

hugo mod clean deletes the Hugo Module cache for the current project. Handy when a cache is damaged or you need a forced fresh download, but it can make the next build slower and dependent on the network:

$ hugo mod clean
$ hugo mod verify

The --pattern option narrows the cleanup to matching module paths. --all cleans the entire module cache, not just this project, so treat it as a maintenance action. Neither needs elevated privileges when the cache belongs to your user; skip sudo, since changing the cache's ownership just creates a second, harder-to-diagnose failure.

7. Run the final build

Resolve the site once more and build it to a disposable destination before committing any dependency change:

$ rm -rf /tmp/hugo-module-preview
$ hugo --destination /tmp/hugo-module-preview
Start building sites ...
                     | EN
---------------------+----
Pages                |  1
Total                |  1

Page counts and timing depend on the site. The disposable destination is safe to remove once you have looked it over. If the build fails, read the first module or mount error, compare hugo mod graph against your configuration, and restore the last known-good dependency files before trying again.

Done means

  • hugo version showed the installed Hugo 0.123.7 binary, or you recorded why another binary was selected.
  • The module path in go.mod matches the project you meant to change.
  • Every added or updated dependency is visible in a reviewed diff.
  • hugo mod graph shows the dependency and its resolution path.
  • hugo mod tidy left only the entries the site still needs.
  • hugo mod verify completed cleanly, or its failure is understood.
  • Any _vendor tree is intentional, reviewed and recoverable from version control.
  • A final Hugo build succeeds without root privileges.