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
- Single binary, zero runtime dependencies. Hugo ships as one executable. External tools (Dart Sass, PostCSS, Asciidoctor) are optional and whitelisted via the security policy.
- 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. - Parallel processing. Hugo uses Go's goroutine model extensively.
Content rendering, image processing, and resource transformations run
concurrently, controlled by
HUGO_NUMWORKERMULTIPLIER. - Incremental rebuilds. The identity-based dependency tracker
(
identity/) detects which pages depend on changed resources and rebuilds only those duringhugo serverwatch cycles. - 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. - 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
main.gocallscommands.Execute(os.Args[1:])commands.govianewExec()wires all CLI subcommands through simplecobracommandeer.goviarootCommandloads flags and resolves the config pathconfig/allconfig/merges config files, environment variables, and CLI flags intoRootConfigthenConfigsmodules/resolves theme and module dependencies (Go module graph)hugofs/constructs the virtual filesystem overlayhugolib/builds the site:doctree/constructs the document treepagesfromdata/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/
publisher/writes output files to the destination directorytransform/applies post-processing (URL replacement, meta injection)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
withdeploybuild tag is required forhugo deployto function. Without it, runninghugo deployproduces 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):
- CLI flags (
--baseURL,--buildDrafts, etc.) - Environment variables (
HUGO_prefix, e.g.,HUGO_BASEURL) - Environment-specific config (
config/{environment}/) - Main config file (
hugo.toml/hugo.yaml/hugo.json) - 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
ignoreLogsto 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
constinitialization order in certain edge cases. If you experience runtime JS errors after enablingminifyOutput, test withdisableJS = trueto 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]
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 customstaticdirectory, you must also explicitly mount the defaultstatic/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:
- Computes local file checksums
- Lists remote objects
- Diffs local vs. remote
- Uploads new/changed files with configured headers
- Optionally deletes remote files not in local (up to
maxDeletes) - 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:
- Parallel builds. Set
HUGO_NUMWORKERMULTIPLIERto tune goroutine count. The default (number of CPUs) is usually optimal. - Segmented builds. For very large sites, use
segmentsconfig to build subsections independently, then merge output. - Cached resources. The
resources/_gen/directory holds processed images and assets. Persist this across CI runs for dramatic speed-ups. - Content-addressable caching. Hugo caches transformed resources by content hash. Identical inputs never reprocess.
- Memory management. Set
HUGO_MEMORYLIMITfor 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:
- Monitors
content/,data/,layouts/,assets/,static/,i18n/, and config files - Debounces rapid successive changes
- Identifies the changed component type (content, template, asset, config)
- Triggers targeted rebuilds based on dependency tracking
- 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
:resourceDirtoken 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
-
Use
partialCachedfor expensive partials. The first argument is the template name, subsequent arguments form the cache key:{{ partialCached "nav.html" . .Section }} -
Avoid unnecessary
.Render. Each.Rendercall invokes the full template pipeline. Use direct field access when possible. -
Minimize
resources.Getin loops. Fetch resources once and pass them to partials. -
Profile templates.
hugo --templateMetrics --templateMetricsHintsThis prints execution time, call count, and cumulative cache stats per template.
Image Processing
- Process images in the page bundle. Avoid global resource lookups.
- Use appropriate quality settings. Default 75 is good for JPEG; lower for thumbnails.
- Prefer WebP output for modern browsers (smaller files, faster builds after initial processing).
- Cache
resources/_gen/across CI builds. Image processing is the single largest time cost in most Hugo sites.
Content Organization
- Page bundles (leaf/branch) reduce filesystem lookups.
- Headless bundles for data-only content avoid rendering overhead.
mainSectionsexplicitly 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:
- The watcher identifies the file type and path
hugobuilder.gomaps the change to affected identities- Only pages depending on changed identities are re-rendered
- For template changes, all pages using that template are rebuilt
- 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 compilationgo— Module operationsgit— GitInfo and module operationsnpm/npx— Node.js package toolspostcss— CSS post-processingtailwindcss— Tailwind CSS
Any command not matching this regex will be blocked with a security error.
Caution
Never use a permissive pattern like
.*forsecurity.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
enableInlineShortcodeswhen 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
localhostby default (change with--bind) - LiveReload WebSocket is unauthenticated
- The
/__stopendpoint 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
- 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. - Pin module versions. Use
go.sumfor integrity verification. - Review
go.sumchanges in PRs — supply chain attack vector. - Restrict HTTP URLs in production config.
- Audit
getenvaccess — theme code should not read host secrets. - Use
hugo mod vendorto snapshot dependencies locally. - Set
module.hugoVersionto 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:
commands.govianewExec()creates the root command and wires subcommandscommandeer.godefinesrootCommandwith all global flags- Each subcommand file (
server.go,deploy.go, etc.) implements thesimplecobra.Commanderinterface - 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 fieldsConfig— complete config for one languageConfigs— all language configs plus the base configConfigCompiled— 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:
:contentbasenamein permalink patterns is broken for taxonomy pages since v0.153. Use:slugas 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:
- Accepts a
Resourceinput - Produces a new
Resourceoutput (immutable) - Caches by content hash in
resources/_gen/ - 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.Builddoes not natively support different options per output format. Workaround: use conditional logic in templates to apply differentjs.Buildconfigurations 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:
- Reads
go.modandgo.sumfor dependency management - Resolves module imports recursively (supports module graph)
- Applies mount configuration to map module directories
- Supports vendoring (
_vendor/) for offline builds - Integrates with npm via
hugo mod npm pack(generatespackage.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:
- Computes local file checksums
- Lists remote objects
- Diffs local vs. remote
- Uploads new/changed files with configured headers
- Optionally deletes remote files not in local (up to
maxDeletes) - 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:
- File cache (
cache/filecache/) — persistent on-disk cache for remote resources, CSV/JSON fetches, and images. Configurable TTL viamaxAge. - Dynamic cache (
cache/dynacache/) — in-memory cache for runtime data. Uses eviction under memory pressure (controlled byHUGO_MEMORYLIMIT). - 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:
- Unit tests — standard
_test.gofiles alongside source - Integration tests —
_integration_test.goinhugolib/ - Test scripts — txtar-based tests in
testscripts/usingrogpeppe/go-internal/testscript - 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 pipelineresources/— resource transformation teststpl/— template function testsmarkup/goldmark/— Markdown rendering testscommands/— CLI command teststestscripts/— end-to-end txtar tests
8.6 Contributing Guide
Development Workflow
- Fork and clone the repository
- Create a feature branch
- Make changes
- Run
mage fmtto format code - Run
mage vetto check for issues - Run
mage testto verify all tests pass - Submit a pull request
Code Style
- Standard Go formatting (
gofmt/goimports) - Package-level documentation in
doc.gofiles - 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— enableshugo 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.
9.12 Related Content
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