Hugo — Structure#

Layout pattern#

Custom — single-binary project with domain packages at root level.

Hugo does not follow standard Go Layout (no cmd/ directory). The single binary entry point is main.go at the repository root; all domain packages live as top-level directories. An internal/ directory exists for truly private infrastructure (WASM/JS bindings), and common/ groups shared utilities, but there is no pkg/ directory. The overall organization is by feature domain rather than by Go convention.

Directory map#

hugo/
├── main.go                   # Single entry point; delegates to commands.Execute()
├── magefile.go               # Mage build system (build, test, install, codegen)
├── Dockerfile                # Multi-stage Docker build; supports extended/withdeploy editions
│
├── commands/                 # Cobra CLI command definitions (build, server, new, mod, deploy…)
├── common/                   # Shared utility sub-packages (all prefixed h*)
│   ├── herrors/              # Error formatting with source context
│   ├── hexec/                # Safe external process execution
│   ├── hstrings/             # String helpers
│   ├── hsync/                # Sync primitives (cond vars, mutexes)
│   ├── htime/                # Time parsing/formatting
│   ├── loggers/              # Structured logging
│   ├── para/                 # Parallel worker utilities
│   ├── paths/                # Path normalization
│   └── types/                # Shared value types
│
├── config/                   # Configuration type hierarchy
│   ├── allconfig/            # Merged/resolved site config
│   ├── privacy/              # Privacy settings
│   ├── security/             # Security policy config
│   └── services/             # Third-party service config (Disqus, GA, etc.)
│
├── hugolib/                  # Core site-building orchestration
│   ├── doctree/              # Radix-trie page tree
│   ├── filesystems/          # Virtual filesystem assembly
│   ├── pagesfromdata/        # Pages generated from data files
│   └── sitesmatrix/          # Multi-site / multilingual matrix
│
├── resources/                # Resource pipeline (pages, images, JS, CSS, fonts)
│   ├── page/                 # Page type and collections
│   ├── images/               # Image processing (resize, crop, filter)
│   ├── resource/             # Base resource interface and registry
│   ├── resource_factories/   # Constructors for each resource type
│   └── resource_transformers/# Transform pipeline (babel, js, tocss, minifier, integrity…)
│
├── tpl/                      # Template function library (~30 sub-packages by category)
│   ├── tplimpl/              # Template store and function registration
│   ├── tplimplinit/          # Init-time wiring of tplimpl
│   ├── collections/          # Slice/map operations for templates
│   ├── strings/              # String functions
│   ├── images/               # Image-related template functions
│   ├── js/                   # JS bundling template functions
│   └── …                     # cast, compare, crypto, encoding, fmt, math, os, path, etc.
│
├── markup/                   # Content converters
│   ├── converter/            # Converter interface and registry
│   ├── goldmark/             # Goldmark Markdown renderer (primary)
│   ├── asciidocext/          # AsciiDoc via external binary
│   ├── org/                  # Org-mode via go-org
│   ├── pandoc/ rst/          # Pandoc and RST via external binaries
│   ├── highlight/            # Chroma syntax highlighting
│   └── tableofcontents/      # ToC extraction
│
├── hugofs/                   # Filesystem abstraction (wraps afero)
│   ├── files/                # File classifier / component types
│   └── hglob/                # Glob matching on virtual FS
│
├── modules/                  # Hugo Modules (Go-module-style theme/content imports)
│   └── npm/                  # npm dependency management for Hugo modules
│
├── cache/                    # Caching layers
│   ├── dynacache/            # Dynamic in-process cache with partition logic
│   ├── filecache/            # On-disk content/asset cache
│   └── httpcache/            # HTTP response cache
│
├── internal/                 # Private infrastructure
│   ├── js/                   # esbuild JS bundler integration (extended edition)
│   └── warpc/                # WASM RPC host (Dart Sass, KaTeX, WebP via WASM)
│
├── langs/                    # Language / i18n support
│   └── i18n/                 # Translation file loading and lookup
│
├── deploy/                   # Cloud deployment (build-tag gated: withdeploy)
│   └── deployconfig/         # Deployment target config (S3, GCS, Azure)
│
├── output/                   # Output format definitions (HTML, RSS, JSON, etc.)
├── media/                    # MIME type registry
├── identity/                 # Dependency identity / change tracking
├── parser/                   # Front matter and page parsing
│   ├── metadecoders/         # TOML/YAML/JSON/CSV/XML decoder
│   └── pageparser/           # Page content + front matter parser
│
├── transform/                # Output HTML transforms (livereload inject, URL rewrite)
├── navigation/               # Menu construction
├── source/                   # Source file abstraction
├── publisher/                # Final HTML output writer
├── watcher/                  # File change watcher
│   └── filenotify/           # fsnotify wrapper
├── livereload/               # WebSocket live-reload server
├── related/                  # Related content scoring
├── minifiers/                # HTML/CSS/JS minification
├── metrics/                  # Build timing and performance counters
├── helpers/                  # Legacy catch-all helpers (being gradually broken up)
├── compare/                  # Deep equality and ordering
├── bufferpool/               # sync.Pool wrappers for byte buffers
├── deps/                     # Central dependency container (Deps struct)
│
├── codegen/                  # Source code generation utilities
├── docshelper/               # Generates JSON docs from Hugo internals
├── releaser/                 # Release automation
├── htesting/                 # Test helpers and quick-test matchers
│   └── hqt/                  # qt-based test helpers
│
├── testscripts/              # txtar-based integration test scripts
└── docs/                     # Hugo's own documentation site (self-hosted)

Entry points#

FileBinaryDescription
main.gohugoSingle entry point — delegates to commands.Execute(os.Args[1:])

There is no cmd/ subdirectory. Hugo ships one binary. The commands/ package owns all Cobra command definitions: hugo (build), hugo server, hugo new, hugo mod, hugo deploy, hugo gen, hugo list, hugo convert, hugo env, hugo import, hugo release.

Package organization#

  • Internal packages (internal/):

    • internal/js — esbuild JavaScript bundler integration, used by the extended edition
    • internal/warpc — WASM RPC runtime for Dart Sass, KaTeX, and WebP processing without CGO
  • Public packages (pkg/): None — Hugo does not use a pkg/ convention. All top-level directories are de-facto packages accessible within the module.

  • Layering: Hugo uses a hub-and-spokes layering model rather than clean architecture or hexagonal:

    • deps/ holds the central Deps struct that wires together configuration, filesystem, and services — it acts as a service locator / dependency container.
    • hugolib/ is the orchestrator; it imports almost everything else.
    • resources/page is the heaviest domain object, imported by tpl/, hugolib/, and commands/.
    • common/ and bufferpool/ are at the bottom — imported by nearly all other packages.
    • tpl/ depends on resources/ and hugolib/ but not vice-versa (template functions are consumers, not producers of core logic).
    • No strict layering enforcement; circular imports are prevented by convention and careful factoring (e.g., identity/ is deliberately minimal to avoid cycles).

Build system#

  • Build tool: Mage (magefile.go) — Go-native build tool, no Makefile
  • Key targets:
    • mage hugo — build binary (default tags: none)
    • mage install — install binary
    • mage test — run full test suite
    • mage testRace — tests with race detector
    • mage generate — run codegen (page method stubs, docs helpers)
    • Build tags via HUGO_BUILD_TAGS env var: none | extended | withdeploy
  • Three build editions:
    • none — standard Hugo, pure Go, no CGO
    • extended — adds LibSass/Dart Sass (CSS processing), WebP image encoding; requires CGO or WASM fallback
    • withdeploy — adds extended + cloud deployment commands (AWS S3, GCS, Azure Blob)
  • Docker: Yes, multi-stage. Stage build cross-compiles with CGO using xx toolchain; stage dart-sass fetches the Dart Sass binary; stage final assembles the runtime image with Node.js, npm, git, and Dart Sass.

Notable structural decisions#

  1. Root-level binary, not cmd/: The single main.go at the repo root is deliberately minimal (5 lines). This is practical for a single-binary tool but deviates from standard Go Layout, occasionally causing confusion for contributors.

  2. common/h* micro-package pattern: Every utility sub-package under common/ uses an h prefix (herrors, hexec, hstrings, hsync…). This prevents shadowing stdlib names and signals internal provenance. The pattern produces ~18 small, focused packages instead of one large utils/ blob.

  3. Build-tag edition system: Three mutually-exclusive editions (none/extended/withdeploy) are selected at compile time via build tags. This cleanly gates CGO dependencies (LibSass, libwebp) so the standard edition ships as a fully static binary.

  4. tpl/ as a library of libraries: The ~30 sub-packages under tpl/ each expose a New() function returning a namespace struct; tpl/tplimpl collects them all and registers their methods into Go’s text/template. This design lets each function category evolve independently and be tested in isolation.

  5. internal/warpc WASM RPC: Rather than requiring CGO for Dart Sass or KaTeX, Hugo embeds a WASM runtime and communicates with compiled WASM modules via a custom RPC protocol. This enables the extended Sass features without CGO on platforms where CGO is unavailable, and is architecturally the most novel structural choice in the codebase.

  6. docs/ as a Hugo site inside Hugo: The project’s own documentation site lives in docs/ and is built with Hugo itself, providing a continuous integration check that real-world Hugo features keep working.

  7. testscripts/ txtar integration tests: End-to-end build scenarios are expressed as txtar scripts (a Go test scripting format), providing readable, self-contained integration tests that exercise the full build pipeline without needing external fixtures.