Hugo is the world's fastest static site generator. Written in Go, it builds thousands of pages in seconds, supports content in Markdown, AsciiDoc, Org Mode, and reStructuredText, and ships as a single binary with zero dependencies. Hugo powers blogs, documentation sites, portfolios, landing pages, and complex multi-language publishing platforms.
This guide covers everything you need to install Hugo, create your first site, manage content, customize themes, and deploy to production. For architecture deep-dives, security hardening, and advanced configuration internals, see the Admin Guide.
1. Quick Start
Build a working Hugo site in under five minutes.
1.1 Prerequisites
- Git (any recent version)
- Hugo v0.147.0+ (extended edition recommended for Sass/SCSS support)
- A terminal (macOS Terminal, Windows PowerShell/WSL, Linux shell)
1.2 Create a New Site
hugo new project my-site
cd my-site
git init
This scaffolds the standard Hugo directory structure:
my-site/
archetypes/ # Content templates
assets/ # Files processed by Hugo Pipes
content/ # Your site content (Markdown, etc.)
data/ # Data files (JSON, TOML, YAML, XML, CSV)
i18n/ # Translation tables
layouts/ # HTML templates
static/ # Static files copied as-is
themes/ # Installed themes
hugo.toml # Site configuration
1.3 Add a Theme
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo 'theme = "ananke"' >> hugo.toml
1.4 Create Your First Post
hugo new content posts/my-first-post.md
This creates content/posts/my-first-post.md with front matter from your archetype:
---
title: "My First Post"
date: 2026-05-07T10:00:00-07:00
draft: true
---
Write your content here.
1.5 Start the Dev Server
hugo server -D
Expected output:
Watching for changes in /home/user/my-site/{archetypes,assets,content,data,i18n,layouts,static,themes}
Watching for config changes in /home/user/my-site/hugo.toml
Started building sites ...
| EN
-------------------+-----
Pages | 7
Paginator pages | 0
Non-page files | 0
Static files | 1
Processed images | 0
Aliases | 1
Cleaned | 0
Built in 23 ms
Environment: "development"
Serving pages from disk
Running in Fast Render Mode.
Web Server is available at http://localhost:1313/
Press Ctrl+C to stop
Open http://localhost:1313/ in your browser. Changes auto-reload instantly.
1.6 Build for Production
Remove draft: true from your post's front matter, then:
hugo
Output lands in public/ by default. Upload that directory to any static host.
Tip
The
-Dflag includes draft content. Always remove it (or setdraft: false) before building for production, or your drafts will be published.
2. Installation
2.1 Package Managers
macOS
# Homebrew (extended edition, includes Sass/SCSS)
brew install hugo
# Verify
hugo version
Windows
# Winget
winget install Hugo.Hugo.Extended
# Chocolatey
choco install hugo-extended
# Scoop
scoop install hugo-extended
Linux
# Snap
snap install hugo
# Debian/Ubuntu (check version — distro repos may lag)
sudo apt install hugo
# Arch
sudo pacman -S hugo
# Fedora
sudo dnf install hugo
FreeBSD
sudo pkg install hugo
Note
The extended edition is recommended for most users. It includes support for Sass/SCSS processing, WebP image encoding, and the embedded LibSass transpiler. The standard edition omits these features.
2.2 Pre-built Binaries
Download from the Hugo releases page.
Choose the archive matching your OS and architecture, extract it, and place the
hugo binary in your system PATH.
2.3 Docker
docker run --rm -it \
-v $(pwd):/src \
-p 1313:1313 \
hugomods/hugo:latest \
hugo server --bind 0.0.0.0
2.4 Build from Source
Requires Go 1.25.0 or later:
git clone https://github.com/gohugoio/hugo.git
cd hugo
go install
To include the deploy command (requires additional build tags):
go install -tags withdeploy
Important
Building from source without the
withdeploytag excludes thehugo deploycommand entirely. If you need cloud deployment support, always include this tag.
2.5 Verifying Your Installation
hugo version
Expected output (version/date will vary):
hugo v0.147.0-ab710a2+extended linux/amd64 BuildDate=2026-05-01T12:00:00Z VendorInfo=gohugoio
hugo env
Shows version, Go version, OS/architecture, and detected features:
hugo v0.147.0-ab710a2+extended linux/amd64 BuildDate=...
GOOS="linux"
GOARCH="amd64"
GOVERSION="go1.25.0"
...
3. Configuration
Hugo supports three configuration file formats: TOML (default), YAML, and JSON.
The default config filename is hugo.toml, hugo.yaml, or hugo.json in the
project root.
3.1 Configuration File
A minimal hugo.toml:
baseURL = "https://example.com/"
languageCode = "en-us"
title = "My Hugo Site"
theme = "ananke"
The same in YAML (hugo.yaml):
baseURL: https://example.com/
languageCode: en-us
title: My Hugo Site
theme: ananke
And JSON (hugo.json):
{
"baseURL": "https://example.com/",
"languageCode": "en-us",
"title": "My Hugo Site",
"theme": "ananke"
}
3.2 Configuration Directory
For complex sites, split configuration across a config/ directory:
config/
_default/
hugo.toml # Base config
menus.toml # Menu definitions
params.toml # Site parameters
production/
hugo.toml # Production overrides
staging/
hugo.toml # Staging overrides
Hugo merges these by environment. The _default/ directory is always loaded;
environment-specific directories overlay it.
3.3 Environments
Hugo uses two default environments:
| Context | Default Environment |
|---|---|
hugo (build) |
production |
hugo server |
development |
Override with the -e flag or the HUGO_ENVIRONMENT / HUGO_ENV variable:
hugo -e staging
hugo server -e production
HUGO_ENVIRONMENT=staging hugo
3.4 Essential Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
baseURL |
string | "" |
Root URL of the site (include trailing slash) |
title |
string | "" |
Site title |
theme |
string/list | "" |
Theme name(s) to use |
languageCode |
string | "" |
RFC 5646 language tag |
defaultContentLanguage |
string | "en" |
Default content language |
paginate |
int | 10 |
Number of items per paginated page |
summaryLength |
int | 70 |
Number of words in auto-summaries |
buildDrafts |
bool | false |
Include draft content |
buildFuture |
bool | false |
Include content with future dates |
buildExpired |
bool | false |
Include expired content |
enableEmoji |
bool | false |
Enable emoji shortcodes |
enableGitInfo |
bool | false |
Attach Git commit info to pages |
enableRobotsTXT |
bool | false |
Generate robots.txt |
canonifyURLs |
bool | false |
Make all relative URLs absolute |
relativeURLs |
bool | false |
Make all URLs relative to content root |
uglyURLs |
bool | false |
Use page.html instead of page/index.html |
disableKinds |
list | [] |
Page kinds to skip (e.g., ["taxonomy", "term"]) |
disableHugoGeneratorInject |
bool | false |
Remove Hugo meta tag from HTML head |
timeout |
string | "30s" |
Timeout for page generation |
timeZone |
string | "" |
Default timezone (e.g., America/New_York) |
hasCJKLanguage |
bool | false |
Enable CJK word counting |
titleCaseStyle |
string | "AP" |
Title case style: AP, Chicago, Go, none |
removePathAccents |
bool | false |
Remove accents from auto-generated paths |
copyright |
string | "" |
Site copyright notice |
newContentEditor |
string | "" |
Editor to open for hugo new |
3.5 Configuring the Build Pipeline
[build]
noJSConfigInAssets = false
useResourceCacheWhen = "fallback" # never | fallback | always
buildStats = false
cacheBusters = []
[build.cachebusters]
# ...
3.6 Permalink Configuration
[permalinks]
[permalinks.page]
posts = "/blog/:year/:month/:slug/"
[permalinks.section]
posts = "/blog/"
[permalinks.term]
tags = "/tags/:slug/"
Available tokens: :year, :month, :monthname, :day, :weekday,
:weekdayname, :yearday, :section, :sections, :title, :slug,
:filename, :slugorfilename.
3.7 Menu Configuration
[[menus.main]]
name = "Home"
pageRef = "/"
weight = 10
[[menus.main]]
name = "Posts"
pageRef = "/posts"
weight = 20
[[menus.main]]
name = "About"
pageRef = "/about"
weight = 30
3.8 Taxonomy Configuration
[taxonomies]
tag = "tags"
category = "categories"
series = "series"
Disable default taxonomies:
[taxonomies]
# Empty — no taxonomies at all
3.9 Output Formats
[outputs]
home = ["HTML", "RSS", "JSON"]
page = ["HTML"]
section = ["HTML", "RSS"]
taxonomy = ["HTML", "RSS"]
term = ["HTML", "RSS"]
Built-in output formats: HTML, RSS, JSON, AMP, CSS, Calendar, Markdown, Robots.txt, Sitemap, WebAppManifest.
3.10 Markup Configuration
[markup]
defaultMarkdownHandler = "goldmark"
[markup.goldmark]
[markup.goldmark.extensions]
footnote = true
strikethrough = true
table = true
taskList = true
typographer = true
[markup.goldmark.renderer]
unsafe = false # Set true to allow raw HTML in Markdown
[markup.highlight]
style = "monokai"
lineNos = true
lineNumbersInTable = true
noClasses = true
guessSyntax = false
3.11 Imaging Configuration
[imaging]
quality = 75
hint = "photo" # photo | picture | drawing | icon | text
resampleFilter = "box" # box | lanczos | cosine | etc.
anchor = "smart" # smart | center | topleft | top | topright | ...
[imaging.exif]
includeFields = ""
excludeFields = ""
disableDate = false
disableLatLong = true
3.12 Minification Configuration
[minify]
disableCSS = false
disableHTML = false
disableJS = false
disableJSON = false
disableSVG = false
disableXML = false
minifyOutput = false
[minify.tdewolff]
[minify.tdewolff.html]
keepDocumentTags = true
keepEndTags = true
keepQuotes = false
3.13 Cache Configuration
[caches]
[caches.getjson]
dir = ":cacheDir/:project"
maxAge = "10m"
[caches.getcsv]
dir = ":cacheDir/:project"
maxAge = "10m"
[caches.images]
dir = ":cacheDir/images"
maxAge = -1 # Never expires
[caches.assets]
dir = ":resourceDir/_gen"
maxAge = -1
[caches.modules]
dir = ":cacheDir/modules"
maxAge = -1
3.14 Security Configuration
[security]
enableInlineShortcodes = false
[security.exec]
allow = ["^(dart-)?sass(-embedded)?$", "^go$", "^git$", "^npx$", "^postcss$", "^tailwindcss$"]
osEnv = ["(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM|HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SystemRoot|SYSTEMROOT)$"]
[security.funcs]
getenv = ["^HUGO_", "^CI$"]
[security.http]
methods = ["(?i)GET|POST"]
urls = [".*"]
3.15 Privacy Configuration
[privacy]
[privacy.disqus]
disable = false
[privacy.googleAnalytics]
disable = false
[privacy.instagram]
disable = false
simple = false
[privacy.twitter]
disable = false
enableDNT = false
simple = false
[privacy.vimeo]
disable = false
enableDNT = false
simple = false
[privacy.youtube]
disable = false
privacyEnhanced = false
3.16 Viewing Your Configuration
# Print merged configuration (default: TOML)
hugo config
# Output as YAML
hugo config --format yaml
# Output as JSON
hugo config --format json
# Include zero-value fields
hugo config --printZero
# Show config for a specific language
hugo config --lang fr
# Show configured module mounts
hugo config mounts
3.17 Environment Variables
Any configuration key can be overridden with environment variables using the
prefix HUGO_ and underscores for nesting:
HUGO_BASEURL="https://staging.example.com/" hugo
HUGO_PARAMS_AUTHOR="Jane Doe" hugo
HUGO_TITLE="Override Title" hugo server
Dedicated environment variables:
| Variable | Purpose |
|---|---|
HUGO_ENVIRONMENT / HUGO_ENV |
Set the build environment |
HUGO_NUMWORKERMULTIPLIER |
Multiplier for parallel workers (default: CPU count) |
HUGO_MEMORYLIMIT |
Memory limit for image processing |
HUGO_FILE_LOG_FORMAT |
Custom file change log format |
HUGO_BUILD_TAGS |
Build tags when compiling from source |
DART_SASS_BINARY |
Path to Dart Sass binary |
NODE_PATH |
Node.js module resolution path |
NO_COLOR |
Disable color output (any non-empty value) |
Note
For the full configuration reference including all nested sections (
build,caches,markup,imaging,module,deployment,server,security,privacy,services,frontmatter,sitemap,related,pagination,segments,httpCache,versions,roles,cascade,page), see the Admin Guide.
4. Core Usage
4.1 Building Your Site
Basic Build
hugo
Generates the site into public/ using the production environment.
Build with Options
# Specify destination directory
hugo -d dist/
# Build with drafts, future, and expired content
hugo -D -F -E
# Build with a specific base URL
hugo -b https://staging.example.com/
# Build with minification
hugo --minify
# Build with specific theme
hugo -t mytheme
# Build in quiet mode (suppress non-error output)
hugo --quiet
# Build with template metrics
hugo --templateMetrics --templateMetricsHints
Build Environment Control
# Force production environment
hugo -e production
# Use staging config overlay
hugo -e staging
# Set via environment variable
HUGO_ENVIRONMENT=production hugo
Render to Memory
hugo -M
Renders entirely in memory without writing files to disk. Useful for CI validation (ensures the build succeeds without disk I/O).
4.2 Development Server
Start the Server
hugo server
The server runs in development environment by default, with live reload enabled.
Server Options
# Include drafts
hugo server -D
# Custom port
hugo server -p 8080
# Bind to all interfaces (for LAN access)
hugo server --bind 0.0.0.0
# Disable live reload
hugo server --disableLiveReload
# Disable fast render (full rebuild on every change)
hugo server --disableFastRender
# Disable browser error overlay
hugo server --disableBrowserError
# Navigate to changed content file after edit
hugo server --navigateToChanged
# Serve static files from disk (not memory)
hugo server --renderStaticToDisk
# Disable HTTP caching headers
hugo server --noHTTPCache
# Watch with polling (useful for network drives)
hugo server --poll 700ms
HTTPS / TLS
# Auto-generate locally-trusted certificates (requires mkcert)
hugo server --tlsAuto
# Use your own certificates
hugo server --tlsCertFile cert.pem --tlsKeyFile key.pem
To install/uninstall the local CA for auto-generated certs:
hugo server trust
hugo server trust uninstall
Tip
Use
--disableFastRenderwhen debugging template changes. Fast render mode only re-renders changed pages, which can miss cascading template effects.
4.3 Content Management
Creating Content
# Create a new content file using archetypes
hugo new content posts/my-post.md
hugo new content about.md
hugo new content docs/getting-started.md
# Legacy syntax (auto-inserts "content" prefix)
hugo new posts/my-post.md
Hugo uses archetype templates from archetypes/ to populate the new file's
front matter. The default archetype:
---
title: "{{ replace .File.ContentBaseName "-" " " | title }}"
date: {{ .Date }}
draft: true
---
Front Matter Formats
YAML (delimited by ---):
---
title: "My Post"
date: 2026-05-07
draft: false
tags: ["go", "static-site"]
categories: ["tutorials"]
weight: 10
slug: "custom-url-slug"
aliases: ["/old-url/"]
description: "A brief description"
---
TOML (delimited by +++):
+++
title = "My Post"
date = 2026-05-07
draft = false
tags = ["go", "static-site"]
+++
JSON (wrapped in {}):
{
"title": "My Post",
"date": "2026-05-07",
"draft": false
}
Content Organization
Hugo derives URL structure from your content directory layout:
content/
_index.md # Home page content
about.md # /about/
posts/
_index.md # /posts/ (section list page)
first-post.md # /posts/first-post/
second-post.md # /posts/second-post/
docs/
_index.md # /docs/
getting-started.md # /docs/getting-started/
advanced/
_index.md # /docs/advanced/
tips.md # /docs/advanced/tips/
Page Bundles
Leaf bundle -- a directory with index.md (no underscore). Represents a
single page with its own resources:
content/posts/my-post/
index.md # The page
hero.jpg # Page resource
data.csv # Page resource
Branch bundle -- a directory with _index.md (with underscore). Represents
a section/list page:
content/posts/
_index.md # Section list page
first-post.md # Child page
Listing Content
# List all drafts
hugo list drafts
# List content with future publish dates
hugo list future
# List expired content
hugo list expired
# List all content
hugo list all
# List published (non-draft, non-future, non-expired) content
hugo list published
Output is CSV format with columns: path, slug, title, date, expiry date, publish date, draft status, permalink.
4.4 Hugo Modules
Hugo Modules use Go Modules under the hood to manage dependencies -- themes, content, data, assets, and more.
Initialize a Module
hugo mod init github.com/yourname/yoursite
This creates a go.mod file in your project root.
Add a Theme as a Module
In hugo.toml:
[module]
[[module.imports]]
path = "github.com/theNewDynamic/gohugo-theme-ananke"
Then fetch:
hugo mod get
Module Commands
# Resolve and install dependencies
hugo mod get
# Update all modules to latest
hugo mod get -u
# Update a specific module
hugo mod get -u github.com/theNewDynamic/gohugoio-theme-ananke
# Remove unused module entries
hugo mod tidy
# Vendor all dependencies into _vendor/
hugo mod vendor
# Verify module dependencies
hugo mod verify
# Print module dependency graph
hugo mod graph
# Delete module cache
hugo mod clean
hugo mod clean --all
hugo mod clean --pattern "github.com/foo/*"
# Merge Node.js dependencies from modules into workspace
hugo mod npm pack
4.5 Asset Processing (Hugo Pipes)
Hugo Pipes process assets (CSS, JS, images) at build time through a pipeline.
Assets must live in assets/ (or a mounted equivalent).
CSS Processing
In templates:
{{ $style := resources.Get "css/main.css" }}
{{ $style = $style | minify | fingerprint }}
<link rel="stylesheet" href="{{ $style.RelPermalink }}" integrity="{{ $style.Data.Integrity }}">
Sass/SCSS Compilation
{{ $opts := dict "transpiler" "dartsass" "targetPath" "css/style.css" }}
{{ $style := resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }}
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
JavaScript Bundling
{{ $js := resources.Get "js/main.js" | js.Build (dict "minify" true) }}
<script src="{{ $js.RelPermalink }}"></script>
PostCSS
{{ $css := resources.Get "css/main.css" | postCSS | minify }}
Requires a postcss.config.js in your project root.
Image Processing
{{ $image := resources.Get "images/hero.jpg" }}
{{ $thumbnail := $image.Resize "300x" }}
{{ $cropped := $image.Fill "400x300 smart" }}
{{ $fitted := $image.Fit "600x400" }}
{{ $webp := $image.Resize "800x webp" }}
<img src="{{ $thumbnail.RelPermalink }}" width="{{ $thumbnail.Width }}" height="{{ $thumbnail.Height }}">
4.6 Shortcodes
Shortcodes are reusable template snippets you embed in content files.
Built-in Shortcodes
<!-- YouTube embed -->
{{</* youtube dQw4w9WgXcQ */>}}
<!-- Vimeo embed -->
{{</* vimeo 146022717 */>}}
<!-- GitHub Gist -->
{{</* gist user 12345678 */>}}
<!-- Twitter/X embed -->
{{</* twitter user 1234567890 */>}}
<!-- Instagram -->
{{</* instagram BWNjjyYFxVx */>}}
<!-- Figure with caption -->
{{</* figure src="/images/photo.jpg" title="Caption" alt="Alt text" */>}}
<!-- Highlight code -->
{{</* highlight go "linenos=table,hl_lines=3 5" */>}}
package main
func main() {
fmt.Println("Hello")
}
{{</* /highlight */>}}
<!-- Reference another page -->
{{</* ref "posts/my-post.md" */>}}
{{</* relref "posts/my-post.md" */>}}
<!-- Param from front matter or site config -->
{{</* param "description" */>}}
Custom Shortcodes
Create layouts/shortcodes/myshortcode.html:
<div class="callout">
{{ .Inner }}
</div>
Use in content:
{{</* myshortcode */>}}
This is a callout box.
{{</* /myshortcode */>}}
4.7 Taxonomies
Taxonomies organize content by classification. Hugo provides tags and
categories by default.
Using Taxonomies in Content
---
title: "My Post"
tags: ["go", "web", "tutorial"]
categories: ["programming"]
series: ["learn-hugo"]
---
Custom Taxonomies
In hugo.toml:
[taxonomies]
tag = "tags"
category = "categories"
series = "series"
author = "authors"
4.8 Multilingual Sites
defaultContentLanguage = "en"
[languages]
[languages.en]
weight = 1
languageName = "English"
title = "My Site"
[languages.fr]
weight = 2
languageName = "Français"
title = "Mon Site"
[languages.de]
weight = 3
languageName = "Deutsch"
title = "Meine Seite"
Content is organized by language suffix or directory:
Filename approach:
content/posts/my-post.md # English (default)
content/posts/my-post.fr.md # French
content/posts/my-post.de.md # German
Directory approach:
content/en/posts/my-post.md
content/fr/posts/my-post.md
content/de/posts/my-post.md
Translation files go in i18n/:
i18n/en.toml
i18n/fr.toml
i18n/de.toml
4.9 Data Templates
Place data files in data/:
data/
members.json
config.yaml
products/
widgets.toml
Access in templates via .Site.Data:
{{ range .Site.Data.members }}
<p>{{ .name }} -- {{ .role }}</p>
{{ end }}
5. Common Tasks
5.1 Creating a Blog
hugo new project my-blog
cd my-blog
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
hugo.toml:
baseURL = "https://myblog.com/"
title = "My Blog"
theme = "ananke"
paginate = 5
[permalinks]
[permalinks.page]
posts = "/blog/:year/:month/:slug/"
[params]
author = "Your Name"
Create posts:
hugo new content posts/hello-world.md
hugo new content posts/second-post.md
5.2 Creating a Documentation Site
hugo new project my-docs
cd my-docs
Structure content as nested sections:
content/
_index.md
docs/
_index.md
getting-started/
_index.md
installation.md
configuration.md
guides/
_index.md
basics.md
advanced.md
reference/
_index.md
api.md
cli.md
Use weight in front matter to control page ordering within sections:
---
title: "Installation"
weight: 1
---
5.3 Adding Search (JSON Index)
Enable JSON output for the home page:
[outputs]
home = ["HTML", "RSS", "JSON"]
Create layouts/_default/index.json:
{{- $pages := where .Site.RegularPages "Type" "not in" (slice "page") -}}
[
{{- range $i, $p := $pages }}
{{- if $i }},{{ end }}
{
"title": {{ $p.Title | jsonify }},
"url": {{ $p.RelPermalink | jsonify }},
"content": {{ $p.Plain | jsonify }},
"tags": {{ $p.Params.tags | jsonify }},
"date": {{ $p.Date.Format "2006-01-02" | jsonify }}
}
{{- end }}
]
Then use a client-side search library (Fuse.js, Lunr.js, Pagefind) to query
index.json.
5.4 Adding an RSS Feed
RSS is enabled by default for the home page and sections. Customize in config:
[services]
[services.rss]
limit = 20
Custom RSS template: create layouts/_default/rss.xml.
5.5 Creating Custom Archetypes
Create archetypes/posts.md:
---
title: "{{ replace .File.ContentBaseName "-" " " | title }}"
date: {{ .Date }}
draft: true
tags: []
categories: []
description: ""
cover:
image: ""
alt: ""
---
## Introduction
## Body
## Conclusion
Now hugo new content posts/my-post.md uses this template.
Directory-based archetypes are also supported. Create archetypes/posts/ with
an index.md and any resource files -- hugo new content copies the entire
directory as a page bundle.
5.6 Syntax Highlighting
Hugo uses Chroma for server-side syntax highlighting.
Inline Highlighting
```python
def hello():
print("Hello, world!")
```
Highlight Shortcode with Options
{{</* highlight go "linenos=table,hl_lines=2-3,linenostart=10" */>}}
func main() {
fmt.Println("Hello")
fmt.Println("World")
}
{{</* /highlight */>}}
Generate a Custom Chroma Stylesheet
hugo gen chromastyles --style=dracula > static/css/syntax.css
hugo gen chromastyles --style=github --highlightStyle="bg:#f0f0f0"
Then in config:
[markup.highlight]
noClasses = false
5.7 Image Processing Recipes
Responsive Images
{{ $img := resources.Get "images/hero.jpg" }}
{{ $small := $img.Resize "480x" }}
{{ $medium := $img.Resize "960x" }}
{{ $large := $img.Resize "1440x" }}
<img
srcset="{{ $small.RelPermalink }} 480w,
{{ $medium.RelPermalink }} 960w,
{{ $large.RelPermalink }} 1440w"
sizes="(max-width: 600px) 480px, (max-width: 1200px) 960px, 1440px"
src="{{ $medium.RelPermalink }}"
alt="Hero image">
WebP Conversion
{{ $jpg := resources.Get "images/photo.jpg" }}
{{ $webp := $jpg.Resize "800x webp" }}
<picture>
<source srcset="{{ $webp.RelPermalink }}" type="image/webp">
<img src="{{ ($jpg.Resize "800x").RelPermalink }}" alt="Photo">
</picture>
Image Filters
{{ $img := resources.Get "images/photo.jpg" }}
{{ $gray := $img.Filter (images.Grayscale) }}
{{ $bright := $img.Filter (images.Brightness 20) }}
{{ $blurred := $img.Filter (images.GaussianBlur 6) }}
{{ $overlay := $img.Filter (images.Overlay $watermark 50 50) }}
5.8 Deploying to Popular Hosts
Netlify
Create netlify.toml:
[build]
command = "hugo --minify"
publish = "public"
[build.environment]
HUGO_VERSION = "0.147.0"
[context.deploy-preview]
command = "hugo --minify -b $DEPLOY_PRIME_URL"
GitHub Pages
Create .github/workflows/hugo.yml:
name: Deploy Hugo
on:
push:
branches: [main]
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: 'latest'
extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
Cloudflare Pages
Set build command to hugo --minify and output directory to public. Set
environment variable HUGO_VERSION to your desired version.
Vercel
Create vercel.json:
{
"build": {
"env": {
"HUGO_VERSION": "0.147.0"
}
}
}
Firebase Hosting
firebase init hosting
# Set public directory to "public"
hugo --minify
firebase deploy
Amazon S3
hugo --minify
aws s3 sync public/ s3://my-bucket/ --delete
Hugo Deploy (Built-in)
Hugo includes a built-in deploy command for cloud storage providers. Requires
building Hugo with the withdeploy tag.
[deployment]
[[deployment.targets]]
name = "production"
URL = "s3://my-bucket?region=us-east-1"
[[deployment.matchers]]
pattern = "^.+\\.(js|css|svg|ttf)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = true
[[deployment.matchers]]
pattern = "^.+\\.(png|jpg|gif|webp)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = false
[[deployment.matchers]]
pattern = "^.+\\.(html|xml|json)$"
gzip = true
# Dry run
hugo deploy --dryRun
# Deploy with confirmation
hugo deploy --confirm
# Deploy to a specific target
hugo deploy --target production
# Force re-upload all files
hugo deploy --force
# Control CDN invalidation
hugo deploy --invalidateCDN=false
# Limit file deletions
hugo deploy --maxDeletes 100
# Control parallelism
hugo deploy --workers 10
5.9 Custom Output Formats
Define a custom output format and assign it:
[mediaTypes]
[mediaTypes."text/netlify"]
suffixes = [""]
delimiter = ""
[outputFormats]
[outputFormats.Netlify]
mediaType = "text/netlify"
baseName = "_redirects"
isPlainText = true
notAlternative = true
[outputs]
home = ["HTML", "RSS", "Netlify"]
Create the template layouts/_default/home.netlify:
/old-page /new-page 301
/blog/* /posts/:splat 302
5.10 Related Content
[related]
includeNewer = false
threshold = 80
[[related.indices]]
name = "tags"
weight = 100
[[related.indices]]
name = "categories"
weight = 80
[[related.indices]]
name = "date"
weight = 10
type = "datetime"
In templates:
{{ $related := .Site.RegularPages.Related . | first 5 }}
{{ with $related }}
<h3>Related Posts</h3>
<ul>
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
</ul>
{{ end }}
5.11 Pagination
paginate = 10
In list templates:
{{ range .Paginator.Pages }}
<article>
<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
<p>{{ .Summary }}</p>
</article>
{{ end }}
{{ template "_internal/pagination.html" . }}
Custom paginator:
{{ $paginator := .Paginate (where .Pages "Type" "posts") 5 }}
{{ range $paginator.Pages }}
...
{{ end }}
5.12 Sitemap Customization
[sitemap]
changeFreq = "monthly"
filename = "sitemap.xml"
priority = 0.5
Per-page overrides in front matter:
---
sitemap:
changeFreq: daily
priority: 0.9
---
5.13 Robots.txt
Enable generation:
enableRobotsTXT = true
Custom template: create layouts/robots.txt:
User-agent: *
Disallow: /private/
Sitemap: {{ "sitemap.xml" | absURL }}
5.14 Content Summaries
Hugo auto-generates summaries (first 70 words by default). Control with:
summaryLength = 100
Or use a manual summary divider in content:
This is the summary text.
<!--more-->
This is the rest of the content.
5.15 Table of Contents
Access in templates:
{{ .TableOfContents }}
Configure depth:
[markup.tableOfContents]
startLevel = 2
endLevel = 4
ordered = false
5.16 Draft / Future / Expired Workflow
Use front matter date fields to control content visibility:
---
title: "Scheduled Post"
date: 2026-06-01 # Publish date
expiryDate: 2026-12-31 # Auto-expire date
publishDate: 2026-06-01 # Alternative to "date" for scheduling
draft: false
---
During development:
hugo server -D -F -E # Show drafts, future, and expired
For production, omit those flags -- only published, non-future, non-expired content renders.
5.17 Git Info on Pages
enableGitInfo = true
Access in templates:
<p>Last modified: {{ .GitInfo.AuthorDate.Format "January 2, 2006" }}</p>
<p>By: {{ .GitInfo.AuthorName }}</p>
<p>Hash: {{ .GitInfo.Hash }}</p>
Warning
enableGitInforequires the full Git history. If you're using shallow clones in CI (e.g.,actions/checkoutwith defaultdepth: 1), setfetch-depth: 0to get the complete history, or Git info will be missing/incorrect.
5.18 Front Matter Cascade
Apply front matter values to all descendant pages:
# content/docs/_index.md
---
title: "Documentation"
cascade:
type: docs
layout: single
sidebar: true
---
All pages under content/docs/ inherit these values unless they override them.
5.19 Page Resources
Access resources from page bundles:
{{ $img := .Resources.GetMatch "hero.*" }}
{{ with $img }}
<img src="{{ .RelPermalink }}" alt="Hero">
{{ end }}
{{ range .Resources.Match "gallery/*" }}
<img src="{{ .RelPermalink }}">
{{ end }}
5.20 Aliases and Redirects
---
title: "New URL"
aliases:
- /old-url/
- /another-old-url/
- /legacy/page.html
---
Hugo generates redirect HTML files at the old URLs pointing to the new one.
5.21 Custom 404 Page
Create layouts/404.html:
{{ define "main" }}
<h1>Page Not Found</h1>
<p>Sorry, the page you're looking for doesn't exist.</p>
<a href="{{ "/" | relURL }}">Go home</a>
{{ end }}
Most static hosts serve 404.html automatically for missing routes.
5.22 Converting Front Matter Formats
# Convert all front matter to TOML
hugo convert toTOML
# Convert to YAML
hugo convert toYAML
# Convert to JSON
hugo convert toJSON
# Write to a different directory (preserve originals)
hugo convert toYAML --output converted/
# Convert even unsafe content
hugo convert toTOML --unsafe
5.23 Importing from Jekyll
hugo import jekyll /path/to/jekyll-site /path/to/hugo-site
# Force overwrite existing destination
hugo import jekyll /path/to/jekyll-site /path/to/hugo-site --force
This converts Jekyll content and front matter to Hugo format. Manual cleanup is usually needed for Liquid templates.
5.24 Generating CLI Documentation
# Generate Markdown documentation for all Hugo commands
hugo gen doc --dir docs/cli/
# Generate man pages
hugo gen man --dir man/
5.25 Sections and Content Types
Hugo's content type system maps sections to layouts:
content/
posts/ # Type: "posts" -> layouts/posts/
docs/ # Type: "docs" -> layouts/docs/
events/ # Type: "events" -> layouts/events/
Override in front matter:
---
type: "docs"
layout: "tutorial"
---
5.26 Menu Management
In Config
[[menus.main]]
name = "Blog"
pageRef = "/posts"
weight = 10
[menus.main.params]
icon = "blog"
[[menus.main]]
name = "GitHub"
url = "https://github.com/yourname"
weight = 100
[menus.main.params]
external = true
In Front Matter
---
title: "About"
menus:
main:
weight: 30
name: "About Us"
---
Nested Menus
[[menus.main]]
identifier = "products"
name = "Products"
weight = 20
[[menus.main]]
parent = "products"
name = "Widget A"
pageRef = "/products/widget-a"
weight = 1
5.27 Render Hooks
Customize how Markdown elements render by creating templates in
layouts/_default/_markup/:
layouts/_default/_markup/
render-link.html # Custom link rendering
render-image.html # Custom image rendering
render-heading.html # Custom heading rendering
render-codeblock.html # Custom code block rendering
render-codeblock-mermaid.html # Mermaid diagram rendering
Example render-image.html:
{{ $img := .Page.Resources.GetMatch .Destination }}
{{ with $img }}
{{ $small := .Resize "600x" }}
<figure>
<img src="{{ $small.RelPermalink }}" alt="{{ $.Text }}" loading="lazy">
{{ with $.Title }}<figcaption>{{ . }}</figcaption>{{ end }}
</figure>
{{ else }}
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}">
{{ end }}
5.28 Content Adapters
Use content adapters to dynamically generate pages from external data sources
(APIs, databases, CSV files). Create _content.gotmpl in a content directory:
{{ $data := dict }}
{{ $url := "https://api.example.com/posts" }}
{{ with resources.GetRemote $url }}
{{ $data = .Content | transform.Unmarshal }}
{{ end }}
{{ range $data }}
{{ $content := dict
"mediaType" "text/markdown"
"value" .body
}}
{{ $params := dict
"title" .title
"date" .date
}}
{{ $page := dict
"content" $content
"kind" "page"
"params" $params
"path" (printf "%s" .slug)
}}
{{ $.AddPage $page }}
{{ end }}
5.29 Segments (Partial Builds)
Render only specific portions of your site:
[segments]
[segments.docs]
[[segments.docs.includes]]
kind = "{page,section}"
path = "{/docs,/docs/**}"
[segments.blog]
[[segments.blog.includes]]
kind = "{page,section}"
path = "{/posts,/posts/**}"
hugo --renderSegments docs
hugo server --renderSegments blog
5.30 Working with Data Files
Supported formats: JSON, YAML, TOML, XML, CSV.
data/
team.json
pricing.yaml
features.toml
Access in templates:
{{ range .Site.Data.team }}
<div class="member">
<h3>{{ .name }}</h3>
<p>{{ .title }}</p>
</div>
{{ end }}
5.31 Remote Data Fetching
{{ $url := "https://api.github.com/repos/gohugoio/hugo" }}
{{ with resources.GetRemote $url }}
{{ $data := .Content | transform.Unmarshal }}
<p>Stars: {{ $data.stargazers_count }}</p>
{{ end }}
Caution
Remote data fetching is subject to Hugo's security policy. By default, only GET and POST methods are allowed. The URL must match the configured
security.http.urlspatterns. If a fetch fails silently, check yoursecurityconfiguration.
5.32 PostCSS / Tailwind CSS Integration
Install dependencies:
npm init -y
npm install tailwindcss @tailwindcss/typography postcss autoprefixer
postcss.config.js:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}
In your template:
{{ $css := resources.Get "css/main.css" | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}">
Or use Tailwind CSS v4+ directly (Hugo has built-in tailwindcss binary
support via the css.TailwindCSS template function).
5.33 JavaScript Bundling with js.Build
{{ $opts := dict
"targetPath" "js/bundle.js"
"minify" true
"target" "es2020"
"externals" (slice "react" "react-dom")
"defines" (dict "process.env.NODE_ENV" "\"production\"")
"format" "esm"
"sourceMap" "inline"
}}
{{ $js := resources.Get "js/main.js" | js.Build $opts }}
<script type="module" src="{{ $js.RelPermalink }}"></script>
js.Build uses esbuild internally -- it handles ESM imports, TypeScript,
JSX/TSX, tree-shaking, and code splitting.
5.34 Mounting Directories
[module]
[[module.mounts]]
source = "content"
target = "content"
[[module.mounts]]
source = "static"
target = "static"
[[module.mounts]]
source = "layouts"
target = "layouts"
[[module.mounts]]
source = "data"
target = "data"
[[module.mounts]]
source = "assets"
target = "assets"
[[module.mounts]]
source = "i18n"
target = "i18n"
[[module.mounts]]
source = "archetypes"
target = "archetypes"
# Mount a directory from a module
[[module.mounts]]
source = "node_modules/@fortawesome/fontawesome-free/webfonts"
target = "static/webfonts"
5.35 Multi-host Server Configuration
[server]
[[server.headers]]
for = "/**"
[server.headers.values]
X-Frame-Options = "DENY"
Content-Security-Policy = "default-src 'self'"
[[server.redirects]]
from = "/old/**"
to = "/new/:splat"
status = 301
[[server.redirects]]
from = "/api/**"
to = "https://api.example.com/:splat"
status = 200 # Proxy (rewrite, not redirect)
6. Troubleshooting
6.1 Build Errors
"Error: module 'X' not found"
Hugo cannot resolve a module dependency.
# Re-fetch modules
hugo mod get
# Clean and re-fetch
hugo mod clean --all
hugo mod get
If using go.sum, ensure it's committed. Try hugo mod tidy to remove stale entries.
"Error building site: TOCSS: failed to transform"
Sass/SCSS compilation failed. Common causes:
- Missing Dart Sass: Install
dart-sassorsass-embeddedand ensure it's in PATH. - Wrong edition: You need the extended edition of Hugo for built-in LibSass.
- Invalid SCSS syntax: Check the file referenced in the error message.
# Verify Hugo edition
hugo version
# Should show "+extended"
# Set Dart Sass path explicitly
export DART_SASS_BINARY=/usr/local/bin/sass
"Error: POSTCSS: failed to transform"
PostCSS processing failed.
# Ensure Node.js dependencies are installed
npm install
# Verify postcss is available
npx postcss --version
# Check postcss.config.js exists in project root
"Error building site: ... timed out"
Page generation exceeded the timeout (default 30 seconds).
# Increase timeout in hugo.toml
timeout = "120s"
This can happen with complex template logic, heavy image processing, or large
resources.GetRemote calls.
"WARN duplicate target path"
Two pages resolve to the same URL.
hugo --printPathWarnings
Fix by adjusting slug, url, or permalinks in the conflicting pages.
"Template metrics: slow templates"
hugo --templateMetrics --templateMetricsHints
Look for templates with high cumulative time. Common culprits: uncached
resources.GetRemote, unoptimized image processing inside loops, repeated
.GetPage calls.
6.2 Server Issues
Port Already in Use
# Use a different port
hugo server -p 8080
# Or find and kill the process using port 1313
lsof -ti :1313 | xargs kill
Live Reload Not Working
- Check that
--disableLiveReloadis not set. - Browser extensions (ad blockers, privacy tools) may block WebSocket connections.
- If behind a reverse proxy, ensure WebSocket upgrade headers are forwarded.
- Try
--disableFastRenderfor a full rebuild on each change.
File Watching Not Working (Network Drives / VMs)
hugo server --poll 700ms
Polling mode uses periodic filesystem checks instead of inotify/fsevents, which don't work on network-mounted filesystems.
Server Not Accessible from LAN
hugo server --bind 0.0.0.0 -b http://192.168.1.100:1313/
The default bind address (127.0.0.1) only accepts local connections.
6.3 Content Issues
Page Not Appearing
Check these common causes:
- Draft:
draft: truein front matter -- use-Dflag or setdraft: false. - Future date:
dateis in the future -- use-Fflag or fix the date. - Expired:
expiryDatehas passed -- use-Eflag or remove/extend the date. - Wrong section: File is not in the expected content directory.
- Missing
_index.md: Section pages require_index.mdto be listed. - Disabled kind: Check
disableKindsin config.
Front Matter Not Parsed
Ensure delimiters are correct:
- YAML: three dashes
---on their own line, top and bottom - TOML: three plus signs
+++on their own line, top and bottom - JSON: opening
{and closing}(first and only JSON block)
No blank lines before the opening delimiter.
Taxonomy Pages Missing
Ensure taxonomies are configured:
[taxonomies]
tag = "tags"
category = "categories"
If you override [taxonomies], you must include ALL taxonomies -- even the
defaults (tags, categories) if you want to keep them.
Unicode / Accent Issues in URLs
removePathAccents = true
Markdown Not Rendering
Check that the file has a supported extension (.md, .markdown, .mdown).
For raw HTML in Markdown:
[markup.goldmark.renderer]
unsafe = true
6.4 Template Issues
"Can't evaluate field X in type Y"
You're accessing a variable that doesn't exist on the object. Common mistakes:
.Params.titlevs.Title(params are lowercase).Site.Params.xvs.Params.x(site params vs page params)- Missing
withorifguard around optional values
Partial Not Found
Partials must live in layouts/partials/. The call omits the directory:
{{ partial "header.html" . }}
Corresponds to layouts/partials/header.html.
Template Changes Not Reflected
In server mode with fast render:
hugo server --disableFastRender
Or restart the server. Some template changes (especially in baseof.html)
require a full rebuild.
6.5 Image Processing Issues
"Image not found" or Nil Pointer
Images must be in assets/ (for global resources) or in a page bundle (for
page resources). Files in static/ cannot be processed.
<!-- Correct: from assets/ -->
{{ $img := resources.Get "images/hero.jpg" }}
<!-- Correct: from page bundle -->
{{ $img := .Resources.GetMatch "hero.*" }}
<!-- Wrong: static/ files can't be processed -->
EXIF / Image Metadata Warnings
Some images trigger decode warnings (related to #14758). These are non-fatal warnings. To suppress:
ignoreLogs = ["warning-image-metadata"]
WebP / AVIF Not Working
Requires the extended edition. Verify with hugo version (must show +extended).
6.6 Module Issues
"go.sum: not found"
hugo mod tidy
Module Cache Stale
hugo mod clean --all
hugo mod get -u
Vendor Directory Issues
# Re-vendor all dependencies
hugo mod vendor
# Build using vendored modules (ignore _vendor when this glob matches)
hugo --ignoreVendorPaths "**"
6.7 Performance Issues
Slow Builds
- Profile templates:
hugo --templateMetrics --templateMetricsHints - Reduce image processing: Cache processed images, limit resize operations.
- Avoid
.Site.Pagesin templates: Use.Site.RegularPagesor scope queries. - Enable caching: Configure
[caches]section. - Limit taxonomies: Disable unused taxonomies.
- Use
--gc: Clean up unused cache files.
hugo --gc --minify
Memory Issues
export HUGO_MEMORYLIMIT=4096 # MB
hugo --gc
Parallel Processing
export HUGO_NUMWORKERMULTIPLIER=2 # Default: 1 (num CPUs)
6.8 Deployment Issues
"deploy" Command Not Found
The deploy command requires Hugo to be built with the withdeploy tag. Binary
releases may not include it. Build from source:
go install -tags withdeploy github.com/gohugoio/hugo@latest
Base URL Wrong in Production
Ensure baseURL matches your production domain exactly:
baseURL = "https://www.example.com/"
Or override at build time:
hugo -b https://www.example.com/
Minification Breaks JavaScript
Hugo's minifier can reorder const initializations (#14760). If your JS
breaks after minification:
[minify]
disableJS = true
Or use js.Build with its own minify option instead, which uses esbuild
(more JavaScript-aware).
SVG Minification Breaks Alpine.js
The SVG minifier can corrupt Alpine.js x-bind attributes (#14669).
Workaround:
[minify]
disableSVG = true
6.9 Hugo New Ignores Environment
The hugo new command does not respect the -e flag for environment selection
(#13722). It always uses the default configuration. Workaround:
manually apply environment-specific values after creation.
6.10 Syntax Highlighting Style Mismatch
The github Chroma style may not match actual GitHub rendering for dark mode
(#14730). Use github-dark explicitly for dark themes:
hugo gen chromastyles --style=github-dark > static/css/syntax-dark.css
6.11 :contentbasename Broken for Taxonomies
The :contentbasename permalink token has issues with taxonomy pages since
v0.153 (#14325). Workaround: use :slug or :title tokens
for taxonomy permalinks.
6.12 js.Build Output Varies by Output Format
Different output formats may produce different js.Build results
(#14254). Ensure consistent js.Build options across all output
formats, or use resource caching.
6.13 Cache :resourceDir Token Resolution
The :resourceDir token in cache paths may not resolve as expected
(#14165). Use explicit absolute paths in cache configuration
if you encounter issues:
[caches.assets]
dir = "/tmp/hugo-cache/assets"
maxAge = -1
6.14 Commands Apply Config from All Environments
Certain commands may unexpectedly apply configuration from all environment directories rather than just the target environment (#14763). Workaround: keep environment-specific overrides minimal and non-conflicting.
6.15 Stacktrace Lost on Panic
When Hugo panics during template execution, the stacktrace may not point to the
template that caused the issue (#13811). Use --panicOnWarning during
debugging to catch issues earlier, and --logLevel debug for more context.
6.16 Language/Role/Version in Filenames
Content filenames with language, role, or version suffixes may not be parsed as expected (#14756). Prefer using front matter for these metadata fields rather than encoding them in the filename.
6.17 Build Lock File Conflicts
Hugo creates .hugo_build.lock during builds. If you encounter lock conflicts
in CI:
hugo --noBuildLock
6.18 CORS Issues with Dev Server
The dev server doesn't set CORS headers by default. Use server configuration:
[server]
[[server.headers]]
for = "/api/**"
[server.headers.values]
Access-Control-Allow-Origin = "*"
6.19 Config File Not Found
Hugo looks for hugo.toml, hugo.yaml, or hugo.json in the project root
(or the path specified by --source). Common issues:
- Wrong directory: Run Hugo from the project root.
- Wrong filename: Hugo does not support
config.tomlin recent versions. Rename tohugo.toml. - Config directory: If using
config/, ensure_default/hugo.tomlexists.
# Specify config explicitly
hugo --config my-config.toml
# Specify config directory
hugo --configDir my-config/
6.20 Emoji Shortcodes Not Rendering
enableEmoji = true
Without this, :smile: renders as literal text.
6.21 i18n Translation Warnings
hugo --printI18nWarnings
Shows missing translation keys. Provide translations in i18n/ files.
6.22 Assets Not Found After Moving to Modules
When migrating from git submodule themes to Hugo Modules, asset paths may
change. Verify mounts:
hugo config mounts
6.23 Ignoring Cache for Fresh Builds
hugo --ignoreCache
Forces Hugo to bypass all caches and rebuild from scratch.
6.24 Content Not Updating in Server Mode
Fast render mode only rebuilds changed pages. If related pages don't update:
hugo server --disableFastRender
Or press Ctrl+C and restart the server.
6.25 "Security policy violation" Errors
Hugo restricts which external programs can run. If you get a security policy error:
[security.exec]
allow = ["^dart-sass$", "^go$", "^git$", "^npx$", "^postcss$", "^tailwindcss$", "^your-tool$"]
Add your tool's binary name to the allow list.
6.26 Exif Jsonify Type Info
Calling jsonify on .Exif data may produce unexpected type information
in the output (#10345). Extract specific EXIF fields
individually rather than serializing the entire .Exif object.
7. FAQ
General
Q: What is Hugo? A: Hugo is a static site generator written in Go. It takes content files (Markdown, AsciiDoc, etc.) and templates, and produces a complete static website that can be served by any web server or CDN.
Q: How fast is Hugo? A: Hugo routinely builds thousands of pages per second. A site with 10,000+ pages typically builds in under 10 seconds. Build speed depends on template complexity, image processing, and content volume -- not Hugo itself.
Q: What's the difference between Hugo standard and extended editions? A: The extended edition adds Sass/SCSS compilation (LibSass), WebP encoding, and regex-based Unicode normalization. Most users should install the extended edition.
Q: What content formats does Hugo support? A: Markdown (via Goldmark -- the default), AsciiDoc (via Asciidoctor), Org Mode, reStructuredText, and Pandoc. Markdown is by far the most common.
Q: What front matter formats does Hugo support?
A: YAML (delimited by ---), TOML (delimited by +++), and JSON (wrapped
in {}). YAML is the most common convention.
Q: What license is Hugo released under? A: Apache License 2.0.
Q: What are the page kinds Hugo supports?
A: home, page, section, taxonomy, term, RSS, sitemap,
robotsTXT, and 404.
Installation
Q: Do I need Go installed to use Hugo? A: No. Pre-built binaries are standalone. You only need Go if building from source or using Hugo Modules (Go handles module resolution behind the scenes, but Hugo bundles the necessary tooling).
Q: How do I check my Hugo version?
A: hugo version or hugo env for full environment details.
Q: How do I upgrade Hugo?
A: Use your package manager (brew upgrade hugo, choco upgrade hugo-extended,
etc.) or download the latest binary from the releases page.
Q: What Go version do I need to build Hugo from source? A: Go 1.25.0 or later.
Content
Q: What's the difference between index.md and _index.md?
A: _index.md (with underscore) is a branch bundle -- it defines a section
list page and can have child pages. index.md (without underscore) is a
leaf bundle -- it defines a single page and its resources.
Q: How do I create a page at a specific URL?
A: Use the url front matter field:
---
url: /custom/path/
---
Q: How do I exclude a page from listings?
A: Set _build options in front matter:
---
_build:
list: never
render: always
---
Q: How do I set a custom slug?
A: Use the slug front matter field:
---
slug: "my-custom-slug"
---
Q: Can I use HTML in Markdown files? A: By default, raw HTML in Markdown is stripped. Enable it:
[markup.goldmark.renderer]
unsafe = true
Q: How do I add metadata to pages without rendering them? A: Use headless bundles:
# content/data-pages/my-data/index.md
---
headless: true
---
Headless pages are accessible in templates but don't generate output files.
Q: How do I control the order of pages in a section?
A: Use weight in front matter (lower weight = earlier in list). Default
ordering is by date (newest first).
Q: How does the <!--more--> divider work?
A: Place <!--more--> in your content to define a manual summary split point.
Everything above the divider becomes the .Summary; everything below is
only shown on the full page.
Q: What is a headless bundle?
A: A leaf bundle with headless: true in front matter. It is processed (so
you can access its resources in templates) but does not produce an output page
or appear in any listing.
Configuration
Q: Can I use multiple configuration files?
A: Yes. Use the config directory approach (config/_default/, environment
overrides) or pass multiple files: --config a.toml,b.toml.
Q: How do I set config values via environment variables?
A: Prefix with HUGO_ and use underscores for nesting:
HUGO_PARAMS_AUTHOR="Jane" sets params.author.
Q: What's the default environment for hugo vs hugo server?
A: hugo (build) defaults to production. hugo server defaults to
development. Override with -e or HUGO_ENVIRONMENT.
Q: What config file names does Hugo support?
A: hugo.toml, hugo.yaml, or hugo.json. The old config.toml name is
no longer auto-detected in recent versions.
Q: How do I use a config directory instead of a single file?
A: Create a config/ directory with _default/hugo.toml as the base, and
add environment-specific subdirectories (production/, staging/, etc.)
with overlay files. Hugo merges them automatically.
Themes
Q: Where do I find Hugo themes? A: The official theme directory is at themes.gohugo.io. Themes can also be installed as Hugo Modules from any Git repository.
Q: How do I override a theme template?
A: Create the same file path in your project's layouts/ directory. Hugo
uses your version instead of the theme's. For example, to override the theme's
layouts/_default/single.html, create layouts/_default/single.html in your
project.
Q: Can I use multiple themes? A: Yes. Specify multiple themes in config:
theme = ["theme-base", "theme-override"]
Later themes override earlier ones (right wins).
Q: How do I create my own theme?
A: hugo new theme mytheme scaffolds a theme skeleton in themes/mytheme/.
Q: What is the theme lookup order?
A: Hugo checks your project's layouts/ first, then themes in reverse order
(last theme listed wins). This applies to templates, partials, shortcodes,
and archetypes.
Deployment
Q: What do I need to deploy a Hugo site? A: Just a web server or static file host. Hugo outputs plain HTML/CSS/JS. Any host that serves static files works: Netlify, Vercel, Cloudflare Pages, GitHub Pages, S3, a VPS with nginx, etc.
Q: Does Hugo have a built-in deploy command?
A: Yes, hugo deploy supports S3, GCS, and Azure Blob Storage. It requires
the withdeploy build tag (included in some binary releases). Configure
targets in [deployment] in your config.
Q: How do I handle redirects?
A: Hugo supports aliases in front matter (generates HTML redirect files).
For server-side redirects, use your hosting platform's native redirect mechanism.
Q: How do I set up continuous deployment?
A: Connect your Git repository to Netlify, Vercel, Cloudflare Pages, or
GitHub Actions. Set the build command to hugo --minify and the publish
directory to public. Pin the Hugo version via environment variable.
Performance
Q: Why is my build slow?
A: Common causes: heavy image processing, complex template logic (especially
in loops), excessive resources.GetRemote calls, unused taxonomy generation.
Profile with hugo --templateMetrics --templateMetricsHints.
Q: How do I speed up image processing? A: Use image caching (enabled by default), process images once and reference the result, avoid processing in loops. Consider generating image variants at fewer breakpoints.
Q: What is --gc and when should I use it?
A: The --gc flag runs garbage collection after the build, removing unused
cached files (processed images, resources). Use it in CI or when disk space
is a concern.
Q: How can I reduce memory usage during builds?
A: Set HUGO_MEMORYLIMIT (in MB), reduce image processing, use --gc, and
avoid loading entire site page collections in templates when a scoped query
will do.
Modules
Q: What are Hugo Modules?
A: Hugo Modules use Go Modules to manage project dependencies. Themes, content,
data, assets, layouts -- anything can be a module. They replace git submodule
for dependency management.
Q: Do I need Go installed for Hugo Modules?
A: Hugo ships with Go module support, but having Go installed helps for
module initialization (hugo mod init) and management.
Q: How do I update a module?
A: hugo mod get -u github.com/owner/module or hugo mod get -u for all.
Q: How do I pin a module to a specific version?
A: hugo mod get github.com/owner/module@v1.2.3. The version is recorded
in go.mod.
Multilingual
Q: How do I set up a multilingual site?
A: Configure [languages] in your config with weight, language name, and
any language-specific parameters. Create translated content with filename
suffixes (.fr.md) or directory structure (content/fr/).
Q: How do I translate menus and strings?
A: Use i18n/ files for UI strings. Menus can be defined per-language in
config under each [languages.xx] section.
Q: How does Hugo determine the default language?
A: Via defaultContentLanguage in config (defaults to "en"). Content files
without a language suffix are assigned to the default language.
Templating
Q: What templating language does Hugo use?
A: Go's html/template and text/template packages, with Hugo-specific
functions and methods added on top.
Q: What is baseof.html?
A: The base template (layouts/_default/baseof.html) defines the overall HTML
structure. Other templates define named blocks ({{ block "main" . }}) that
fill in sections of the base template.
Q: How do I access site-wide parameters in templates?
A: Use .Site.Params.yourParam. Define parameters under [params] in config.
Q: How do I pass variables to partials?
A: Pass a context (usually . for the current page) or a custom dict:
{{ partial "mypartial.html" (dict "page" . "color" "blue") }}
CLI Reference
Global Flags
These flags work with every Hugo command:
| Flag | Short | Default | Description |
|---|---|---|---|
--source |
-s |
. |
Filesystem path to read files from |
--destination |
-d |
public |
Filesystem path to write files to |
--environment |
-e |
varies | Build environment |
--config |
auto-detected | Config file path | |
--configDir |
config |
Config directory path | |
--themesDir |
themes |
Path to themes directory | |
--quiet |
false |
Suppress non-error output | |
--logLevel |
warn |
Log level: debug, info, warn, error | |
--renderToMemory |
-M |
false |
Render to memory (no disk write) |
--ignoreVendorPaths |
Glob pattern to ignore _vendor paths |
||
--noBuildLock |
false |
Don't create .hugo_build.lock |
|
--clock |
Override system clock (ISO 8601 format) |
Build Flags
These flags work with hugo and hugo server:
| Flag | Short | Default | Description |
|---|---|---|---|
--theme |
-t |
config value | Theme(s) to use |
--baseURL |
-b |
config value | Root URL |
--contentDir |
-c |
content |
Content directory |
--layoutDir |
-l |
layouts |
Layout directory |
--cacheDir |
OS temp | Cache directory | |
--buildDrafts |
-D |
false |
Include drafts |
--buildFuture |
-F |
false |
Include future content |
--buildExpired |
-E |
false |
Include expired content |
--enableGitInfo |
false |
Add Git info to pages | |
--cleanDestinationDir |
false |
Remove dest files not from static | |
--minify |
false |
Minify output | |
--watch |
-w |
false |
Watch for changes |
--gc |
false |
Run cache cleanup after build | |
--ignoreCache |
false |
Bypass cache directory | |
--renderSegments |
Named segments to render | ||
--disableKinds |
Page kinds to disable | ||
--poll |
File watch poll interval | ||
--templateMetrics |
false |
Display template timing metrics | |
--templateMetricsHints |
false |
Show template optimization hints | |
--forceSyncStatic |
false |
Copy all static files on change | |
--noTimes |
false |
Don't sync modification times | |
--noChmod |
false |
Don't sync permissions | |
--printI18nWarnings |
false |
Print missing i18n translations | |
--printPathWarnings |
false |
Print duplicate path warnings | |
--printUnusedTemplates |
false |
Warn on unused templates | |
--panicOnWarning |
false |
Panic on WARNING log entries |
Server Flags
These flags are specific to hugo server:
| Flag | Short | Default | Description |
|---|---|---|---|
--port |
-p |
1313 |
Port to listen on |
--bind |
127.0.0.1 |
Interface to bind to | |
--liveReloadPort |
-1 (auto) |
Live reload port | |
--disableLiveReload |
false |
Disable live reload | |
--disableFastRender |
false |
Full re-render on each change | |
--disableBrowserError |
false |
Don't show errors in browser | |
--navigateToChanged |
false |
Navigate to changed content | |
--renderStaticToDisk |
false |
Serve static from disk | |
--noHTTPCache |
false |
Disable HTTP caching | |
--tlsAuto |
false |
Auto-generate local TLS certs | |
--tlsCertFile |
TLS certificate file | ||
--tlsKeyFile |
TLS key file |
Command Reference
| Command | Description |
|---|---|
hugo / hugo build |
Build the site |
hugo server |
Start development server with live reload |
hugo server trust |
Install/uninstall local CA for TLS |
hugo new content <path> |
Create content file from archetype |
hugo new project <path> |
Scaffold new Hugo project |
hugo new theme <name> |
Scaffold new theme |
hugo config |
Print merged site configuration |
hugo config mounts |
Print configured file mounts |
hugo mod init |
Initialize Hugo Module (creates go.mod) |
hugo mod get |
Resolve and install module dependencies |
hugo mod tidy |
Remove unused module entries |
hugo mod vendor |
Vendor dependencies into _vendor/ |
hugo mod verify |
Verify module dependency checksums |
hugo mod graph |
Print module dependency graph |
hugo mod clean |
Delete module cache |
hugo mod npm pack |
Merge Node.js deps into npm workspace |
hugo convert toJSON |
Convert front matter to JSON |
hugo convert toTOML |
Convert front matter to TOML |
hugo convert toYAML |
Convert front matter to YAML |
hugo import jekyll <src> <dest> |
Import Jekyll site |
hugo list drafts |
List draft content (CSV) |
hugo list future |
List future-dated content (CSV) |
hugo list expired |
List expired content (CSV) |
hugo list all |
List all content (CSV) |
hugo list published |
List published content (CSV) |
hugo deploy |
Deploy to cloud provider |
hugo gen chromastyles |
Generate Chroma CSS stylesheet |
hugo gen doc |
Generate CLI markdown documentation |
hugo gen man |
Generate man pages |
hugo env |
Display version and environment info |
hugo version |
Display version string |
Environment Variables Reference
| Variable | Description |
|---|---|
HUGO_ENVIRONMENT / HUGO_ENV |
Build environment (overrides -e flag) |
HUGO_NUMWORKERMULTIPLIER |
Parallel worker multiplier (default: CPU count) |
HUGO_MEMORYLIMIT |
Memory limit in MB for image processing |
HUGO_FILE_LOG_FORMAT |
Custom format for file change logging |
HUGO_BUILD_TAGS |
Build tags for Go compilation |
DART_SASS_BINARY |
Path to Dart Sass binary |
NODE_PATH |
Node.js module resolution path |
NO_COLOR |
Disable colored output (any value) |
HUGO_* |
Any config key: HUGO_BASEURL, HUGO_TITLE, HUGO_PARAMS_X, etc. |
Important
This guide covers Hugo's complete CLI surface and core workflows. For architecture internals, advanced security configuration, detailed deployment strategies, and infrastructure guidance, see the Admin Guide.