Jesse A. Green / notebook

Hugo — User Guide

Generated May 2026 from gohugoio/hugo at 62cef36

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

Hugo is the world's fastest static site generator. 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 -D flag includes draft content. Always remove it (or set draft: 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 withdeploy tag excludes the hugo deploy command 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]
  # ...
[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 --disableFastRender when 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) }}

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
[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

enableGitInfo requires the full Git history. If you're using shallow clones in CI (e.g., actions/checkout with default depth: 1), set fetch-depth: 0 to 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.urls patterns. If a fetch fails silently, check your security configuration.

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:

  1. Missing Dart Sass: Install dart-sass or sass-embedded and ensure it's in PATH.
  2. Wrong edition: You need the extended edition of Hugo for built-in LibSass.
  3. 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

  1. Check that --disableLiveReload is not set.
  2. Browser extensions (ad blockers, privacy tools) may block WebSocket connections.
  3. If behind a reverse proxy, ensure WebSocket upgrade headers are forwarded.
  4. Try --disableFastRender for 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:

  1. Draft: draft: true in front matter -- use -D flag or set draft: false.
  2. Future date: date is in the future -- use -F flag or fix the date.
  3. Expired: expiryDate has passed -- use -E flag or remove/extend the date.
  4. Wrong section: File is not in the expected content directory.
  5. Missing _index.md: Section pages require _index.md to be listed.
  6. Disabled kind: Check disableKinds in 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.title vs .Title (params are lowercase)
  • .Site.Params.x vs .Params.x (site params vs page params)
  • Missing with or if guard 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

  1. Profile templates: hugo --templateMetrics --templateMetricsHints
  2. Reduce image processing: Cache processed images, limit resize operations.
  3. Avoid .Site.Pages in templates: Use .Site.RegularPages or scope queries.
  4. Enable caching: Configure [caches] section.
  5. Limit taxonomies: Disable unused taxonomies.
  6. 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:

  1. Wrong directory: Run Hugo from the project root.
  2. Wrong filename: Hugo does not support config.toml in recent versions. Rename to hugo.toml.
  3. Config directory: If using config/, ensure _default/hugo.toml exists.
# 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.