Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Hugo — Administrator & Developer Guide

Generated May 2026 from gohugoio/hugo at 62cef36

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Hugo is the world's fastest static site generator, built in Go with a single-binary architecture that eliminates runtime dependencies. This guide covers everything an administrator, DevOps engineer, or contributor needs to deploy, configure, secure, operate, and extend Hugo at scale. For everyday usage, content authoring, and template basics, see the User Guide.


1. Architecture Overview

1.1 High-Level Design

Hugo follows a pipeline architecture: content files enter through a virtual filesystem layer, pass through front matter parsing and markup rendering, flow through the Go template engine, and exit as static HTML/CSS/JS/XML/JSON files ready for any web server or CDN.

                         ┌─────────────────────────────┐
                         │       CLI (Cobra/simplecobra)│
                         │  main.go → commands.Execute()│
                         └──────────┬──────────────────┘
                                    │
                    ┌───────────────▼───────────────┐
                    │        Config Loading          │
                    │  config/allconfig → RootConfig │
                    │  (TOML/YAML/JSON, env, flags)  │
                    └───────────────┬───────────────┘
                                    │
              ┌─────────────────────▼─────────────────────┐
              │            Hugo Modules System             │
              │  (Go-module-based theme/component imports) │
              └─────────────────────┬─────────────────────┘
                                    │
         ┌──────────────────────────▼──────────────────────────┐
         │              Virtual Filesystem (hugofs)             │
         │  Overlay FS → Component FS → Filter FS → Source FS  │
         └──────────────────────────┬──────────────────────────┘
                                    │
      ┌─────────────────────────────▼─────────────────────────────┐
      │                    Site Building Engine                     │
      │                      (hugolib/)                            │
      │  ┌──────────┐  ┌───────────┐  ┌───────────┐  ┌─────────┐│
      │  │ Document  │  │ Sites     │  │ Page      │  │ Content ││
      │  │ Tree      │  │ Matrix    │  │ From Data │  │ Versions││
      │  │ (doctree) │  │(sitematrix│  │           │  │ & Roles ││
      │  └──────────┘  └───────────┘  └───────────┘  └─────────┘│
      └─────────────────────────────┬─────────────────────────────┘
                                    │
         ┌──────────────────────────▼──────────────────────────┐
         │               Resource Pipeline                      │
         │  ┌──────┐ ┌──────┐ ┌───────┐ ┌──────┐ ┌──────────┐│
         │  │Images│ │JS    │ │CSS    │ │Minify│ │Integrity ││
         │  │(gift)│ │(esb.)│ │(Sass) │ │      │ │(SRI)     ││
         │  └──────┘ └──────┘ └───────┘ └──────┘ └──────────┘│
         └──────────────────────────┬──────────────────────────┘
                                    │
         ┌──────────────────────────▼──────────────────────────┐
         │                 Markup Rendering                     │
         │  Goldmark │ AsciiDoc │ RST │ Org │ Pandoc │ Chroma │
         └──────────────────────────┬──────────────────────────┘
                                    │
         ┌──────────────────────────▼──────────────────────────┐
         │                Template Engine                       │
         │  Go html/template + text/template (forked)          │
         │  50+ function namespaces │ Shortcodes │ Partials    │
         └──────────────────────────┬──────────────────────────┘
                                    │
         ┌──────────────────────────▼──────────────────────────┐
         │                 Output / Publishing                  │
         │  Output formats │ Media types │ Minification        │
         │  URL transforms │ Meta injection │ SRI hashes       │
         └──────────────────────────┬──────────────────────────┘
                                    │
         ┌──────────────────────────▼──────────────────────────┐
         │              Deploy (optional, withdeploy)           │
         │  S3 │ GCS │ Azure Blob │ CloudFront invalidation    │
         └─────────────────────────────────────────────────────┘

1.2 Key Architectural Principles

  1. Single binary, zero runtime dependencies. Hugo ships as one executable. External tools (Dart Sass, PostCSS, Asciidoctor) are optional and whitelisted via the security policy.
  2. Virtual filesystem composition. Content, themes, assets, data, and i18n are each mounted through a layered VFS (hugofs) that supports overlays, component isolation, and glob filtering.
  3. Parallel processing. Hugo uses Go's goroutine model extensively. Content rendering, image processing, and resource transformations run concurrently, controlled by HUGO_NUMWORKERMULTIPLIER.
  4. Incremental rebuilds. The identity-based dependency tracker (identity/) detects which pages depend on changed resources and rebuilds only those during hugo server watch cycles.
  5. Multi-dimensional site matrix. Sites are organized by language, content version, and content role — sitesmatrix/ manages the full language x version x role cross-product.
  6. Immutable resource pipeline. Once a resource is transformed (resized image, bundled JS), the result is cached by content hash, enabling deterministic builds.

1.3 Request Flow: hugo build

  1. main.go calls commands.Execute(os.Args[1:])
  2. commands.go via newExec() wires all CLI subcommands through simplecobra
  3. commandeer.go via rootCommand loads flags and resolves the config path
  4. config/allconfig/ merges config files, environment variables, and CLI flags into RootConfig then Configs
  5. modules/ resolves theme and module dependencies (Go module graph)
  6. hugofs/ constructs the virtual filesystem overlay
  7. hugolib/ builds the site:
    • doctree/ constructs the document tree
    • pagesfromdata/ generates pages from data sources
    • Front matter parsed by parser/pageparser/
    • Markup rendered by markup/goldmark/ (or other renderers)
    • Templates executed from tpl/tplimpl/
    • Resources processed by resources/resource_transformers/
  8. publisher/ writes output files to the destination directory
  9. transform/ applies post-processing (URL replacement, meta injection)
  10. minifiers/ optionally minifies output

2. System Requirements

2.1 Build Requirements

Requirement Minimum Recommended
Go version 1.25.0 1.25.0+
Git 2.x Latest stable
OS Linux, macOS, Windows, FreeBSD, OpenBSD Linux amd64
Disk (build from source) 500 MB 1 GB
RAM (build from source) 2 GB 4 GB+

2.2 Runtime Requirements

Hugo itself has no runtime dependencies beyond the single binary. Optional external tools extend functionality:

Tool Purpose Required When
git GitInfo, Hugo Modules enableGitInfo: true or using modules
go Hugo Modules Using hugo mod commands
dart-sass-embedded / dart-sass Sass/SCSS compilation Using resources.ToCSS with Sass
npx / npm PostCSS, Tailwind, npm packages Using PostCSS pipe or JS packages
postcss PostCSS processing Using resources.PostCSS
tailwindcss Tailwind CSS Using Tailwind integration
asciidoctor AsciiDoc rendering .adoc content files
pandoc Pandoc rendering .pandoc / .pdc content files
rst2html reStructuredText .rst content files

Important

All external commands are subject to the security exec whitelist (security.exec.allow). If you add a tool not in the default regex, you must update the whitelist or Hugo will refuse to execute it.

2.3 Runtime Resource Guidelines

Site Scale Pages Expected Build Time RAM Usage
Small < 1,000 < 2 seconds 100-300 MB
Medium 1,000-10,000 2-15 seconds 300 MB-1 GB
Large 10,000-100,000 15-120 seconds 1-4 GB
Very Large 100,000+ 2-10 minutes 4-16 GB

Memory usage scales with content volume, image processing pipelines, and template complexity. Control via the HUGO_MEMORYLIMIT environment variable (in MB).

2.4 Build from Source

# Clone
git clone https://github.com/gohugoio/hugo.git
cd hugo

# Standard build (no deploy support)
go build -o hugo

# Build with cloud deployment support
go build -tags withdeploy -o hugo

# Using Mage (recommended for development)
go install github.com/magefile/mage@latest
mage hugo        # Build
mage install     # Build and install to $GOPATH/bin
mage test        # Run tests
mage fmt         # Format code
mage vet         # Run vet

Note

The withdeploy build tag is required for hugo deploy to function. Without it, running hugo deploy produces the error: "deploy not supported in this version of Hugo". Pre-built release binaries from GitHub include this tag.


3. Configuration Reference

Hugo's configuration system supports TOML, YAML, and JSON formats. Config files can be a single file (hugo.toml, hugo.yaml, or hugo.json) or a config directory (config/) with environment-specific overrides.

3.1 Config Resolution Order

Configuration is merged in this precedence (highest wins):

  1. CLI flags (--baseURL, --buildDrafts, etc.)
  2. Environment variables (HUGO_ prefix, e.g., HUGO_BASEURL)
  3. Environment-specific config (config/{environment}/)
  4. Main config file (hugo.toml / hugo.yaml / hugo.json)
  5. Theme/module defaults

The environment defaults to production for hugo and development for hugo server. Override with --environment or HUGO_ENVIRONMENT / HUGO_ENV.

3.2 Config Directory Structure

config/
├── _default/
│   ├── hugo.toml          # Base config
│   ├── menus.toml         # Menu definitions
│   ├── params.toml        # Site params
│   └── languages.toml     # Language config
├── production/
│   └── hugo.toml          # Production overrides
├── staging/
│   └── hugo.toml          # Staging overrides
└── development/
    └── hugo.toml          # Development overrides

3.3 Complete Top-Level Configuration Keys

The following is the authoritative list of top-level configuration keys from config/allconfig/allconfig.go (RootConfig struct):

Core Settings

Key Type Default Description
baseURL string "" Hostname and path to the root (e.g., https://example.com/)
title string "" Site title
copyright string "" Copyright notice
locale string "" BCP 47 language tag (replaces deprecated languageCode)
timeZone string "" Timezone for date operations (e.g., America/New_York)
theme string/list [] Theme name(s)
environment string "production" / "development" Build environment

Content Behavior

Key Type Default Description
buildDrafts bool false Include draft content
buildExpired bool false Include expired content
buildFuture bool false Include future-dated content
defaultContentLanguage string "en" Default language
defaultContentLanguageInSubdir bool false Put default language in subdirectory
defaultContentRole string "" Default content role
defaultContentRoleInSubdir bool false Put default role in subdirectory
defaultContentVersion string "" Default content version
defaultContentVersionInSubdir bool false Put default version in subdirectory
defaultOutputFormat string "" Default output format
disableKinds list [] Page kinds to disable (page, home, section, taxonomy, term, RSS, sitemap, robotsTXT, 404)
disableLanguages list [] Languages to disable
renderSegments list [] Segments to render (partial builds)
enableEmoji bool false Enable emoji shortcodes
hasCJKLanguage bool false Enable CJK-aware word counting
summaryLength int 70 Word count for auto-summary
mainSections list auto Sections used for .Site.RegularPages
ignoreFiles list [] Regexes for files to ignore
ignoreCache bool false Ignore cache directory

URL and Path Settings

Key Type Default Description
canonifyURLs bool false Make all relative URLs absolute
relativeURLs bool false Make URLs relative to content
removePathAccents bool false Remove accents from paths
disablePathToLower bool false Preserve case in paths
disableAliases bool false Disable alias generation
uglyURLs bool/map false Use ugly URL style (e.g., /page.html instead of /page/)
permalinks map {} Permalink patterns by section

Build Settings

Key Type Default Description
timeout duration "30s" Timeout for content generation
enableGitInfo bool false Enable Git info for pages
cleanDestinationDir bool false Remove files from destination not in static dirs
noTimes bool false Don't sync modification times
noChmod bool false Don't sync file permissions
noBuildLock bool false Don't create .hugo_build.lock
templateMetrics bool false Enable template execution metrics
templateMetricsHints bool false Show template metrics hints
panicOnWarning bool false Panic on warnings

Output and Redirect Settings

Key Type Default Description
enableRobotsTXT bool false Generate robots.txt
disableHugoGeneratorInject bool false Don't inject Hugo generator meta tag
disableLiveReload bool false Disable LiveReload in dev server
disableDefaultLanguageRedirect bool false Don't redirect to default language
disableDefaultSiteRedirect bool false Don't redirect to default site
pluralizeListTitles bool true Pluralize list page titles
capitalizeListTitles bool true Capitalize list page titles
titleCaseStyle string "AP" Title case style (AP, Chicago, Go, firstupper, none)
printUnusedTemplates bool false Print unused templates
printI18nWarnings bool false Print i18n warnings
printPathWarnings bool false Print path warnings
enableMissingTranslationPlaceholders bool false Show placeholder for missing translations

Reference Settings

Key Type Default Description
refLinksErrorLevel string "ERROR" Ref link error level
refLinksNotFoundURL string "" URL for broken ref links
sectionPagesMenu string "" Menu to auto-populate from sections
newContentEditor string "" Editor for hugo new
ignoreVendorPaths string "" Regex for vendor paths to ignore

Logging

Key Type Default Description
ignoreLogs list [] Log statement IDs to suppress

Tip

Use ignoreLogs to suppress specific warning IDs in CI/CD pipelines where certain warnings are expected. Identify log IDs by running a build with --logLevel debug.

3.4 Nested Configuration Sections

[build]

Controls build behavior:

[build]
  useResourceCacheWhen = "fallback"  # "fallback", "always", "never"
  noJSConfigInAssets = false
  buildStats = false
  cacheBusters = []

buildStats generates hugo_stats.json with classes, IDs, and tags used across the site, which is needed for PurgeCSS and Tailwind CSS tree-shaking workflows.

[caches]

File-cache configuration (from cache/filecache/):

[caches]
  [caches.assets]
    dir = ":resourceDir/_gen"
    maxAge = -1          # Never expire (-1 = never, 0 = disabled)
  [caches.getcsv]
    dir = ":cacheDir/:project"
    maxAge = -1
  [caches.getjson]
    dir = ":cacheDir/:project"
    maxAge = -1
  [caches.getresource]
    dir = ":cacheDir/:project"
    maxAge = -1
  [caches.images]
    dir = ":resourceDir/_gen"
    maxAge = -1
  [caches.modules]
    dir = ":cacheDir/modules"
    maxAge = -1
  [caches.misc]
    dir = ":cacheDir/:project"
    maxAge = -1

Tokens: :cacheDir (OS cache dir or cacheDir config), :resourceDir (resources/ by default), :project (project base directory name).

[httpCache]

HTTP response caching:

[httpCache]
  [httpCache.polls]
    disable = false
    low = "5m"
    high = "1s"
  [httpCache.cache]
    [httpCache.cache.for]
      includes = ["**"]
      excludes = []

[markup]

Markup renderer configuration:

[markup]
  [markup.goldmark]
    [markup.goldmark.extensions]
      definitionList = true
      footnote = true
      linkify = true
      linkifyProtocol = "https"
      strikethrough = true
      table = true
      taskList = true
      typographer = true
      [markup.goldmark.extensions.cjk]
        enable = false
        eastAsianLineBreaks = false
        eastAsianLineBreaksStyle = "simple"
      [markup.goldmark.extensions.extras]
        [markup.goldmark.extensions.extras.delete]
          enable = false
        [markup.goldmark.extensions.extras.insert]
          enable = false
        [markup.goldmark.extensions.extras.mark]
          enable = false
        [markup.goldmark.extensions.extras.subscript]
          enable = false
        [markup.goldmark.extensions.extras.superscript]
          enable = false
      [markup.goldmark.extensions.passthrough]
        enable = false
        [markup.goldmark.extensions.passthrough.delimiters]
          block = []
          inline = []
    [markup.goldmark.parser]
      autoHeadingID = true
      autoHeadingIDType = "github"
      wrapStandAloneImageInParagraph = true
      [markup.goldmark.parser.attribute]
        block = false
        title = true
    [markup.goldmark.renderer]
      hardWraps = false
      unsafe = false
      xhtml = false
    [markup.goldmark.renderHooks]
      [markup.goldmark.renderHooks.image]
        enableDefault = false
      [markup.goldmark.renderHooks.link]
        enableDefault = false

  [markup.highlight]
    anchorLineNos = false
    codeFences = true
    guessSyntax = false
    hl_Lines = ""
    hl_inline = false
    lineAnchors = ""
    lineNoStart = 1
    lineNos = false
    lineNumbersInTable = true
    noClasses = true
    noHl = false
    style = "monokai"
    tabWidth = 4
    wrapperClass = "highlight"

  [markup.tableOfContents]
    startLevel = 2
    endLevel = 3
    ordered = false

  [markup.asciidocExt]
    backend = "html5"
    extensions = []
    failureLevel = "fatal"
    noHeaderOrFooter = true
    preserveTOC = false
    safeMode = "unsafe"
    sectionNumbers = false
    trace = false
    verbose = false
    workingFolderCurrent = false
    [markup.asciidocExt.attributes]

[imaging]

Image processing defaults:

[imaging]
  anchor = "smart"             # Crop anchor: smart, center, topleft, etc.
  bgColor = "#ffffff"
  hint = "photo"               # WebP encoding hint: photo, picture, drawing, icon, text
  quality = 75                 # JPEG/WebP quality (1-100)
  resampleFilter = "box"       # Lanczos, CatmullRom, MitchellNetravali, Linear, Box, NearestNeighbor
  [imaging.exif]
    disableDate = false
    disableLatLong = false
    excludeFields = ""
    includeFields = ""

[minify]

Minification settings (tdewolff/minify):

[minify]
  disableCSS = false
  disableHTML = false
  disableJS = false
  disableJSON = false
  disableSVG = false
  disableXML = false
  minifyOutput = false
  [minify.tdewolff]
    [minify.tdewolff.css]
      keepCSS2 = true
      precision = 0
    [minify.tdewolff.html]
      keepComments = false
      keepConditionalComments = true
      keepDefaultAttrVals = true
      keepDocumentTags = true
      keepEndTags = true
      keepQuotes = false
      keepWhitespace = false
    [minify.tdewolff.js]
      keepVarNames = false
      precision = 0
      version = 2022
    [minify.tdewolff.json]
      keepNumbers = false
      precision = 0
    [minify.tdewolff.svg]
      keepComments = false
      precision = 0
    [minify.tdewolff.xml]
      keepWhitespace = false

Caution

Issue #14760: Hugo's minifier can break JavaScript const initialization order in certain edge cases. If you experience runtime JS errors after enabling minifyOutput, test with disableJS = true to isolate.

Issue #14669: The SVG minifier can corrupt Alpine.js binding attributes (e.g., x-bind, @click). Disable SVG minification if using Alpine.js inline in SVGs.

[server]

Dev server configuration:

[server]
  [[server.headers]]
    for = "/**"
    [server.headers.values]
      X-Frame-Options = "DENY"
      Content-Security-Policy = "default-src 'self'"
  [[server.redirects]]
    from = "/old-path"
    to = "/new-path"
    status = 301

[pagination]

[pagination]
  pagerSize = 10
  path = "page"
  disableAliases = false

[sitemap]

[sitemap]
  changeFreq = ""
  disable = false
  filename = "sitemap.xml"
  priority = -1

[taxonomies]

[taxonomies]
  category = "categories"
  tag = "tags"
  # Add custom taxonomies:
  # series = "series"

Related content engine:

[related]
  includeNewer = false
  threshold = 80
  toLower = false
  [[related.indices]]
    applyFilter = false
    cardinalityThreshold = 0
    name = "keywords"
    pattern = ""
    toLower = false
    type = "basic"
    weight = 100
  [[related.indices]]
    name = "date"
    type = "basic"
    weight = 10

[frontmatter]

Front matter field mapping:

[frontmatter]
  date = ["date", "publishDate", "lastmod"]
  expiryDate = ["expiryDate"]
  lastmod = [":git", "lastmod", "date", "publishDate"]
  publishDate = ["publishDate", "date"]

The :git token uses Git commit timestamps (requires enableGitInfo = true).

[outputs]

Output format assignments by page kind:

[outputs]
  home = ["HTML", "RSS"]
  section = ["HTML", "RSS"]
  taxonomy = ["HTML", "RSS"]
  term = ["HTML", "RSS"]
  page = ["HTML"]

[outputFormats]

Custom output format definitions:

[outputFormats]
  [outputFormats.Calendar]
    mediaType = "text/calendar"
    baseName = "events"
    isPlainText = true
    protocol = "webcal://"

[mediaTypes]

Custom media type definitions:

[mediaTypes]
  [mediaTypes."application/calendar+json"]
    suffixes = ["jcal"]

[segments]

Segmented/partial builds:

[segments]
  [segments.docs]
    [[segments.docs.includes]]
      kind = "page"
      path = "/docs/**"
    [[segments.docs.excludes]]
      lang = "de"

Use with renderSegments = ["docs"] for partial site builds.

3.5 Module Configuration

[module]
  proxy = "direct"
  noProxy = "none"
  private = "*.*"
  noVendor = ""
  vendorClosest = false
  workspace = ""
  replacements = ""

  [module.hugoVersion]
    min = ""
    max = ""
    extended = false

  [[module.imports]]
    path = "github.com/user/theme"
    disable = false
    ignoreConfig = false
    ignoreImports = false
    noMounts = false
    noVendor = false

    [[module.imports.mounts]]
      source = "assets"
      target = "assets"
      lang = ""
      includeFiles = ""
      excludeFiles = ""

  [[module.mounts]]
    source = "content"
    target = "content"
    lang = ""
    includeFiles = ""
    excludeFiles = ""

Note

When you define any module.mounts, the default mounts for that component type are replaced entirely. If you mount a custom static directory, you must also explicitly mount the default static/ if you want to keep it.

3.6 Language Configuration

defaultContentLanguage = "en"

[languages]
  [languages.en]
    weight = 1
    title = "My Site"
  [languages.fr]
    weight = 2
    title = "Mon Site"
    [languages.fr.params]
      description = "Description en francais"

3.7 Privacy Configuration

Controls third-party service data transmission:

[privacy]
  [privacy.disqus]
    disable = false
  [privacy.googleAnalytics]
    disable = false
  [privacy.instagram]
    disable = false
    simple = false
  [privacy.twitter]
    disable = false
    enableDNT = false
    simple = false
  [privacy.youtube]
    disable = false
    privacyEnhanced = false

3.8 Services Configuration

[services]
  [services.disqus]
    shortname = ""
  [services.googleAnalytics]
    ID = ""
  [services.instagram]
    accessToken = ""
    disableInlineCSS = false

3.9 Content Types Configuration

[contentTypes]
  [contentTypes."text/markdown"]
    [contentTypes."text/markdown".markup]
      # Override markup settings per content type

3.10 Environment Variables

Hugo recognizes these environment variables:

Variable Purpose
HUGO_ENVIRONMENT / HUGO_ENV Build environment name
HUGO_NUMWORKERMULTIPLIER Worker goroutine multiplier (default: CPU count)
HUGO_MEMORYLIMIT Memory limit in MB
HUGO_FILE_LOG_FORMAT Custom log format string
HUGO_BUILD_TAGS Build tags for module compilation
HUGO_TESTRUN Enable test run mode
NODE_PATH Node.js module resolution path
DART_SASS_BINARY Path to Dart Sass binary
NO_COLOR Disable colored output (standard)
CI Signals CI environment

Any config key can be set via env var with the HUGO_ prefix. Nested keys use underscores: HUGO_PARAMS_AUTHOR=John sets params.author.

3.11 Deployment Configuration

[deployment]
  invalidateCDN = true      # Default: true
  maxDeletes = 256           # Default: 256 (-1 for unlimited)
  workers = 10               # Default: 10

  [[deployment.targets]]
    name = "production"
    URL = "s3://my-bucket?region=us-east-1"
    cloudFrontDistributionID = "E1234567890ABC"

  [[deployment.targets]]
    name = "staging"
    URL = "gs://staging-bucket"

  [[deployment.matchers]]
    pattern = "^.+\\.(js|css|svg|ttf|woff|woff2)$"
    cacheControl = "max-age=31536000, no-transform, public"
    gzip = true

  [[deployment.matchers]]
    pattern = "^.+\\.(html|xml|json)$"
    cacheControl = "max-age=3600, no-transform, public"
    gzip = true

  [[deployment.matchers]]
    pattern = "^.+\\.(png|jpg|jpeg|gif|webp)$"
    cacheControl = "max-age=31536000, no-transform, public"
    gzip = false

4. Deployment & Scaling

4.1 Built-in Deployment (hugo deploy)

Hugo includes a cloud deployment system (requires the withdeploy build tag). The deployment engine uses gocloud.dev for provider-agnostic cloud storage.

Supported target URL schemes:

Scheme Provider Example
s3:// AWS S3 s3://bucket?region=us-east-1
gs:// Google Cloud Storage gs://bucket
azblob:// Azure Blob Storage azblob://container
# Deploy to the default (first) target
hugo deploy

# Deploy to a named target
hugo deploy --target staging

# Dry run (show what would change)
hugo deploy --dryRun

# Force re-upload all files
hugo deploy --force

# Confirm before deleting
hugo deploy --confirm

# Limit deletions (override config)
hugo deploy --maxDeletes 100

# Invalidate CDN only (no upload)
hugo deploy --invalidateCDN

The deployment process:

  1. Computes local file checksums
  2. Lists remote objects
  3. Diffs local vs. remote
  4. Uploads new/changed files with configured headers
  5. Optionally deletes remote files not in local (up to maxDeletes)
  6. Optionally invalidates CloudFront CDN (AWS SDK v2)

4.2 CI/CD Deployment Patterns

GitHub Actions

name: Deploy Hugo
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
          fetch-depth: 0     # Needed for enableGitInfo

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Build
        run: hugo --minify --environment production

      - name: Deploy
        run: hugo deploy --target production
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

GitLab CI

stages:
  - build
  - deploy

build:
  stage: build
  image: klakegg/hugo:ext-alpine
  script:
    - hugo --minify
  artifacts:
    paths:
      - public/

deploy:
  stage: deploy
  script:
    - rsync -avz --delete public/ user@server:/var/www/html/
  only:
    - main

4.3 Web Server Configuration

Nginx

server {
    listen 443 ssl http2;
    server_name example.com;

    root /var/www/hugo/public;
    index index.html;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Immutable assets
    location ~* \.(js|css|svg|woff2?|ttf|eot|ico)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Images
    location ~* \.(png|jpg|jpeg|gif|webp|avif)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # HTML — short cache for content freshness
    location ~* \.html$ {
        expires 1h;
        add_header Cache-Control "public, must-revalidate";
    }

    # Clean URLs — try file, then directory, then 404
    location / {
        try_files $uri $uri/index.html =404;
    }

    # Custom 404
    error_page 404 /404.html;
}

Caddy

example.com {
    root * /var/www/hugo/public
    file_server
    try_files {path} {path}/index.html
    handle_errors {
        rewrite * /404.html
        file_server
    }
    header /assets/* Cache-Control "public, max-age=31536000, immutable"
}

4.4 Docker Deployment

# Multi-stage build
FROM golang:1.25-alpine AS builder
RUN apk add --no-cache git gcc g++ musl-dev
RUN go install github.com/gohugoio/hugo@latest

FROM alpine:3.20
COPY --from=builder /go/bin/hugo /usr/local/bin/hugo
WORKDIR /site
COPY . .
RUN hugo --minify

FROM nginx:alpine
COPY --from=1 /site/public /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

4.5 Scaling Considerations

Hugo is a build-time tool. "Scaling" means optimizing build speed and managing build infrastructure:

  1. Parallel builds. Set HUGO_NUMWORKERMULTIPLIER to tune goroutine count. The default (number of CPUs) is usually optimal.
  2. Segmented builds. For very large sites, use segments config to build subsections independently, then merge output.
  3. Cached resources. The resources/_gen/ directory holds processed images and assets. Persist this across CI runs for dramatic speed-ups.
  4. Content-addressable caching. Hugo caches transformed resources by content hash. Identical inputs never reprocess.
  5. Memory management. Set HUGO_MEMORYLIMIT for memory-constrained environments (CI runners, containers).

5. Operations

5.1 Development Server

# Basic dev server
hugo server

# With drafts, on a custom port, binding to all interfaces
hugo server --buildDrafts --port 1313 --bind 0.0.0.0

# With TLS (auto-generates certs via mkcert)
hugo server --tlsAuto

# Navigate directly to a changed page
hugo server --navigateToChanged

# Disable fast render (full rebuilds on every change)
hugo server --disableFastRender

# Render to disk (useful for debugging)
hugo server --renderToDisk

# With custom environment
hugo server --environment staging

The dev server features:

  • LiveReload via WebSocket (injected into HTML, managed by the livereload/ package)
  • File watching via fsnotify (with poll fallback for network filesystems)
  • Fast render mode: only re-renders changed pages and their dependencies
  • TLS support via bep/mclib (mkcert integration)

5.2 Build Commands

# Production build
hugo --minify --environment production

# With specific config
hugo --config hugo.toml,custom.toml

# With specific config directory
hugo --configDir config

# Build with memory/timing stats
hugo --templateMetrics --templateMetricsHints

# Build specific content segments
hugo --renderSegments docs,blog

# Verbose logging
hugo --logLevel debug

# Print path warnings
hugo --printPathWarnings --printI18nWarnings --printUnusedTemplates

# Build with profiling
hugo --profile-cpu cpu.pprof --profile-mem mem.pprof --profile-mutex mutex.pprof --trace trace.out

5.3 Module Management

# Initialize a new module
hugo mod init github.com/user/mysite

# Add a module dependency
hugo mod get github.com/user/theme

# Update all modules
hugo mod get -u

# Update a specific module
hugo mod get -u github.com/user/theme

# Tidy module dependencies
hugo mod tidy

# Vendor modules (copy into _vendor/)
hugo mod vendor

# Show module graph
hugo mod graph

# Clean module cache
hugo mod clean

# Verify module checksums
hugo mod verify

# Create npm package.json from modules
hugo mod npm pack

5.4 Content Management Commands

# Create new content
hugo new content posts/my-post.md

# Create new site
hugo new site mysite

# Create new theme
hugo new theme mytheme

# List all content
hugo list all

# List drafts
hugo list drafts

# List expired content
hugo list expired

# List future-dated content
hugo list future

# Convert content to different front matter format
hugo convert toTOML
hugo convert toYAML
hugo convert toJSON

5.5 Build Lock File

Hugo creates .hugo_build.lock during builds to prevent concurrent builds from corrupting output. Disable with noBuildLock = true if your CI system handles concurrency externally.

5.6 Template Debugging

# Show template execution metrics
hugo --templateMetrics

# Show template metrics with hints
hugo --templateMetricsHints

# Identify unused templates
hugo --printUnusedTemplates

5.7 File Watching Behavior

Hugo uses fsnotify for file system notifications, with a poll-based fallback (enabled with --poll). The watcher:

  1. Monitors content/, data/, layouts/, assets/, static/, i18n/, and config files
  2. Debounces rapid successive changes
  3. Identifies the changed component type (content, template, asset, config)
  4. Triggers targeted rebuilds based on dependency tracking
  5. Sends LiveReload notification to connected browsers

Config changes trigger a full site rebuild. Template changes rebuild all pages using that template. Content changes rebuild only the affected page and its dependents.

5.8 Cache Management

Hugo maintains several caches:

Cache Location Purpose
File cache cacheDir (OS default or configured) Remote resources, CSV/JSON data
Resource cache resources/_gen/ Processed images, compiled Sass, bundled JS
Module cache cacheDir/modules/ Downloaded Go modules
Dynamic cache In-memory Runtime page/template data
HTTP cache Configured per-resource HTTP response caching
# Clear all caches
hugo mod clean --all

# Ignore cache for a build
hugo --ignoreCache

Warning

Issue #14165: The :resourceDir token in file cache configuration may not resolve correctly in all contexts. If you encounter unexpected cache behavior, specify absolute paths instead of using the token.


6. Performance

6.1 Build Performance Optimization

Template Optimization

  1. Use partialCached for expensive partials. The first argument is the template name, subsequent arguments form the cache key:

    {{ partialCached "nav.html" . .Section }}
    
  2. Avoid unnecessary .Render. Each .Render call invokes the full template pipeline. Use direct field access when possible.

  3. Minimize resources.Get in loops. Fetch resources once and pass them to partials.

  4. Profile templates.

    hugo --templateMetrics --templateMetricsHints
    

    This prints execution time, call count, and cumulative cache stats per template.

Image Processing

  1. Process images in the page bundle. Avoid global resource lookups.
  2. Use appropriate quality settings. Default 75 is good for JPEG; lower for thumbnails.
  3. Prefer WebP output for modern browsers (smaller files, faster builds after initial processing).
  4. Cache resources/_gen/ across CI builds. Image processing is the single largest time cost in most Hugo sites.

Content Organization

  1. Page bundles (leaf/branch) reduce filesystem lookups.
  2. Headless bundles for data-only content avoid rendering overhead.
  3. mainSections explicitly set this to avoid expensive auto-detection on large sites.

6.2 Memory Optimization

# Set memory limit (MB)
export HUGO_MEMORYLIMIT=4096

# Reduce worker count for memory-constrained environments
export HUGO_NUMWORKERMULTIPLIER=1

Hugo's dynamic cache (cache/dynacache/) automatically evicts entries under memory pressure. The file cache (cache/filecache/) offloads large resources to disk.

6.3 Build Profiling

# CPU profiling
hugo --profile-cpu cpu.pprof
go tool pprof cpu.pprof

# Memory profiling
hugo --profile-mem mem.pprof
go tool pprof -alloc_space mem.pprof

# Trace
hugo --trace trace.out
go tool trace trace.out

6.4 Incremental Rebuild Performance

The identity/ package implements fine-grained dependency tracking. During hugo server, when a file changes:

  1. The watcher identifies the file type and path
  2. hugobuilder.go maps the change to affected identities
  3. Only pages depending on changed identities are re-rendered
  4. For template changes, all pages using that template are rebuilt
  5. For content changes, only the page and its list pages are rebuilt

This makes rebuilds nearly instantaneous for single-page edits on large sites.


7. Security

7.1 Security Configuration

Hugo's security model restricts external command execution and HTTP access. Configuration lives in [security] (implemented in config/security/).

[security]
  enableInlineShortcodes = false

  [security.exec]
    allow = '^(dart-sass-embedded|go|git|npx?|postcss|tailwindcss)$'
    osEnv = '(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM|HUGO_|HOME|LANG|USER|LOGNAME)$'

  [security.funcs]
    getenv = '^HUGO_'

  [security.http]
    methods = '(?i)GET|POST'
    urls = '.*'
    mediaTypes = ''

Exec Whitelist

The security.exec.allow regex controls which external commands Hugo may execute. The default whitelist includes only:

  • dart-sass-embedded — Sass/SCSS compilation
  • go — Module operations
  • git — GitInfo and module operations
  • npm / npx — Node.js package tools
  • postcss — CSS post-processing
  • tailwindcss — Tailwind CSS

Any command not matching this regex will be blocked with a security error.

Caution

Never use a permissive pattern like .* for security.exec.allow. Untrusted themes or modules could execute arbitrary commands on your system. Only whitelist specific binaries you actually use.

Environment Variable Filtering

security.exec.osEnv controls which host environment variables are visible to executed commands. The default restricts to PATH-like variables, temp directories, TERM, and HUGO_* prefixed variables.

security.funcs.getenv controls which env vars are accessible via the os.Getenv template function. Default: only HUGO_* prefixed variables.

HTTP Restrictions

security.http.urls restricts which URLs Hugo can fetch (for resources.GetRemote, getJSON, getCSV). Default allows all URLs. Lock down in production:

[security.http]
  urls = '^https://(api\.github\.com|fonts\.googleapis\.com)/.*$'

7.2 Inline Shortcodes

Inline shortcodes (enableInlineShortcodes) allow defining shortcodes directly in content files. This is disabled by default because it allows content authors to execute Go template code, which has access to all template functions including os.Getenv and resources.GetRemote.

Warning

Only enable enableInlineShortcodes when you fully trust all content authors. In multi-author or user-generated content scenarios, this is a privilege escalation vector.

7.3 Markup Safety

Goldmark's unsafe renderer option (markup.goldmark.renderer.unsafe) controls whether raw HTML in Markdown is passed through. Default: false (raw HTML is stripped).

7.4 Dev Server Security

The development server is for local development only:

  • Binds to localhost by default (change with --bind)
  • LiveReload WebSocket is unauthenticated
  • The /__stop endpoint can halt the server (internal use)
  • TLS via mkcert generates locally-trusted certificates

Never expose hugo server to untrusted networks.

7.5 Module Supply Chain Security

  1. Vet third-party themes before use. Themes have full template access, which means they can call os.Getenv, resources.GetRemote, and any whitelisted external commands.
  2. Pin module versions. Use go.sum for integrity verification.
  3. Review go.sum changes in PRs — supply chain attack vector.
  4. Restrict HTTP URLs in production config.
  5. Audit getenv access — theme code should not read host secrets.
  6. Use hugo mod vendor to snapshot dependencies locally.
  7. Set module.hugoVersion to enforce minimum/maximum Hugo version requirements in module configurations.

8. Developer Internals

8.1 Repository Structure

hugo/
├── main.go                      Entry point → commands.Execute()
├── go.mod / go.sum              Go module dependencies
├── magefile.go                  Mage build system (Hugo, Install, Test, etc.)
├── commands/                    CLI layer (18 files, 170K chars)
│   ├── commands.go              newExec() — wires all subcommands
│   ├── commandeer.go            rootCommand, flag definitions, config loading
│   ├── hugobuilder.go           Build orchestration, watch, rebuild
│   ├── server.go                Dev server, LiveReload, TLS, file watching
│   ├── config.go                Config-related commands
│   ├── convert.go               Content format conversion
│   ├── deploy.go                Cloud deployment command
│   ├── gen.go                   Code generation commands
│   ├── import.go                Import from Jekyll, etc.
│   ├── list.go                  Content listing commands
│   ├── mod.go                   Module management commands
│   └── new.go                   Content/site/theme creation
├── config/                      Configuration management (12 files, 55K chars)
│   ├── allconfig/               Full config structs (Config, RootConfig, Configs)
│   │   ├── allconfig.go         Master config definition
│   │   ├── configlanguage.go    Per-language config
│   │   └── load.go              Config file loading/merging
│   ├── security/                Security policy (exec, HTTP, func whitelists)
│   ├── privacy/                 Privacy config (disqus, analytics, social)
│   ├── services/                Third-party service config
│   └── commonConfig/            Shared config (sitemap, build, taxonomies)
├── hugolib/                     Core site building engine (95 files, 1M chars)
│   ├── hugo_sites.go            HugoSites — top-level build orchestrator
│   ├── hugo_sites_build.go      Build pipeline stages
│   ├── site.go                  Single site representation
│   ├── page*.go                 Page loading, rendering, collections
│   ├── content_map*.go          Content map construction
│   ├── sitesmatrix/             Multi-dimensional site matrix (lang x ver x role)
│   ├── filesystems/             Virtual filesystem orchestration
│   ├── doctree/                 Document tree data structures
│   ├── pagesfromdata/           Data-driven page generation
│   ├── segments/                Partial/segmented builds
│   ├── versions/                Content versioning
│   ├── roles/                   Content role system
│   └── paths/                   Path processing
├── hugofs/                      Virtual filesystem layer (23 files, 115K chars)
│   ├── rootmapping_fs.go        Root-mapping overlay filesystem
│   ├── component_fs.go          Component-based filesystem
│   ├── filter_fs.go             Filtered filesystem
│   ├── glob/                    Glob matching
│   ├── files/                   File classifiers
│   └── decorators/              FS decorators (read-only, no-stat, etc.)
├── resources/                   Resource pipeline
│   ├── page/                    Page model (49 files, 288K chars)
│   │   ├── page.go              Page interface definitions
│   │   ├── pagination.go        Pagination system
│   │   ├── permalinks.go        Permalink generation
│   │   └── page_matcher.go      Page matching/filtering
│   ├── resource/                Resource interfaces and base types
│   ├── resource_transformers/   Transformation pipeline
│   │   ├── js/                  JavaScript bundling (esbuild)
│   │   ├── cssjs/               CSS/PostCSS processing
│   │   ├── dartsass/            Dart Sass compilation
│   │   ├── babel/               Babel transpilation
│   │   ├── tocss/               Sass/SCSS to CSS
│   │   ├── minifier/            Resource minification
│   │   └── integrity/           SRI hash generation
│   └── images/                  Image processing (resize, crop, filters)
├── markup/                      Content rendering
│   ├── goldmark/                Goldmark Markdown (8 files, 94K chars)
│   │   ├── goldmark.go          Main renderer
│   │   ├── extensions/          Custom extensions
│   │   └── render_hooks/        Render hooks (links, images, code blocks)
│   ├── asciidocext/             AsciiDoc via asciidoctor
│   ├── rst/                     reStructuredText
│   ├── org/                     Org mode
│   ├── pandoc/                  Pandoc
│   ├── highlight/               Syntax highlighting (Chroma)
│   └── tableofcontents/         TOC generation
├── tpl/                         Template functions (50+ namespaces)
│   ├── tplimpl/                 Template store & engine (16 files, 200K chars)
│   │   ├── template.go          Template execution
│   │   ├── templatestore.go     Template storage and lookup
│   │   └── embedded/            Embedded templates (RSS, sitemap, robots, etc.)
│   ├── collections/             Collection functions (where, slice, etc.)
│   ├── strings/                 String manipulation
│   ├── math/                    Math functions
│   ├── time/                    Time functions
│   ├── crypto/                  Crypto functions (md5, sha, hmac)
│   ├── encoding/                Encoding functions (base64, jsonify)
│   ├── transform/               Transform functions (highlight, emojify, etc.)
│   ├── urls/                    URL functions
│   ├── os/                      OS functions (getenv, readDir, readFile, stat)
│   ├── resources/               Resource functions (get, fingerprint, etc.)
│   ├── css/                     CSS functions (PostCSS, Sass)
│   ├── js/                      JS functions (build/esbuild)
│   ├── images/                  Image functions
│   ├── diagrams/                Diagram functions
│   ├── fmt/                     Formatting functions
│   ├── compare/                 Comparison functions
│   ├── cast/                    Type casting functions
│   ├── debug/                   Debug functions
│   ├── hugo/                    Hugo metadata functions
│   ├── inflect/                 Inflection functions
│   ├── lang/                    Language functions
│   ├── openapi/                 OpenAPI functions
│   ├── page/                    Page functions
│   ├── partials/                Partial functions
│   ├── path/                    Path functions
│   ├── reflect/                 Reflection functions
│   ├── safe/                    Safe output functions
│   ├── site/                    Site functions
│   └── templates/               Template functions
├── modules/                     Hugo Modules (10 files, 93K chars)
│   ├── client.go                Module client (Go module operations)
│   ├── collect.go               Module collection/graph building
│   ├── config.go                Module configuration
│   └── npm/                     NPM integration (package.json generation)
├── deploy/                      Cloud deployment (5 files, 59K chars)
│   ├── deploy.go                Deployment engine (S3, GCS, Azure)
│   ├── deployconfig/            Deployment configuration
│   └── cloudfront.go            CloudFront CDN invalidation
├── parser/                      Content parsing
│   ├── pageparser/              Front matter + content parsing (13 files, 71K)
│   │   ├── pageparser.go        Page parser state machine
│   │   ├── pagelexer.go         Lexer for front matter detection
│   │   └── item.go              Parsed item types
│   └── metadecoders/            Format decoders (6 files, 27K)
│       └── decoder.go           TOML/YAML/JSON/XML/CSV/ORG decoding
├── cache/                       Caching subsystem
│   ├── filecache/               File-based cache (7 files, 42K chars)
│   ├── dynacache/               Dynamic in-memory cache
│   └── httpcache/               HTTP response cache
├── livereload/                  WebSocket live reload (4 files, 163K chars)
├── identity/                    Dependency tracking and cache invalidation
├── publisher/                   Output writing
├── output/                      Output format definitions (HTML, RSS, JSON, etc.)
├── media/                       Media type definitions
├── navigation/                  Menu system
├── related/                     Related content engine
├── source/                      Source file handling
├── transform/                   Output transformation (URL replacement, meta)
├── watcher/                     File system watching (fsnotify + poll fallback)
├── minifiers/                   Minification (HTML/CSS/JS/JSON/SVG/XML)
├── internal/warpc/              WebAssembly runtime (wazero) for KaTeX math
├── common/                      Shared utilities
│   ├── paths/                   Path manipulation
│   ├── herrors/                 Error types with file position info
│   ├── loggers/                 Logging (bep/logg)
│   ├── hashing/                 Content hashing
│   ├── hugo/                    Hugo version info
│   ├── maps/                    Map utilities
│   └── types/                   Common types
├── snap/                        Snap package definition
├── scripts/docker/              Docker build scripts
└── testscripts/                 txtar-based integration tests

8.2 Architecture Deep Dive

8.2.1 CLI Layer (commands/)

Hugo uses spf13/cobra wrapped in bep/simplecobra for a cleaner command registration pattern. The flow:

  1. commands.go via newExec() creates the root command and wires subcommands
  2. commandeer.go defines rootCommand with all global flags
  3. Each subcommand file (server.go, deploy.go, etc.) implements the simplecobra.Commander interface
  4. Flag values are resolved against config after parsing

The hugobuilder struct in hugobuilder.go is the build orchestrator; it manages the build lifecycle, file watching, and incremental rebuilds.

8.2.2 Configuration System (config/)

The config system uses a layered merge approach:

CLI flags (highest priority)
    ↓
Environment variables (HUGO_*)
    ↓
Environment-specific config (config/{env}/)
    ↓
Main config file (hugo.toml)
    ↓
Theme/module defaults (lowest priority)

Key types in config/allconfig/:

  • RootConfig — all top-level config fields
  • Config — complete config for one language
  • Configs — all language configs plus the base config
  • ConfigCompiled — pre-computed values for performance

8.2.3 Virtual Filesystem (hugofs/)

Hugo builds a layered virtual filesystem for content composition:

OverlayFS (project + theme merge)
    ↓
ComponentFS (content, layouts, assets, static, data, i18n)
    ↓
FilterFS (include/exclude patterns)
    ↓
RootMappingFS (module mount remapping)
    ↓
BasePathFS / OS FS (actual disk)

This allows themes and modules to contribute content, layouts, and assets that the project can selectively override. The afero filesystem abstraction underpins the implementation.

8.2.4 Site Building Engine (hugolib/)

This is the largest package (approximately 1M chars across 95 files). Key components:

  • HugoSites — orchestrates multi-site builds (multilingual). Manages the full build pipeline: init, content load, assemble, render, finalize.
  • Site — single language/version/role site. Holds page collections, menus, taxonomies.
  • sitesmatrix/ — manages the language x version x role matrix, determining which sites exist and how they relate.
  • doctree/ — tree data structure for the document hierarchy. Nodes represent pages, branches represent sections.
  • pagesfromdata/ — generates pages from YAML/JSON/TOML data files, enabling data-driven content.
  • segments/ — supports building only specified content segments for faster partial builds in development.
  • versions/ — content versioning system allowing multiple versions of documentation to coexist.
  • roles/ — content role system (e.g., separating user/admin content).

8.2.5 Page Model (resources/page/)

Pages are Hugo's central abstraction. The page model includes:

  • Page interface — methods for content, metadata, rendering
  • Pagination — configurable pager with URL generation
  • Permalinks — pattern-based URL generation (:year, :title, :sections, :contentbasename, etc.)
  • Page matching — glob and regex-based page selection
  • Cascade — config inheritance down the page tree

Note

Issue #14325: :contentbasename in permalink patterns is broken for taxonomy pages since v0.153. Use :slug as a workaround for taxonomy permalinks.

8.2.6 Resource Pipeline (resources/resource_transformers/)

The resource transformation pipeline is designed as a chain of transformers:

Source Resource
    → ToCSS (Sass/SCSS compilation)
    → PostCSS
    → js.Build (esbuild bundling)
    → Minify
    → Fingerprint (content hash)
    → Integrity (SRI hash)
    → Published Resource

Each transformer:

  1. Accepts a Resource input
  2. Produces a new Resource output (immutable)
  3. Caches by content hash in resources/_gen/
  4. Supports pipeline chaining via method calls

JavaScript bundling uses esbuild directly (compiled into Hugo):

{{ $js := resources.Get "js/main.js" | js.Build (dict
    "targetPath" "js/app.js"
    "minify" true
    "target" "es2020"
    "externals" (slice "react" "react-dom")
    "defines" (dict "process.env.NODE_ENV" "\"production\"")
    "sourcemap" "external"
) }}

Tip

Issue #14254: js.Build does not natively support different options per output format. Workaround: use conditional logic in templates to apply different js.Build configurations based on the current output format.

Sass/SCSS compilation uses Dart Sass (external binary):

{{ $css := resources.Get "scss/main.scss" | toCSS (dict
    "targetPath" "css/style.css"
    "outputStyle" "compressed"
    "includePaths" (slice "node_modules")
) }}

8.2.7 Markup System (markup/)

Hugo supports multiple content formats through a pluggable renderer architecture:

Renderer Package Implementation
Markdown (Goldmark) markup/goldmark/ Native Go, compiled in
AsciiDoc markup/asciidocext/ External asciidoctor binary
reStructuredText markup/rst/ External rst2html binary
Org Mode markup/org/ Native Go (go-org)
Pandoc markup/pandoc/ External pandoc binary
HTML (pass-through) No transformation

Goldmark is the default and most feature-rich. It supports:

  • GitHub-Flavored Markdown (tables, strikethrough, task lists, autolinks)
  • Footnotes, definition lists, typographer (smart quotes/dashes)
  • Math rendering via KaTeX (WebAssembly in internal/warpc/)
  • Render hooks for custom link, image, heading, and code block rendering
  • Attribute blocks for adding classes/IDs to elements
  • Passthrough delimiters for math notation

8.2.8 Template Engine (tpl/)

Hugo uses Go's html/template and text/template (with a forked version for additional features). The template system provides 50+ function namespaces.

Template Store (tpl/tplimpl/):

  • Templates are loaded from layouts/ directories (project + themes)
  • Lookup order respects page kind, output format, language, and type
  • Embedded templates provide defaults (RSS, sitemap, robots.txt, etc.)
  • Template transformation applies security sandboxing

Key Template Namespaces:

Namespace Key Functions
collections where, slice, dict, first, last, sort, group, union, intersect, complement, symdiff, append, merge
strings split, replace, replaceRE, trim, lower, upper, title, truncate, hasPrefix, hasSuffix, contains, containsAny
transform highlight, emojify, markdownify, plainify, htmlEscape, htmlUnescape, remarshal, unmarshal
resources Get, GetRemote, GetMatch, Match, ByType, Copy, Concat, FromString, PostCSS, ToCSS, Fingerprint, Minify
os Getenv, ReadDir, ReadFile, Stat, FileExists
crypto MD5, SHA1, SHA256, HMAC, FNV32a
encoding Base64Decode, Base64Encode, Jsonify
urls Parse, AbsURL, RelURL, AbsLangURL, RelLangURL, Ref, RelRef, URLize, Anchorize
fmt Print, Printf, Println, Errorf, Erroridf, Warnidf, Warnf
images Filter, Config, Process, Overlay, Text, Brightness, ColorBalance, Contrast, Gamma, GaussianBlur, Grayscale, Hue, Invert, Opacity, Pixelate, Saturation, Sepia, Sigmoid, UnsharpMask
js Build (esbuild integration)
css PostCSS, TailwindCSS, Sass
diagrams Goat (ASCII to SVG diagrams)
debug Dump, Timer
hugo Version, Environment, IsProduction, IsServer, Generator, Deps, GoVersion, IsMultiHost, IsMultilingual

8.2.9 Module System (modules/)

Hugo Modules are built on Go Modules. The module client:

  1. Reads go.mod and go.sum for dependency management
  2. Resolves module imports recursively (supports module graph)
  3. Applies mount configuration to map module directories
  4. Supports vendoring (_vendor/) for offline builds
  5. Integrates with npm via hugo mod npm pack (generates package.json)

Module lifecycle:

hugo mod init → go.mod created
hugo mod get  → dependency added/updated
hugo mod tidy → unused dependencies removed
hugo mod vendor → dependencies copied to _vendor/
hugo mod verify → checksums validated

8.2.10 Deployment System (deploy/)

The deployment system (build tag withdeploy) uses gocloud.dev for provider-agnostic cloud storage:

  1. Computes local file checksums
  2. Lists remote objects
  3. Diffs local vs. remote
  4. Uploads new/changed files with configured headers
  5. Optionally deletes remote files not in local (up to maxDeletes)
  6. Optionally invalidates CloudFront CDN (AWS SDK v2)

8.2.11 Identity and Dependency Tracking (identity/)

The identity package enables Hugo's incremental rebuild system:

  • Every page, template, partial, and resource has an identity
  • Dependencies between identities are tracked during rendering
  • When a source changes, only affected identities are invalidated
  • This drives hugo server's "fast render" mode

8.2.12 WebAssembly Integration (internal/warpc/)

Hugo embeds a wazero-based WebAssembly runtime for KaTeX math rendering. This avoids requiring Node.js for LaTeX math while keeping the single-binary deployment model.

8.2.13 Caching Architecture (cache/)

Hugo uses three caching tiers:

  1. File cache (cache/filecache/) — persistent on-disk cache for remote resources, CSV/JSON fetches, and images. Configurable TTL via maxAge.
  2. Dynamic cache (cache/dynacache/) — in-memory cache for runtime data. Uses eviction under memory pressure (controlled by HUGO_MEMORYLIMIT).
  3. HTTP cache (cache/httpcache/) — conditional request caching for remote resources with ETags and Last-Modified support.

8.2.14 Output Format System (output/)

Hugo supports multiple output formats per page. Built-in formats include HTML, RSS, JSON, AMP, Calendar, CSV, Markdown, Robots, Sitemap, and WebAppManifest. Custom formats are defined in [outputFormats] config and assigned to page kinds via [outputs].

Each output format specifies:

  • Media type
  • Base name and suffix
  • Protocol
  • Whether it's plain text
  • Permalink behavior
  • Rel attribute

8.3 Technology Stack Reference

Component Technology Version/Package
Language Go 1.25.0
CLI Cobra + simplecobra spf13/cobra, bep/simplecobra
Markdown Goldmark yuin/goldmark
Syntax Highlighting Chroma v2 alecthomas/chroma/v2
Image Processing Gift gohugoio/gift, golang.org/x/image
JavaScript Bundling esbuild evanw/esbuild
Sass/SCSS Dart Sass bep/godartsass/v2, bep/golibsass
Template Engine Go templates html/template, text/template (forked)
File Watching fsnotify fsnotify/fsnotify
Live Reload WebSocket gorilla/websocket
Cloud Deploy gocloud.dev S3, GCS, Azure
CDN AWS SDK v2 CloudFront invalidation
Module System Go Modules golang.org/x/mod
Minification tdewolff/minify v2 tdewolff/minify/v2
WASM Runtime wazero tetratelabs/wazero
TOML go-toml v2 pelletier/go-toml/v2
YAML go-yaml goccy/go-yaml
OpenAPI kin-openapi getkin/kin-openapi
Logging logg bep/logg
TLS mclib bep/mclib (mkcert)

8.4 Code Patterns and Conventions

Error Handling

Hugo uses structured errors with file position information (common/herrors/). Errors include:

  • Source file path and line/column numbers
  • Error context (surrounding lines)
  • Categorized error types (template, content, config, resource)
// Example: error with file context
return herrors.NewFileErrorFromPos(
    fmt.Errorf("failed to parse: %w", err),
    pos,
)

Logging

Hugo uses bep/logg for structured logging with suppressible IDs:

s.Log.Infof("building site: %s", s.Language().Lang)
s.Log.Warnf("deprecated: use %q instead of %q", newKey, oldKey)

Log IDs enable selective suppression via ignoreLogs config.

Configuration Pattern

Config structs use mapstructure tags for TOML/YAML/JSON mapping:

type RootConfig struct {
    BaseURL          string `mapstructure:"baseURL"`
    BuildDrafts      bool   `mapstructure:"buildDrafts"`
    // ...
}

Resource Immutability

Transformed resources are immutable. Each transformation produces a new resource instance. The original is never modified. This enables safe caching and concurrent processing.

8.5 Testing Strategy

Hugo employs multiple testing approaches:

# Run all tests
mage test
# or
go test ./...

# Run tests for a specific package
go test ./hugolib/...

# Run with race detector
go test -race ./...

# Run testscript tests
go test ./testscripts/...

# Run specific test
go test ./hugolib/ -run TestBuild

# With coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Testing layers:

  1. Unit tests — standard _test.go files alongside source
  2. Integration tests — _integration_test.go in hugolib/
  3. Test scripts — txtar-based tests in testscripts/ using rogpeppe/go-internal/testscript
  4. Helper packages — htesting/ provides test utilities

The txtar test format bundles multiple files and commands into a single test file:

# Test that basic Markdown renders correctly
exec hugo --logLevel debug
stdout 'Total in'
exists public/index.html

-- hugo.toml --
title = "Test"

-- content/_index.md --
---
title: Home
---
Hello **world**.

-- layouts/index.html --
{{ .Content }}

Key test packages by area:

  • hugolib/ — integration tests for the build pipeline
  • resources/ — resource transformation tests
  • tpl/ — template function tests
  • markup/goldmark/ — Markdown rendering tests
  • commands/ — CLI command tests
  • testscripts/ — end-to-end txtar tests

8.6 Contributing Guide

Development Workflow

  1. Fork and clone the repository
  2. Create a feature branch
  3. Make changes
  4. Run mage fmt to format code
  5. Run mage vet to check for issues
  6. Run mage test to verify all tests pass
  7. Submit a pull request

Code Style

  • Standard Go formatting (gofmt / goimports)
  • Package-level documentation in doc.go files
  • Exported types and functions must have doc comments
  • Error strings start lowercase, do not end with punctuation
  • Use fmt.Errorf("context: %w", err) for error wrapping

Build Tags

  • withdeploy — enables hugo deploy (cloud deployment)
  • Build without tags for a minimal binary

Commit Conventions

  • Clear, descriptive commit messages
  • Reference issue numbers when applicable
  • One logical change per commit

9. Integration Points

9.1 Hugo Modules Ecosystem

Hugo Modules enable composition of sites from multiple sources:

# Import a theme
[[module.imports]]
  path = "github.com/theNewDynamic/gohugo-theme-ananke"

# Import a component for specific directories
[[module.imports]]
  path = "github.com/user/hugo-seo"
  [[module.imports.mounts]]
    source = "layouts/partials"
    target = "layouts/partials/seo"

Module mounts allow remapping any source directory to any target:

Source Dir Target Dir Purpose
content/ content/ Content files
layouts/ layouts/ Templates
assets/ assets/ Pipeline-processed resources
static/ static/ Passthrough static files
data/ data/ Data files
i18n/ i18n/ Translation files
archetypes/ archetypes/ Content templates

9.2 JavaScript/npm Integration

Hugo integrates with the npm ecosystem:

# Generate package.json from module config
hugo mod npm pack

# Install npm dependencies
npm install

# Hugo discovers node_modules automatically for:
# - PostCSS
# - Tailwind CSS
# - esbuild imports

js.Build wraps esbuild with Hugo-specific features:

{{ $opts := dict
    "targetPath" "js/bundle.js"
    "minify" hugo.IsProduction
    "target" "es2020"
    "externals" (slice "jquery")
    "defines" (dict
        "process.env.NODE_ENV" (printf "%q" hugo.Environment)
    )
    "params" (dict "api" "https://api.example.com")
    "inject" (slice "js/shims/process.js")
    "sourceMap" (cond hugo.IsProduction "" "inline")
}}
{{ $js := resources.Get "js/main.js" | js.Build $opts }}

9.3 CSS Pipeline Integration

Sass/SCSS (Dart Sass)

{{ $opts := dict
    "targetPath" "css/style.css"
    "outputStyle" "compressed"
    "enableSourceMap" (not hugo.IsProduction)
    "includePaths" (slice "node_modules" "assets/scss")
}}
{{ $css := resources.Get "scss/main.scss" | toCSS $opts }}

PostCSS

{{ $css := resources.Get "css/main.css" | postCSS }}

Requires postcss.config.js in project root and postcss-cli installed.

Tailwind CSS

{{ $css := resources.Get "css/main.css" | css.TailwindCSS }}

Enable buildStats = true under [build] to generate hugo_stats.json for Tailwind tree-shaking.

9.4 Image Processing Pipeline

Hugo provides comprehensive image processing via the gohugoio/gift library:

{{ $image := resources.Get "images/photo.jpg" }}

{{ $resized := $image.Resize "800x webp q85" }}
{{ $cropped := $image.Fill "300x300 smart" }}
{{ $fitted := $image.Fit "600x400" }}
{{ $filtered := $image | images.Filter
    (images.Brightness 10)
    (images.Contrast 15)
    (images.GaussianBlur 2)
}}

Processing options:

  • Resize: {width}x{height} (preserves aspect ratio if one dimension omitted)
  • Fill: {width}x{height} {anchor} (crops to exact dimensions)
  • Fit: {width}x{height} (scales to fit within bounds)
  • Crop: {width}x{height} {anchor} (crops without scaling)
  • Filter: chain image filter operations

Output formats: jpg, png, gif, tif, bmp, webp

Anchor positions: smart, center, topleft, top, topright, left, right, bottomleft, bottom, bottomright

9.5 External Content Sources

Remote Resources

{{ $data := resources.GetRemote "https://api.example.com/data.json" }}
{{ if $data.Err }}
  {{ errorf "Failed to fetch: %s" $data.Err }}
{{ else }}
  {{ $json := $data.Content | transform.Unmarshal }}
{{ end }}

Subject to security.http.urls whitelist.

Data Files

Hugo loads data from the data/ directory (TOML, YAML, JSON, CSV, XML):

{{ range .Site.Data.authors }}
  {{ .name }}
{{ end }}

9.6 Git Integration

enableGitInfo = true

Exposes .GitInfo on pages:

  • .GitInfo.Hash — full commit hash
  • .GitInfo.AbbreviatedHash — short hash
  • .GitInfo.Subject — commit message
  • .GitInfo.AuthorName / .AuthorEmail / .AuthorDate

Requires fetch-depth: 0 in CI checkouts.

9.7 OpenAPI Integration

Hugo can render OpenAPI specifications:

{{ $spec := resources.Get "api/openapi.yaml" }}
{{ $api := openapi.Unmarshal $spec }}

Uses getkin/kin-openapi for parsing and validation.

9.8 Diagram Integration

ASCII art diagrams via GoAT (Go AT&T):

```goat
      .---.
     /-o-/--
  .-/ / /->
 ( *  \/
  '-.  \
     \ /
      '
```

Rendered to inline SVG at build time; no external dependencies.

9.9 Automation and CI/CD Triggers

For CI/CD automation, common triggers:

Trigger Method
Git push GitHub Actions, GitLab CI, etc.
Content CMS publish Webhook to CI rebuild
Scheduled rebuild Cron job / scheduled pipeline
Manual deploy hugo deploy CLI

9.10 Output Formats

Hugo supports multiple output formats per page:

Format Media Type Built-in
HTML text/html Yes
RSS application/rss+xml Yes
JSON application/json Yes
AMP text/html Yes
Calendar text/calendar Yes
CSV text/csv Yes
Markdown text/markdown Yes
Robots text/plain Yes
Sitemap application/xml Yes
WebAppManifest application/manifest+json Yes
HTTPStatus (404/server) text/html Yes

Custom output formats are defined in [outputFormats] and assigned to page kinds via [outputs].

9.11 Content Versioning and Roles

Hugo supports multi-version, multi-role content organization:

defaultContentVersion = "v2"
defaultContentVersionInSubdir = true
defaultContentRole = "user"
defaultContentRoleInSubdir = true

[versions]
  [versions.v1]
    weight = 1
  [versions.v2]
    weight = 2

[roles]
  [roles.user]
    weight = 1
  [roles.admin]
    weight = 2

This enables content structures like content/v2/admin/docs/ where content is segmented by version and audience role.

The related content engine uses configurable indices to find semantically similar pages:

{{ $related := .Site.RegularPages.Related . | first 5 }}

Configure indices in [related] to control matching by keywords, date, tags, or custom parameters.

9.13 Menu System

Hugo supports multiple menus with hierarchical nesting:

[menus]
  [[menus.main]]
    name = "Home"
    pageRef = "/"
    weight = 1
  [[menus.main]]
    name = "About"
    pageRef = "/about"
    weight = 2
    [[menus.main]]
      name = "Team"
      parent = "About"
      pageRef = "/about/team"
      weight = 1

Or auto-populate from sections:

sectionPagesMenu = "main"

Appendix A: Troubleshooting

A.1 Configuration Errors

# Symptom Cause Fix
1 "Unable to locate config file or config directory" No hugo.toml/hugo.yaml/hugo.json in project root or config/ directory Create config file or specify path with --config
2 "failed to parse timeout: %s" Invalid duration format in timeout Use Go duration format: "30s", "5m", "1h"
3 "invalid language configuration for %q" Malformed [languages] section Check language weight, title, and nested params structure
4 "failed to load config: %v" General config parse error Validate TOML/YAML/JSON syntax; check for tabs in YAML
5 Config values not taking effect Wrong environment or precedence Check --environment, verify config dir structure
6 Issue #14763: config from all environments applied Commands may apply config from unintended environments Isolate environment-specific config to config/{env}/ directories
7 Issue #13722: hugo new ignores environment hugo new does not respect --environment flag Set values in default config instead of environment-specific

A.2 Build Errors

# Symptom Cause Fix
8 "maximum template call stack size exceeded" Infinite template recursion Check partials for circular partial calls
9 "no template found for shortcode %q" Missing shortcode template Create layouts/shortcodes/{name}.html
10 "unknown output format %q for kind %q" Referencing undefined output format Define format in [outputFormats] before using in [outputs]
11 Build hangs or exceeds timeout Long-running template logic or external command Increase timeout; check external commands
12 "no modules loaded" Missing main module definition Run hugo mod init github.com/user/site
13 Missing pages in output buildDrafts/buildFuture/buildExpired not set Set draft: false in front matter or enable build flags
14 Wrong page order Default date sort vs. weight sort Set weight in front matter for manual ordering
15 Issue #13811: stacktrace lost on panic Panic handler swallows useful trace Run with --logLevel debug and panicOnWarning = true

A.3 Template Errors

# Symptom Cause Fix
16 .Params.X returns nil Case mismatch (params are lowercased) Access as .Params.x (lowercase)
17 Pages returns no results Wrong page context or collection method Use .RegularPages, .Pages, or where site.RegularPages
18 Partial not found Wrong path or missing file Partials are relative to layouts/partials/
19 resources.Get returns nil Asset not in assets/ directory Move file to assets/ or use page resources
20 .Content is empty Template called before rendering Use .Content only in template execution context

A.4 Resource Pipeline Errors

# Symptom Cause Fix
21 "not found" for Sass/SCSS Dart Sass not installed Install dart-sass or dart-sass-embedded
22 PostCSS fails silently postcss-cli not installed or no config Install postcss-cli and create postcss.config.js
23 js.Build error esbuild compilation failure Check JS syntax; review esbuild error output
24 Image processing fails Unsupported format or corrupt file Verify image format; try re-encoding
25 Issue #10345: EXIF data type issues with .Exif .Exif data may have unexpected types when jsonified Use specific EXIF field access rather than marshaling the whole object
26 Issue #14758: image metadata decode warnings Certain image metadata triggers warnings Suppress with ignoreLogs or re-encode images without problematic metadata

A.5 Security Errors

# Symptom Cause Fix
27 "binary with name X not allowed" Command not in security.exec.allow Add binary name to the exec whitelist regex
28 "env variable X not allowed" Env var not matching security.exec.osEnv Add var pattern to osEnv regex
29 "getenv not allowed for X" Template os.Getenv blocked Add key pattern to security.funcs.getenv
30 "URL not allowed: X" Remote resource URL blocked Add URL pattern to security.http.urls

A.6 Module Errors

# Symptom Cause Fix
31 "module not found" Module not in go.sum or network unavailable Run hugo mod get or hugo mod vendor for offline use
32 Module version mismatch go.sum checksum failure Run hugo mod verify then hugo mod tidy
33 Theme not applying Module mounts overriding defaults Check module.mounts configuration; defaults are replaced when any mount is defined
34 Mount target collision Two modules mounting to same target Use unique target paths per module

A.7 Server and LiveReload Errors

# Symptom Cause Fix
35 Port already in use Another process on port 1313 Use --port to specify different port
36 LiveReload not working WebSocket blocked by proxy/firewall Check browser console; ensure WS connection is allowed
37 Changes not detected Network filesystem or Docker volume Use --poll 1s flag for poll-based watching
38 "bind: permission denied" Binding to privileged port (< 1024) Use port > 1024 or run with elevated privileges

A.8 Deployment Errors

# Symptom Cause Fix
39 "deploy not supported in this version" Built without withdeploy tag Use release binary or build with -tags withdeploy
40 "empty deployment target" No [[deployment.targets]] configured Add target configuration
41 S3 permission denied IAM policy missing S3 permissions Grant s3:PutObject, s3:GetObject, s3:ListBucket, s3:DeleteObject
42 CloudFront invalidation fails Missing CloudFront permissions Grant cloudfront:CreateInvalidation

A.9 Content and Rendering Issues

# Symptom Cause Fix
43 Raw HTML stripped from Markdown Goldmark unsafe mode disabled (default) Set markup.goldmark.renderer.unsafe = true
44 Table of contents empty Content has no headings in configured range Adjust markup.tableOfContents.startLevel/endLevel
45 Emoji codes not rendering enableEmoji not set Set enableEmoji = true in config
46 CJK word count wrong hasCJKLanguage not enabled Set hasCJKLanguage = true
47 Broken cross-references Missing .Ref/.RelRef target Check target path; set refLinksErrorLevel to debug
48 Taxonomy pages missing Custom taxonomy not defined Add to [taxonomies] config section
49 Multilingual content not linked Missing translations Ensure matching filenames or explicit translationKey
50 Issue #14325: :contentbasename broken for taxonomies Regression since v0.153 Use :slug instead of :contentbasename for taxonomy permalinks

A.10 Minification Issues

# Symptom Cause Fix
51 Issue #14760: JS const initialization order broken Minifier reorders const declarations Set minify.tdewolff.js.keepVarNames = true or disableJS = true
52 Issue #14669: SVG Alpine.js bindings corrupted SVG minifier strips/corrupts Alpine directives Set minify.disableSVG = true

Appendix B: Quick Reference

B.1 Essential Commands

# Build
hugo                             # Production build
hugo --minify                    # Build with minification
hugo --environment staging       # Build for specific environment
hugo --gc                        # Run garbage collection after build
hugo --buildDrafts               # Include draft content

# Server
hugo server                      # Dev server on :1313
hugo server -D                   # Include drafts
hugo server --tlsAuto            # Dev server with TLS
hugo server --poll 1s            # Poll-based file watching

# Modules
hugo mod init <path>             # Initialize module
hugo mod get -u                  # Update all modules
hugo mod tidy                    # Clean unused modules
hugo mod vendor                  # Vendor dependencies
hugo mod graph                   # Show dependency graph

# Content
hugo new content posts/foo.md    # Create content
hugo list all                    # List all content
hugo list drafts                 # List drafts

# Deploy
hugo deploy                      # Deploy to default target
hugo deploy --target staging     # Deploy to named target
hugo deploy --dryRun             # Preview changes

# Debug
hugo config                      # Print resolved config
hugo config mounts               # Print resolved mounts
hugo env                         # Print Hugo environment info

B.2 Key File Locations

File / Directory Purpose
hugo.toml / hugo.yaml / hugo.json Main config
config/ Config directory (environment-based)
content/ Content files
layouts/ Templates
assets/ Pipeline-processed resources
static/ Passthrough static files
data/ Data files (TOML/YAML/JSON/XML/CSV)
i18n/ Translation files
archetypes/ Content templates
public/ Build output (default)
resources/_gen/ Processed resource cache
.hugo_build.lock Build lock file
go.mod / go.sum Module dependencies
_vendor/ Vendored modules
hugo_stats.json Build statistics (when buildStats = true)

B.3 Configuration Quick Reference

# Minimal production config
baseURL = "https://example.com/"
title = "My Site"
defaultContentLanguage = "en"
enableGitInfo = true
enableRobotsTXT = true

[build]
  buildStats = true              # For Tailwind CSS tree-shaking

[markup.goldmark.renderer]
  unsafe = false                 # Keep false for security

[minify]
  minifyOutput = true

[pagination]
  pagerSize = 20

[security.exec]
  allow = '^(dart-sass-embedded|go|git|npx?|postcss|tailwindcss)$'

[security.http]
  urls = '^https://.*$'         # Restrict to HTTPS only

[[module.imports]]
  path = "github.com/user/theme"

B.4 Common Environment Variables

export HUGO_ENVIRONMENT=production
export HUGO_NUMWORKERMULTIPLIER=4      # 4x CPU workers
export HUGO_MEMORYLIMIT=8192           # 8 GB memory limit
export HUGO_BASEURL=https://staging.example.com/  # Override baseURL
export DART_SASS_BINARY=/usr/local/bin/sass
export NO_COLOR=1                      # Disable colored output