Hugo — API Surface#
API types#
Hugo exposes four distinct API surfaces:
- CLI — the primary user-facing interface
- HTTP dev server — a local static file server (
hugo server) with dev-only endpoints - Template Function API — Go template functions available to theme/site authors
- Library (limited) — packages consumed by other Hugo tools or tests; not a stable public library
There is no REST API, no gRPC, and no formal plugin system at runtime.
CLI#
Framework#
github.com/bep/simplecobra — a thin wrapper around github.com/spf13/cobra that enforces an interface-based command pattern (simplecobra.Commander) instead of cobra’s struct-literal approach. Every command implements Name(), Init(), Run(), PreRun(), and Commands().
Command structure#
hugo ← root command (also invokes build via hugoBuildCommand alias)
build ← explicit alias for root build behavior
server (serve) ← embedded dev web server with live reload
trust ← install/uninstall local TLS CA cert
version ← print Hugo version + build info
env ← print Hugo environment (OS, Go version, build tags)
config ← print resolved site configuration
mounts ← print configured module mounts
new ← scaffold new items
content ← create a new content file from archetype
project ← create a new Hugo project skeleton
theme ← create a new Hugo theme skeleton
convert ← convert front matter format (toYAML, toJSON, toTOML)
import ← import from other SSGs
jekyll ← import a Jekyll site
list ← list content pages
all ← all pages
drafts ← draft pages
future ← pages with future publish dates
expired ← expired pages
published ← published pages
mod ← Hugo Modules management
init ← initialize a new module
verify ← verify module checksums
graph ← print module dependency graph
clean ← delete module cache
tidy ← remove unused module entries
vendor ← vendor module dependencies to _vendor/
get ← resolve/update a module dependency
npm
pack ← pack npm dependencies from modules
gen ← internal code/doc generation
chromastyles ← generate CSS for a Chroma syntax highlight theme
man ← generate man pages
doc ← generate CLI reference docs
docshelper ← generate internal docs helper JSON
deploy ← deploy public/ to cloud storage
release ← internal release helper (maintainers only)Global (persistent) flags#
| Flag | Default | Purpose |
|---|---|---|
--source, -s | cwd | filesystem path to read files from |
--destination, -d | public/ | filesystem path to write output to |
--environment, -e | production | build environment (selects config dir) |
--config | auto | explicit config file path |
--configDir | config | config directory |
--themesDir | override themes directory | |
--logLevel | warn | debug|info|warn|error |
--quiet | false | suppress non-essential output |
--renderToMemory, -M | false | render to memory instead of disk |
--noBuildLock | false | skip .hugo_build.lock |
--clock | freeze Hugo’s clock (for reproducible builds) | |
--ignoreVendorPaths | glob to bypass _vendor for matched modules |
Build-specific flags (on hugo and hugo server)#
| Flag | Purpose |
|---|---|
--theme, -t | themes to activate |
--baseURL, -b | override base URL |
--buildDrafts, -D | include drafts |
--buildFuture, -F | include future-dated content |
--buildExpired, -E | include expired content |
--minify | minify output (HTML, XML, JS, CSS, SVG, JSON) |
--disableKinds | skip generating page kinds (home, section, taxonomy, etc.) |
--enableGitInfo | add Git metadata to pages |
--gc | garbage-collect unused cache files |
--templateMetrics | print per-template execution timing |
--renderSegments | render only named segments |
--cleanDestinationDir | remove stale files from public/ |
--ignoreCache | bypass file cache |
--poll | use polling instead of fsnotify (e.g. --poll 700ms) |
HTTP Dev Server (hugo server)#
The dev server is not a general-purpose HTTP server. It is a purpose-built static file server with dev-only features. Not intended for production use.
Server-specific flags#
| Flag | Default | Purpose |
|---|---|---|
--port, -p | 1313 | listen port |
--bind | 127.0.0.1 | network interface |
--liveReloadPort | -1 (auto) | livereload WebSocket port |
--tlsAuto | false | auto-generate locally-trusted TLS cert |
--tlsCertFile / --tlsKeyFile | manual TLS cert | |
--watch, -w | true | watch for changes |
--disableLiveReload | false | watch without browser refresh |
--disableFastRender | false | full rebuild on every change |
--renderStaticToDisk | false | serve static from disk, dynamic from memory |
--noHTTPCache | false | add Cache-Control: no-store headers |
--navigateToChanged, -N | false | auto-navigate browser to changed page |
--openBrowser, -O | false | open browser on startup |
--pprof | false | enable pprof server on :8080 |
Route table#
{baseURL}/ → static file server over public/ (http.FileServer)
{baseURL}/livereload.js → embedded livereload client script
{baseURL}/livereload → WebSocket upgrade endpoint (livereload protocol)
/__stop → test-mode shutdown endpoint (not exposed in normal use)Middleware chain (applied to all static requests)#
- Error display — if build error present, render error page with injected livereload
- Cache headers — inject
no-storeif--noHTTPCache - Custom server headers — match request URI against
server.headersconfig rules - Redirect rules — match against
server.redirectsconfig; handles 301/302/404/200-rewrite - Fast render — on navigation request to unvisited URL, trigger partial re-render before serving
- Static file handler —
http.FileServerover afero-backed public directory - Livereload injection — response transformer injects
<script>tag into HTML responses (transform/livereloadinject)
Custom response header#
X-Hugo-Redirect: true is set on responses that were redirected via Hugo’s redirect rules (mirrors Netlify behavior).
Template Function API#
This is the largest and most important API surface for Hugo users. Theme and site authors call these functions from Go text/template / html/template templates. Each namespace is a struct registered as a global template variable (e.g. {{ collections.Where . "Section" "blog" }}).
Hugo exposes ~30 namespaces. Most functions are also available as top-level aliases without the namespace prefix.
Namespace summary#
| Namespace | Approx. functions | Key purpose |
|---|---|---|
collections | ~138 | slice/map operations: Where, Group, Sort, Shuffle, Uniq, Apply, Append, Merge, After, First, Last, Index, In, Intersect, Reverse, Seq, Dictionary, Slice |
strings | ~64 | string manipulation: HasPrefix, TrimPrefix, Replace, Split, Upper, Lower, Truncate, Title, Chomp, RuneCount |
math | ~61 | arithmetic, log, floor, ceil, sqrt, min, max, mod, rand |
compare | ~39 | eq, ne, lt, gt, ge, le, default, cond |
resources | ~21 | asset pipeline: Get, GetRemote, Match, ByType, Concat, FromString, ExecuteAsTemplate, Fingerprint, Minify, PostProcess, Copy |
urls | ~20 | AbsURL, RelURL, URLize, Anchorize, AbsLangURL, RelLangURL |
partials | ~20 | Include, IncludeCached, Return |
path | ~17 | Join, Dir, Base, Ext, Split, Clean |
css | ~17 | Sass/SCSS: Sass (Dart Sass), PostCSS |
time | ~14 | Now, Format, Since, Until, ParseDuration, AsTime |
safe | ~14 | type-safe HTML/JS/CSS/URL trust markers: HTML, JS, CSS, URL, HTMLAttr |
fmt | ~14 | Errorf, Printf, Println, Sprint, Sprintf |
reflect | ~13 | IsMap, IsSlice, IsString, IsFloat, IsInt, IsBool |
lang | ~13 | Translate (i18n), FormatNumber, FormatCurrency, FormatAccounting, FormatPercent |
images | ~13 | Filter, Process, Config, image filters (Brightness, Contrast, Grayscale, Pixelate, Blur, etc.) |
debug | ~12 | Dump, Timer — development aids |
cast | ~11 | ToInt, ToString, ToFloat, ToBool, ToTime, ToSlice |
crypto | ~10 | MD5, SHA1, SHA256, FNV32a, HMAC |
encoding | ~8 | Base64Encode/Decode, Jsonify, Unmarshal (TOML/YAML/JSON/CSV) |
inflect | ~6 | Humanize, Pluralize, Singularize |
js | — | esbuild: Build, Babel |
hugo | — | Hugo version, environment, .IsProduction, .IsServer, BuildDate |
page | — | page-level helpers |
site | — | site-level helpers |
hash | — | FNV32a, XxHash |
diagrams | — | Goat (ASCII art diagrams) |
openapi | — | load and query OpenAPI specs |
transform | — | Highlight, MarkdownTo, Remarshal, ToMath (KaTeX) |
templates | — | Exists, DoDefer |
Page object API (template dot .)#
The page.Page interface is the central object available as . in page templates. It is composed from ~20 embedded provider interfaces:
| Provider | Key methods |
|---|---|
ContentProvider | .Content, .Plain, .PlainWords, .Summary, .Truncated, .WordCount, .ReadingTime, .FuzzyWordCount |
PageMetaProvider | .Title, .Date, .PublishDate, .ExpiryDate, .Params, .Weight, .Description, .Keywords, .Aliases, .Slug, .URL, .Draft, .Kind, .Type, .Section, .Lang |
ChildCareProvider | .Pages, .RegularPages, .RegularPagesRecursive, .Sections |
TreeProvider | .Parent, .Ancestors, .FirstSection, .IsAncestor, .IsDescendant, .InSection |
OutputFormatsProvider | .OutputFormats, .AlternativeOutputFormats |
TranslationsProvider | .Translations, .AllTranslations, .IsTranslated |
FileProvider | .File (path, filename, basename, dir, extension, logical name) |
GitInfoProvider | .GitInfo (hash, date, author, CODEOWNERS) |
RefProvider | .Ref, .RelRef |
TableOfContentsProvider | .TableOfContents |
RelatedKeywordsProvider | for .Site.RegularPages.Related |
ShortcodeInfoProvider | .HasShortcode |
SitesProvider | .Site, .Sites |
GetPageProvider | .GetPage |
Plugin / Extension System#
Hugo has no runtime plugin system. All extensibility is compile-time or configuration-driven:
Markup converters (markup/converter)#
The only true runtime extension point. A converter.Provider registers a named converter identified by a string (e.g. "goldmark", "asciidocext", "pandoc", "rst", "org").
- Interface:
converter.Provider+converter.ProviderProvider - Registration:
markup.NewConverterProvider(cfg, providers...)— called atDepsinit - Built-in providers: goldmark (default), asciidocext (calls
asciidoctorbinary), pandoc (callspandocbinary), rst (callsrst2htmlbinary), org-mode - External converters must be compiled in — no dynamic loading
Hugo Modules (composition, not code extension)#
Hugo’s module system (mirrors Go modules) lets users compose themes, content, and assets from multiple sources. Not a code plugin system; modules can only contribute file system content (layouts, content, assets, i18n, static, data).
Build-tag editions#
Three compile-time editions control optional features:
- none: pure Go, no CGO
- extended: adds Dart Sass (via WASM/warpc) and image processing (libwebp via CGO or WASM)
- withdeploy: adds cloud deploy drivers (AWS S3, GCS, Azure Blob)
Library API (limited / internal use)#
Hugo does not position itself as a Go library for external consumers. The module path is github.com/gohugoio/hugo and there is no stable public API contract. However, several packages are usable by tools:
github.com/gohugoio/hugo/hugolib— core build API (NewHugoSites,Build); used by hugo itself and some third-party IDE integrationsgithub.com/gohugoio/hugo/config/allconfig— config loadinggithub.com/gohugoio/hugo/common/hugo— version infogithub.com/gohugoio/hugo/resources/page—page.Pageinterface (useful for testing)
No versioning strategy is visible for library consumers. Breaking changes happen freely between Hugo releases. The idiomatic way to embed Hugo is to pin to a specific tag and accept churn.
API design observations#
CLI-first design. All user-facing functionality is CLI. The template API is a secondary surface. There is no admin API, no REST endpoint, no programmatic trigger for builds — the intended integration point is shell scripting around
hugoinvocations.Template API surface is enormous. ~30 namespaces with hundreds of functions make the template API the richest part of the surface. The namespace approach (
collections.Wherevswhere) gives discoverability but also creates naming redundancy.simplecobra over raw cobra is an architectural preference: each command is a named type implementing an interface, not an anonymous struct literal. This improves testability and discoverability but adds boilerplate. The pattern is unique to Hugo in the Go ecosystem.
Dev server is intentionally limited. The HTTP server does no content negotiation, no authentication, no dynamic routing beyond redirects defined in config. This is deliberate: Hugo’s output is always static files; the dev server exists only to preview them.
No gRPC, no proto files. The internal WASM RPC (
internal/warpc) uses a custom stdin/stdout message protocol — not gRPC — specifically to avoid CGO and network overhead. This is invisible to users.