SOTA: Hugo Static Site Generator
As of 2026-07-28. Mode: survey (repo-grounded against PKB-theme). Freshness: findings older than 12 months are flagged [STALE]. Every numbered claim ends with its source and access date; anything unverifiable is marked [UNVERIFIED].
TL;DR
- The latest Hugo release is v0.164.0 (2026-07-06). Roughly 25 minor releases shipped in the last 19 months; the project is very actively maintained, still centered on Bjørn Erik Pedersen.
- The big theme-author events of the period: the v0.146 template-system rewrite (new
layouts/structure), v0.148 render-hookuseEmbeddedenums (replacingenableDefault), the v0.156 mass removal of long-deprecated APIs, v0.158languageCode→locale, v0.163 per-format imaging config, and v0.164resources.PostProcess→templates.Defer. - PKB-theme’s in-progress migration to
useEmbedded = 'fallback'is correct (minimum version v0.148.0, verified). But its CI pins Hugo 0.123.7 / 0.128.0 - below the theme’s ownmin_version = "0.136.0"and far below the README’s new “v0.148+” claim. Aligning versions is the top action. - Concrete code updates for this repo: replace
.Page.Scratch(deprecated v0.138.0) in thecite/sidenoteshortcodes, move the globalimaging.qualityinto per-format blocks, renamelanguageCode→locale, and audit two non-standard render hooks (render-inline.html,render-paragraph.html) that are not part of Hugo’s documented hook set.
Landscape
Release train & maintenance
Hugo ships a minor release roughly every 3–5 weeks with patch releases in between. From v0.140.0 (2024-12-17) to v0.164.0 (2026-07-06) there were 25 minor lines, the majority of which introduced at least one deprecation or small breaking change - Hugo deprecates aggressively and removes on a ~6–18 month horizon. Maintenance is healthy but concentrated: bep accounts for ~60–68% of commits; jmooring is the most visible secondary maintainer; ~210 open issues with closure rate exceeding creation rate over the last year. License: Apache-2.0. No formal public roadmap - direction is visible via GitHub milestones (v0.165.0 is the current one). (releases, contributors, milestone 370, accessed 2026-07-28)
Template system (the v0.146 era)
The headline architectural change of the period is the fully refreshed template system in v0.146.0 (2025-04-10): one unified lookup path for layouts, base templates, shortcodes, and render hooks that walks the template tree matching kind, layout, type, output format, media type, language, and variants against the full page path. The modern structure drops layouts/_default/ (standard templates live directly under layouts/), renames special directories to _partials/, _shortcodes/, _markup/ (placeable at any level), requires home.html instead of index.html, uses baseof.list.html-style base names, and adds an all.html catch-all. Backward compatibility for the old structure is best-effort, not guaranteed - the release notes explicitly say to test before going live, and v0.146 warns about and skips non-hook templates placed under _markup. (v0.146.0, new template system overview, accessed 2026-07-28)
On top of that: try error handling (v0.141.0), partial decorators with the inner keyword plus reflect.IsPage/IsSite/IsResource/IsImageResource (v0.154.0), and templates.Defer replacing resources.PostProcess (deprecated v0.164.0).
Markdown & render hooks
The documented render-hook set as of v0.164.0 is: render-link, render-image, render-heading, render-passthrough, render-codeblock, render-blockquote, and render-table, recommended at layouts/_markup/ (legacy layouts/_default/_markup/ still works). The passthrough hook (v0.132.0) with its -block/-inline variants is the documented pipeline for server-side mathematics together with the Goldmark passthrough extension. In v0.148.0 the boolean enableDefault config for link/image hooks was deprecated in favor of the useEmbedded enum (auto/never/always/fallback). v0.160.0 added .Position/.Ordinal to all hooks. (render hooks introduction, passthrough, markup config, accessed 2026-07-28)
Config & content model
Hugo’s config surface churned significantly: a new YAML parser (v0.152.0 - unquoted yes/no/on/off are now strings, anchors/aliases supported), the multidimensional content model via sites.matrix (v0.153.0 - languages × versions × roles, deprecating lang on mounts/segments and includeFiles/excludeFiles), language key renames (languageCode→locale, languageName→label, languageDirection→direction, v0.158.0), removal of paginate/paginatePath (v0.156.0, use pagination.pagerSize), and module version queries on imports (v0.150.0, ranges v0.155.0).
Asset pipelines
JavaScript: js.Batch (v0.140.0, grouped bundles with global code splitting), js.Build drop option (v0.144.0), es2024 target. CSS: native css.Build (v0.158.0) with hugo:vars custom-property injection (v0.160.0, nested in v0.161.0). Sass: libsass deprecated in favor of dartsass (v0.153.0) - extended builds still ship libsass; dartsass must be installed separately. Node tooling: since v0.161.0, PostCSS/Babel/TailwindCSS run with Node’s --permission flag, Node ≥ 22 is required, and the standalone Tailwind executable is no longer supported (must be a Node package).
Imaging
images.QR and images.Mask (v0.141.0), WASM-based WebP with animation support (v0.153.0), AVIF encode/decode (v0.162.0), and per-format quality config with a content-aware hint option (v0.163.0, deprecating global imaging.quality/imaging.compression).
Security hardening
v0.161.0 tightened default security.http.urls; v0.162.0 denies text/html content files by default (new security.allowContent policy), rejects symlinked resources.Get entries, and re-checks URL allowlists on redirect hops.
Findings
Latest release: Hugo v0.164.0, published 2026-07-06. Adds Chroma dark/light style pairs,
encoding.HexEncode/HexDecode,crypto.Hash, Pandoc citation support, sub-paths in layouts passed to.Render, and fixes a performance regression from v0.128.0. Deprecatesresources.PostProcessin favor oftemplates.Defer. No newer release exists as of today (verified against the releases page). (v0.164.0, accessed 2026-07-28)v0.146.0 (2025-04-10) [STALE] rewrote the template system. Unified lookup over the full page path; modern structure: no
_default/,_partials//_shortcodes//_markup/at any level,home.html,all.htmlcatch-all,baseof.list.html; newtemplates.Currentandtime.In. Back-compat is best-effort - “make sure you test your site before going live”; some real-world breakages reported; non-hook templates under_markupare warned about and skipped. (v0.146.0, overview, accessed 2026-07-28)_internaltemplates: doc-removed, not runtime-removed. v0.146 removed the concept from documentation (use{{ partial "opengraph.html" . }}etc.), but old{{ template "_internal/..." }}calls still execute; formal deprecation of the construct is an open v0.165.0 milestone item (#13553). Corrected in verification - the fan-out’s “removed in v0.146” claim was overstated. (overview, issue #13553, accessed 2026-07-28)Current render-hook set:
render-link,render-image,render-heading,render-passthrough,render-codeblock,render-blockquote,render-table. Recommended locationlayouts/_markup/;layouts/_default/_markup/still works via back-compat. (render hooks, accessed 2026-07-28)render-passthrougharrived in v0.132.0 (2024-08-12) withrender-passthrough-block.html/render-passthrough-inline.htmlvariants; paired with the Goldmark passthrough extension configured undermarkup.goldmark.extensions.passthrough(block delimiters e.g.\[...\],$$...$$; inline\(...\)). (v0.132.0, passthrough, mathematics, accessed 2026-07-28)enableDefault→useEmbedded(v0.148.0). Link/image embedded render hooks are now controlled by an enum:auto(default),never,always,fallback.enableDefaultis deprecated. (markup config, v0.148.0, accessed 2026-07-28).Page.Storereplaced.Page.Scratchin v0.138.0 - Scratch was aliased to Store and is formally deprecated (“Deprecated in v0.138.0. Use the Page.Store method instead.”).site.Store,hugo.Store, andShortcode.Storefollowed in v0.139.0 (2024-11-18). Corrected in verification - earlier drafts attributed page.Store to v0.139.0/v0.146.0. (page.Scratch, site.Store, v0.138.0, v0.139.0, accessed 2026-07-28)trytemplate error handling: v0.141.0 (2025-01-16);resources.GetRemotenow uses it internally. Same release:images.Mask,images.QR,alignxforimages.Text; Twitter shortcode deprecated in favor of X. (v0.141.0, accessed 2026-07-28)Partial decorators and type reflection: v0.154.0 (2025-12-31) - the
innerkeyword lets partials reverse caller/callee roles;reflect.IsPage,reflect.IsSite,reflect.IsResource,reflect.IsImageResourceadded. (v0.154.0, accessed 2026-07-28)v0.156.0 (2026-02-18) removed the long-deprecated API surface (verified against release notes):
data.GetCSV/GetJSON,crypto.FNV32a,resources.Babel/PostCSS/ToCSS,.Paginator.PageSize, config keyspaginate/paginatePath,.Site.Author/.Site.Authors/.Site.Social,.Site.LastChange,.Site.IsMultiLingual,.Sites.First, and thegetjson/getcsvfile caches. Newly deprecated:.Site.AllPages,.Site.BuildDrafts,.Site.Languages,.Site.Data,.Page.Sites,.Site.Sites. (v0.156.0, accessed 2026-07-28)paginateconfig key: deprecated v0.128.0, removed v0.156.0 - use[pagination] pagerSize. (v0.156.0, accessed 2026-07-28)Language config keys deprecated in v0.158.0 (2026-03-16):
languageCode→locale,languageName→label,languageDirection→direction, with matching.Site/.Languagemethod deprecations. Same release added nativecss.Buildandstrings.ReplacePairs. (v0.158.0, accessed 2026-07-28)Front matter deprecations:
_build→build(v0.145.0);kind,lang,pathdeprecated (v0.144.0). Permalink tokens:filename/:slugorfilenamedeprecated in favor of:contentbasename/:slugorcontentbasename(v0.144.0);:sectionslug/:sectionslugsadded (v0.149.0). (v0.145.0, v0.144.0, v0.149.0, accessed 2026-07-28)Top-level
googleAnalyticskey /.Site.GoogleAnalytics: deprecated v0.120.0, announced for removal ~v0.134.0; current docs only documentservices.googleAnalytics.idaccessed as.Site.Config.Services.GoogleAnalytics.ID- the old key is gone in v0.164. [UNVERIFIED: the exact removal release; v0.134–0.136 notes don’t call it out, but the current-state docs are unambiguous.] (services config, discourse, accessed 2026-07-28)Top-level
[author]config deprecated v0.120.0 [STALE] - useparams.author.name/params.author.email. (v0.120.0, accessed 2026-07-28)YAML parser switch in v0.152.0 (2025-10-21) is a quiet breaking change: unquoted
yes/no/on/offnow parse as strings, not booleans; YAML anchors/aliases now supported. (v0.152.0, accessed 2026-07-28)Multidimensional content model: v0.153.0 (2025-12-19) -
sites.matrixfor languages × versions × roles; deprecateslangon mounts/segments and mountincludeFiles/excludeFiles(newfilesfilter); deprecates libsass in favor of dartsass; WASM WebP encode/decode with animation. (v0.153.0, accessed 2026-07-28)Aliases beginning with
/are site-relative since v0.155.0 (2026-01-28), not server-relative - breaking for multidimensional sites. Same release: version-range queries, XMP/IPTC metadata. (v0.155.0, accessed 2026-07-28)Modules matured:
versionquery option on imports (v0.150.0), version ranges (v0.155.0), andPage.GitInfoworks for module-mounted content (v0.157.0). Meanwhile the official Quick Start still teaches git submodules for themes - submodules remain the documented beginner path; Modules are the component-based advanced path. (v0.150.0, v0.157.0, quick start, accessed 2026-07-28)JS pipeline:
js.Batchwith global code splitting (v0.140.0 [STALE]), esbuildplatformoption and es2024 target,dropoption forjs.Build(v0.144.0 [STALE]). (v0.140.0, v0.144.0, accessed 2026-07-28)CSS pipeline: native
css.Build(v0.158.0),hugo:varscustom-property injection via@import "hugo:vars"(v0.160.0), nested vars incss.Build/css.Sass(v0.161.0). (v0.158.0, v0.160.0, v0.161.0, accessed 2026-07-28)Node tooling constraints since v0.161.0 (2026-04-28): PostCSS/Babel/TailwindCSS run under Node’s
--permissionflag; Node ≥ 22 required; the standalone Tailwind CSS executable is no longer supported - Tailwind must be installed as a Node package. (v0.161.0, accessed 2026-07-28)Imaging: WASM WebP + animated WebP (v0.153.0), partial AVIF/HEIF/HEIC metadata (v0.157.0), full AVIF encode/decode (v0.162.0, 2026-05-26), per-format quality + content-aware
hint(v0.163.0, 2026-06-08) with globalimaging.quality/imaging.compressiondeprecated;resources/jsconfigbaseUrlsupport removed (v0.163.0). (v0.162.0, v0.163.0, accessed 2026-07-28)Security defaults tightened: v0.161.0 restricted default
security.http.urls; v0.162.0 deniestext/htmlcontent files unless allowed viasecurity.allowContent, rejects symlinkedresources.Getentries, and re-validates URL allowlists across redirects. (v0.161.0, v0.162.0, accessed 2026-07-28)Server-side math is a first-class pipeline: Goldmark passthrough extension +
render-passthroughhook +transform.ToMath(KaTeX;mhchemextension since v0.144.0). (mathematics, v0.144.0, accessed 2026-07-28)Chroma dark/light style pairs (v0.164.0) - syntax highlighting can now ship paired light/dark themes, directly relevant to sites with a dark-mode toggle. (v0.164.0, accessed 2026-07-28)
Distribution notes:
hugo deployonly ships inwithdeployarchives (or-tags withdeploy) since v0.137.0 [STALE]; extended builds ship libsass (deprecated), so dartsass must be installed separately and selected withtranspiler = 'dartsass'. (hugo deploy, css.Sass, accessed 2026-07-28)v0.165.0 horizon (open milestone): Goldmark v2 beta upgrade,
css.ChromaStyles,.Rendertaking additional data, formal_internaldeprecation, embedded render-hook error handling, Goldmark CJK extension, slug support for sections/taxonomies, and a possible change to the defaultbaseUrl. (milestone 370, accessed 2026-07-28)Content adapters (
_content.gotmpl, v0.126.0 [STALE]) generate pages from local/remote data and can now create home pages (v0.148.0) - the current best practice for data-driven sections, replacing external pre-build scripts. (v0.126.0, v0.148.0, accessed 2026-07-28)Archetypes current behavior:
hugo new contentwith--kind; lookup order project → theme → module; leaf-bundle archetypes require at least one file per subdirectory. (archetypes, accessed 2026-07-28)
Comparison vs. current repo (PKB-theme)
Grounding: PKB-theme is itself a Hugo theme (theme.toml min_version = "0.136.0"). The working tree is mid-migration to v0.148+ patterns. Status of each area against the findings above:
| Area | Repo state (file) | Latest Hugo | Gap / action |
|---|---|---|---|
| Version floor | theme.toml min 0.136.0; README (working tree) claims “v0.148+”; CI pins 0.123.7 (test.yml) and 0.128.0 (hugo.yml) | v0.164.0; useEmbedded needs ≥0.148.0 (F6) | CI pins are below the theme’s own min_version - bump CI to ≥0.148.0 (or latest); align theme.toml min_version with the README’s 0.148+ claim |
| CI health | test.yml contains an unresolved git merge conflict (<<<<<<< HEAD / >>>>>>> gh-pages) | - | Resolve before any CI run is meaningful |
| Render-hook config | Working tree: useEmbedded = 'fallback' in hugo.toml + new markup.toml with footnote/passthrough | Exactly the v0.148.0 enum form (F6); passthrough config matches docs (F5) | Correct - complete and commit the migration |
| Render hooks | Has render-link, render-passthrough, render-codeblock-mermaid, render-codeblock-goat - plus non-standard render-inline.html and render-paragraph.html | Documented set: link/image/heading/passthrough/codeblock/blockquote/table (F4); v0.146+ warns/skips unknown templates under _markup (F2) | Audit render-inline/render-paragraph - almost certainly dead code now that the passthrough hook handles math; remove or rename |
| Scratch | .Page.Scratch.Get/Set in cite.html (4 calls) and sidenote.html (2 calls) | .Page.Store; Scratch deprecated v0.138.0 (F7) | Mechanical rename to .Page.Store |
| Imaging config | Global quality = 85 under [imaging] (hugo.toml:73) | Global imaging.quality deprecated v0.163.0 (F23) | Move to [imaging.webp] / [imaging.avif] per-format blocks |
| Language config | languageCode = 'en-us' (hugo.toml:2) | languageCode → locale deprecated v0.158.0 (F12) | Rename key |
| Layout structure | Legacy: layouts/_default/, layouts/partials/, layouts/shortcodes/, layouts/_default/_markup/ | Modern v0.146 structure (F2) | Works today via best-effort back-compat; migrate deliberately with testing - the legacy structure is frozen, not evolving |
_internal templates | Not used ✓ | Construct slated for formal deprecation v0.165 (F3) | Nothing to do - keep using partials |
| Analytics config | [services.googleAnalytics] present; no .Site.GoogleAnalytics usage ✓ | Old key removed (F14) | Already modern |
| QR codes | qr.html calls external api.qrserver.com; page-qr.html uses native images.QR | images.QR native since v0.141.0 (F8) | Migrate qr.html to images.QR; drop the external dependency |
| Math rendering | KaTeX loaded client-side (head.html) and MathJax via math.html (deleted) - two renderers referenced | Server-side pipeline: passthrough + transform.ToMath (F25) | Pick one renderer; consider server-side KaTeX to match the new passthrough hook |
| RSS link | Hard-coded {{ .Site.BaseURL }}index.xml in footer.html | .OutputFormats.Get "RSS" | Minor robustness fix |
| SEO meta | Hand-rolled Open Graph/Twitter Cards/JSON-LD partials | Hugo’s embedded opengraph.html/twitter_cards.html/schema.html now usable as plain partials (F3) | Optional simplification - current hand-rolled versions are more complete; no urgency |
| Sitemap | scripts/generate-sitemap.js overwrites public/sitemap.xml post-build | Native [sitemap] output (already configured) | Evaluate whether the Node script is still needed |
| Menu entries | .URL on menu entries in menu.html:23 | .PageRef is the documented modern accessor | [UNVERIFIED: formal deprecation status] - low-priority cleanup |
| Content security | All content is Markdown | text/html content denied by default since v0.162.0 (F24) | No action; note for users who add .html content |
| Syntax highlighting | Theme has a dark-mode toggle | Chroma dark/light style pairs (F26) | Opportunity: paired Chroma styles per color scheme |
Recommendations
Prioritized; finding references in parentheses.
P0 - build health & correctness
- Align the version floor everywhere (F6, F12). Bump CI to a single recent Hugo (≥0.148.0, ideally 0.164.x), set
theme.tomlmin_version = "0.148.0"to match the README’s claim, and resolve the merge conflict in.github/workflows/test.yml. CI currently tests a version the theme forbids. - Complete the in-progress
useEmbedded = 'fallback'migration and commit it (F6) - verified correct; the split intoconfig/_default/markup.tomlfor footnote/passthrough matches how Hugo merges theme vs. site markup config. - Replace
.Page.Scratchwith.Page.Storeincite.htmlandsidenote.html(F7). Scratch has been formally deprecated since v0.138.0; the rename is mechanical and behavior-preserving. - Migrate
imaging.quality = 85to per-format blocks (F23) before requiring ≥0.163.0:[imaging.webp] quality = 85,[imaging.avif] quality = 85. - Rename
languageCode→locale(F12) in root and exampleSite configs.
P1 - modernization
- Remove or rename the non-standard render hooks
render-inline.htmlandrender-paragraph.html(F2, F4) - they are not in Hugo’s documented hook set; v0.146+ warns about and skips unknown templates under_markup. The passthrough hook now covers their math use case. - Migrate the QR shortcode to native
images.QR(F8) and drop the externalapi.qrserver.comdependency. - Resolve the KaTeX-vs-MathJax duplication (F25): keep one client-side renderer, or move to server-side
transform.ToMath(KaTeX +mhchem) fed by the passthrough hook the theme just added. - Plan a deliberate migration to the v0.146 layout structure (F2):
layouts/_markup/,_partials/,_shortcodes/,home.html. Not urgent (back-compat holds), but do it as one tested changeset rather than drifting. - Replace the hard-coded footer RSS URL with
.OutputFormats.Get "RSS".
P2 - watch items
- Do not adopt
{{ template "_internal/..." }}anywhere - formal deprecation lands in v0.165 (F3). - Test against Goldmark v2 when v0.165 ships (F28) - the Markdown parser upgrade is the next likely breaking event for render hooks.
- If Tailwind/PostCSS is ever added: Node ≥ 22 and package-installed CLI are mandatory since v0.161.0 (F22).
- Consider Chroma dark/light style pairs (F26) for code blocks to match the theme’s color-scheme toggle.
Coverage disclosure
- Searched: GitHub release notes v0.120.0–v0.164.0 (primary), v0.165.0 milestone #370, gohugo.io docs (new template system overview, markup configuration, render hooks introduction/passthrough, mathematics, services, outputs/output-formats, quick start, archetypes,
page.Scratch/site.Storemethod pages, hugo deploy, css.Sass), Hugo Discourse (GoogleAnalytics deprecation, content adapters), GitHub API (contributors/issues/commits for health signals), and a full local inventory of the PKB-theme repo (layouts, configs, CI, working-tree diff). - Not covered: arXiv (skipped deliberately - a static site generator has no academic-literature angle; no relevant papers exist to survey). Community theme-ecosystem comparisons (Docsy/Blowfish/etc. were not benchmarked). Build-performance benchmarks. Non-English sources. Hugo’s own documentation site internals beyond the pages listed.
- Dropped in verification: “fragments” as a standalone new feature - unverifiable beyond the existing
Page.FragmentsToC method; no claim made. The fan-out’s “_internalremoved in v0.146” and “page.Storein v0.139.0/v0.146.0” claims were corrected (see F3, F7). - Limitations: exact
googleAnalyticsremoval release unverifiable from release notes (current-state docs confirm removal - F14). The v0.139.0 date (2024-11-18) was pinned contextually against neighboring releases. Web research was compiled partly from agent transcripts after an early termination; all load-bearing claims it produced were re-verified in the adversarial pass. This report is a snapshot of a fast-moving project - re-run intrackmode in ~3 months.
Source list
- https://github.com/gohugoio/hugo/releases (v0.120.0 – v0.164.0 tag pages) - accessed 2026-07-28
- https://github.com/gohugoio/hugo/milestone/370 - accessed 2026-07-28
- https://github.com/gohugoio/hugo/issues/13553 - accessed 2026-07-28
- https://gohugo.io/templates/new-templatesystem-overview/ - accessed 2026-07-28
- https://gohugo.io/render-hooks/introduction/ - accessed 2026-07-28
- https://gohugo.io/render-hooks/passthrough/ - accessed 2026-07-28
- https://gohugo.io/configuration/markup/ - accessed 2026-07-28
- https://gohugo.io/configuration/services/ - accessed 2026-07-28
- https://gohugo.io/configuration/output-formats/ - accessed 2026-07-28
- https://gohugo.io/configuration/outputs/ - accessed 2026-07-28
- https://gohugo.io/configuration/security/ - accessed 2026-07-28
- https://gohugo.io/content-management/mathematics/ - accessed 2026-07-28
- https://gohugo.io/content-management/archetypes/ - accessed 2026-07-28
- https://gohugo.io/methods/page/scratch/ - accessed 2026-07-28
- https://gohugo.io/methods/site/store/ - accessed 2026-07-28
- https://gohugo.io/getting-started/quick-start/ - accessed 2026-07-28
- https://gohugo.io/hosting-and-deployment/hugo-deploy/ - accessed 2026-07-28
- https://gohugo.io/functions/css/sass/ - accessed 2026-07-28
- https://discourse.gohugo.io/t/site-googleanalytics-was-deprecated-in-hugo-v0-120-0-and-will-be-removed-in-hugo-0-134-0/51395 - accessed 2026-07-28
- https://discourse.gohugo.io/t/content-adapters-examples-and-performance/49830 - accessed 2026-07-28
- https://api.github.com/repos/gohugoio/hugo/contributors - accessed 2026-07-28
Related notes: Creating Posts with Hugo, Development Tips, Hugo SEO Implementation Guide. See also the glossary for shared terminology.
