Zum Hauptinhalt springen
Technology Web Development

Hugo Mastery Part 2: Module System & Advanced Configuration

Master Hugo's module system and advanced configuration patterns, including YAML anchors, version control, and environment-specific setups.

Introduction

Building on the foundational concepts from Part 1, this guide explores Hugo’s module system and advanced configuration patterns. These features enable component reuse across projects, precise dependency management, and sophisticated multi-environment setups.

The module system, built on Go modules, provides version control for themes and components. Combined with YAML anchors and environment-specific configurations, these tools create maintainable, scalable architectures for complex Hugo projects.

Hugo Module System

Hugo’s module system provides dependency management for themes, components, and content. Built on Go modules, it enables version pinning, transitive dependencies, and reproducible builds across environments.

Modules eliminate the need to copy theme files into projects, allow component sharing across multiple sites, and support mounting multiple versions of the same module - essential for maintaining versioned documentation.

Module Version Control

You can now specify module versions directly in Hugo configuration files, eliminating manual go.mod editing and providing declarative dependency management.

[module]
 [[module.imports]]
 path = "github.com/user/theme"
 version = "v2.1.0" # Specific version

 [[module.imports]]
 path = "github.com/user/components"
 version = "main" # Branch name

Version Query Formats

Hugo supports various version specifications:

Query FormatDescriptionExample
v1.2.3Exact versionv2.1.0
v1Latest v1.x.xv1
v1.2Latest v1.2.xv1.2
latestLatest tagged versionlatest
mainBranch namemain, develop
>=v1.2.3Version constraint>=v1.0.0

Real-World Example: Multi-Version Documentation

# Mount multiple API documentation versions
[module]
 [[module.imports]]
 path = "github.com/mycompany/api-docs"
 version = "v3.0.0"
 [[module.imports.mounts]]
 source = "content"
 target = "content/docs/v3"

 [[module.imports]]
 path = "github.com/mycompany/api-docs"
 version = "v2.1.0"
 [[module.imports.mounts]]
 source = "content"
 target = "content/docs/v2"

 [[module.imports]]
 path = "github.com/mycompany/api-docs"
 version = "v1.5.0"
 [[module.imports.mounts]]
 source = "content"
 target = "content/docs/v1"

Module Mounts

Mounts allow you to map source directories to target locations in your Hugo project.

Basic Mounts

[module]
 [[module.mounts]]
 source = "content"
 target = "content"

 [[module.mounts]]
 source = "static"
 target = "static"

 [[module.mounts]]
 source = "assets"
 target = "assets"

Advanced Mount Patterns

Content Organization:

[module]
 # Reorganize content structure
 [[module.mounts]]
 source = "content/blog"
 target = "content/posts"

 [[module.mounts]]
 source = "content/documentation"
 target = "content/docs"

 # Mount external content
 [[module.mounts]]
 source = "node_modules/bootstrap/dist"
 target = "assets/vendor/bootstrap"

Multilingual Mounts:

[module]
 [[module.mounts]]
 source = "content/en"
 target = "content"
 lang = "en"

 [[module.mounts]]
 source = "content/de"
 target = "content"
 lang = "de"

 [[module.mounts]]
 source = "content/fr"
 target = "content"
 lang = "fr"

Include/Exclude Patterns:

[module]
 [[module.mounts]]
 source = "content"
 target = "content"
 includeFiles = ["*.md", "*.html"]
 excludeFiles = ["drafts/**", "archive/**"]

Working with Node Modules

New in v0.152.2: Hugo now handles node_modules mounting intelligently:

[module]
 # Hugo checks theme's node_modules first, then project root
 [[module.mounts]]
 source = "node_modules/bootstrap"
 target = "assets/vendor/bootstrap"

 [[module.mounts]]
 source = "node_modules/@fortawesome/fontawesome-free"
 target = "assets/vendor/fontawesome"

Complete Module Configuration

[module]
 # Proxy settings for restricted networks
 proxy = "https://proxy.example.com"
 noProxy = "github.com"

 # Private repository access
 private = ["github.com/mycompany/*"]

 # Workspace mode (for local development)
 workspace = "hugo.work"

 # Module imports with versions
 [[module.imports]]
 path = "github.com/user/theme"
 version = "v2.0.0"
 disable = false

 # Module replacements (for local development)
 [[module.replacements]]
 from = "github.com/old/module"
 to = "github.com/new/module"
 version = "v1.0.0"

YAML Enhancements

YAML Anchors & Aliases

YAML anchors and aliases provide a mechanism for reducing configuration duplication through reference-based reuse. This is particularly valuable in multilingual sites, multi-environment setups, and any configuration where similar structures appear repeatedly.

Anchors define reusable configuration blocks; aliases reference them. The YAML parser resolves these references at parse time, resulting in expanded configuration.

Basic Anchors

# Define reusable configuration
defaults: &defaults
  author: John Doe
  language: en
  theme: modern

# Reuse with alias
production:
  <<: *defaults
  baseURL: https://example.com
  environment: production

development:
  <<: *defaults
  baseURL: http://localhost:1313
  environment: development
# Define common menu properties
menu_defaults: &menu_defaults
 class: nav-item
 target: _self

menu:
 main:
 - <<: *menu_defaults
 name: Home
 url: /
 weight: 1

 - <<: *menu_defaults
 name: Blog
 url: /blog/
 weight: 2

 - <<: *menu_defaults
 name: About
 url: /about/
 weight: 3

Complex Anchors with Merge

# Base settings
base_settings: &base
  buildDrafts: false
  buildFuture: false
  buildExpired: false

# Production overrides
prod_settings: &prod
  <<: *base
  minify: true
  environment: production

# Development overrides
dev_settings: &dev
  <<: *base
  buildDrafts: true
  environment: development

# Use based on context
build:
  <<: *prod # Switch to *dev for development

Multilingual with Anchors

# Common language settings
lang_defaults: &lang_defaults
 weight: 1
 disabled: false

# Common parameters
params_defaults: &params
 description: Default description
 copyright: © 2025 My Site

languages:
 en:
 <<: *lang_defaults
 languageName: English
 languageCode: en-us
 params:
 <<: *params
 description: English site description

 de:
 <<: *lang_defaults
 languageName: Deutsch
 languageCode: de
 weight: 2
 params:
 <<: *params
 description: Deutsche Seitenbeschreibung

 fr:
 <<: *lang_defaults
 languageName: Français
 languageCode: fr
 weight: 3
 params:
 <<: *params
 description: Description du site en français

YAML Boolean Changes (Breaking)

Important: YAML 1.1 boolean strings are no longer auto-converted.

Migration Required

Before (YAML 1.1):

published: yes # Was converted to true
draft: no # Was converted to false
enabled: on # Was converted to true

After (Current):

published: true # Use explicit boolean
draft: false # Use explicit boolean
enabled: true # Use explicit boolean

# Or keep as strings (quoted)
status: "yes" # String value "yes"

Search and Replace Guide

Old ValueReplace WithContext
: yes: trueBoolean true
: no: falseBoolean false
: on: trueBoolean true
: off: falseBoolean false

Advanced Configuration Patterns

Environment-Specific Configuration

Organize configurations by environment for maximum flexibility.

Directory Structure:

config/
├── _default/
│ ├── config.toml
│ ├── params.toml
│ └── menus.toml
├── production/
│ ├── config.toml
│ └── params.toml
├── staging/
│ ├── config.toml
│ └── params.toml
└── development/
 ├── config.toml
 └── params.toml

config/_default/config.toml:

baseURL = "https://example.com"
title = "My Site"
theme = "mytheme"

config/production/config.toml:

minify = true
googleAnalytics = "UA-XXXXX-Y"

[params]
 environment = "production"
 comments = true
 analytics = true

config/development/config.toml:

baseURL = "http://localhost:1313"
buildDrafts = true
buildFuture = true

[params]
 environment = "development"
 comments = false
 analytics = false

Run with specific environment:

hugo server  # Uses _default + development
hugo - environment production # Uses _default + production
hugo - environment staging # Uses _default + staging

Feature Flags Pattern

Implement feature toggles for gradual rollouts:

# config/_default/params.toml
[features]
 comments = true
 analytics = true
 search = true
 darkMode = true
 newsletter = false

[features.experimental]
 aiChat = false
 voiceSearch = false
 recommendationEngine = false

Usage in templates:

{{ if .Site.Params.features.comments }}
 {{ partial "comments.html" . }}
{{ end }}

{{ if .Site.Params.features.experimental.aiChat }}
 {{ partial "ai-chat.html" . }}
{{ end }}

Cascading Configuration

Apply settings to entire sections:

content/blog/_index.md:

---
title: Blog
cascade:
  type: posts
  layout: single
  params:
  sidebar: true
  toc: true
  comments: true
---

All pages under /blog/ inherit these settings automatically.

Targeted Cascade:

---
title: Home
cascade:
 - _target:
 kind: page
 path: /blog/**
 params:
 layout: blog-post

 - _target:
 kind: page
 path: /docs/**
 params:
 layout: documentation
---

Performance Configuration

[caches]
 [caches.getjson]
 dir = ":cacheDir/:project"
 maxAge = "24h"

 [caches.getcsv]
 dir = ":cacheDir/:project"
 maxAge = "24h"

 [caches.images]
 dir = ":resourceDir/_gen"
 maxAge = -1 # Never expire

 [caches.assets]
 dir = ":resourceDir/_gen"
 maxAge = -1

 [caches.modules]
 dir = ":cacheDir/modules"
 maxAge = -1

Multilingual Configuration

Advanced Multilingual Setup

defaultContentLanguage = "en"
defaultContentLanguageInSubdir = true

[languages]
 [languages.en]
 languageName = "English"
 languageCode = "en-us"
 weight = 1
 title = "My Site"

 [languages.en.params]
 description = "English description"

 [languages.de]
 languageName = "Deutsch"
 languageCode = "de"
 weight = 2
 title = "Meine Website"

 [languages.de.params]
 description = "Deutsche Beschreibung"

 [languages.fr]
 languageName = "Français"
 languageCode = "fr"
 weight = 3
 title = "Mon Site"

 [languages.fr.params]
 description = "Description française"

Language-Specific Menus

[languages.en.menu]
 [[languages.en.menu.main]]
 name = "Home"
 url = "/"
 weight = 1

 [[languages.en.menu.main]]
 name = "Blog"
 url = "/blog/"
 weight = 2

[languages.de.menu]
 [[languages.de.menu.main]]
 name = "Startseite"
 url = "/"
 weight = 1

 [[languages.de.menu.main]]
 name = "Blog"
 url = "/blog/"
 weight = 2

Using YAML Anchors for Multilingual

# Common language structure
language_template: &lang_template
 disabled: false
 params:
 dateFormat: "2 January 2006"
 copyright: © 2025-2026 Site

languages:
 en:
 <<: *lang_template
 languageName: English
 languageCode: en-us
 weight: 1
 title: My Site

 de:
 <<: *lang_template
 languageName: Deutsch
 languageCode: de
 weight: 2
 title: Meine Website
 params:
 dateFormat: "2. January 2006"

Module Management Commands

Essential Commands

# Initialize module
hugo mod init github.com/user/repo

# Get/update modules
hugo mod get -u   # Update all
hugo mod get github.com/user/module@v1.2.3 # Specific version
hugo mod get github.com/user/module@main # Branch

# Maintenance
hugo mod tidy   # Remove unused
hugo mod clean   # Clear cache
hugo mod vendor   # Vendor locally
hugo mod graph   # Show dependencies

Troubleshooting Modules

# Clear module cache
hugo mod clean

# Force update
hugo mod get -u

# Check module dependency tree
hugo mod graph

# Verify module configuration
hugo config

Practical Examples

Example 1: Complete Module Setup

[module]
 # Theme module with specific version
 [[module.imports]]
 path = "github.com/user/hugo-theme-awesome"
 version = "v2.1.0"

 # Component library
 [[module.imports]]
 path = "github.com/user/hugo-components"
 version = "main"

 # Icon library from npm
 [[module.mounts]]
 source = "node_modules/@fortawesome/fontawesome-free/webfonts"
 target = "static/webfonts"

 [[module.mounts]]
 source = "node_modules/@fortawesome/fontawesome-free/css"
 target = "assets/vendor/fontawesome/css"

Example 2: Multi-Environment Setup with YAML

# config.yaml
_base_config: &base
  title: My Awesome Site
  theme: mytheme
  paginate: 10

_prod_settings: &prod
  minify: true
  googleAnalytics: UA-XXXXX-Y

_dev_settings: &dev
  buildDrafts: true
  buildFuture: true

# Select based on HUGO_ENVIRONMENT
production:
  <<: [*base, *prod]
  baseURL: https://mysite.com

development:
  <<: [*base, *dev]
  baseURL: http://localhost:1313

Example 3: Feature Flag Implementation

# config/_default/params.yaml
features:
 comments: &comments_enabled true
 analytics: &analytics_enabled true
 search: &search_enabled true

# Development overrides
# config/development/params.yaml
features:
 comments: false # Override comments in dev
 analytics: false # Override analytics in dev
 search: *search_enabled # Keep search enabled

Best Practices

  1. Version Control: Pin module versions in production
  2. DRY Configuration: Use YAML anchors to reduce duplication
  3. Environment Separation: Use config directories for different environments
  4. Cache Management: Configure appropriate cache durations
  5. Module Updates: Regularly update modules but test thoroughly
  6. Documentation: Comment your configuration files
  7. Security: Use security settings to restrict external access

Conclusion

Hugo’s module system and advanced configuration patterns provide the foundation for scalable, maintainable static sites. Modules enable component reuse and version control, while YAML anchors and environment-specific configurations reduce duplication and configuration drift.

These patterns become essential as projects grow in complexity. Start with YAML anchors to eliminate configuration duplication, then implement module mounts for better asset organization. Add environment-specific configs to handle multiple deployment targets cleanly.

Part 3 explores modern Hugo features including enhanced content transformation and sampling functions.

Resources


This is Part 2 of the Hugo Mastery series. ← Back to Part 1 | Continue to Part 3: Latest Features & What’s New →

/Users/damirmukimov/projects/samyrai.github.io/layouts/partials/hardware-schema.html