What’s New

Hugo

Developer Tools

Static site generator in Go, with a large template and content pipeline.

Latest v0.164.0 · by HugoWebsitegohugoio/hugo

Changelog

v0.164.0

Notable new features in this release are:

Notes
  • tpl/resources: Deprecate resources.PostProcess in favour of templates.Defer 29ed9325 @bep #15086
Changes
  • all: Rewrite deprecated constructs in tests 5a5f4a54 @bep
  • tpl/tplimpl: Support sub paths in layouts passed to .Render d83ce27a @bep #15056
  • Add markup.rst.syntaxHighlight option c6acc246 @bep #5349
  • tpl/resources: Deprecate resources.PostProcess in favour of templates.Defer 29ed9325 @bep #15086
  • tpl/collections: Include key in IsSet unsupported-type warning 671897ae @bejaratommy #11794
  • create: Keep new content placeholders buildable 499794d1 @sjh9714 #15078
  • hugio: Speedup hasBytesWriter 65c82178 @bep
  • tpl/crypto: Add crypto.Hash dfb35dcd @bep #15072
  • Add encoding.HexDecode/Encode a5ec5423 @bep #15068 #15060
  • tpl/tplimpl: Make template name lookup case-insensitive e46d37a9 @jmooring #15057
  • hugolib: Return error from .Render when template not found fe067352 @jmooring #15052
  • markup/pandoc: Add citation support 128fb17c @jmooring #15062
Dependency Updates
  • build(deps): bump github.com/JohannesKaufmann/html-to-markdown/v2 921db7b5 @dependabot[bot]
  • build(deps): bump golang.org/x/tools from 0.45.0 to 0.47.0 786ce71e @dependabot[bot]
  • build(deps): bump golang.org/x/image from 0.42.0 to 0.43.0 5ad28461 @dependabot[bot]
  • build(deps): bump golang.org/x/net from 0.55.0 to 0.56.0 36ad9f58 @dependabot[bot]
  • build(deps): bump github.com/pelletier/go-toml/v2 from 2.4.2 to 2.4.3 7c0a0bc9 @dependabot[bot]
  • build(deps): bump github.com/getkin/kin-openapi from 0.139.0 to 0.140.0 a879ebfa @dependabot[bot]
  • build(deps): bump golang.org/x/mod from 0.36.0 to 0.37.0 332d5ec8 @dependabot[bot]
  • build(deps): bump github.com/pelletier/go-toml/v2 from 2.3.1 to 2.4.2 212cc11a @dependabot[bot]
  • deps: Upgrade github.com/evanw/esbuild v0.28.0 => v0.28.1 884439b9 @bep #15033
  • deps: Add Chroma dark/light mode support 790a8aa4 @bep #15017

v0.163.3

What's Changed
  • markup/highlight: Escape lang in default code block rendering ce1a7e0b @bep thanks to @k0ngj1 for reporting this issue.
  • parser/pageparser: Preserve non-ASCII whitespace after e.g. summary divider 70a9068a @bep
  • resources: Support babel/postcss config variants 9d66d513 @jmooring #15039 #15040 #15043
  • hugolib: Fix page/section name collision regression f0133466 @jmooring #15046

v0.163.2

What's Changed
  • Continue resolving on ERR_ACCESS_DENIED in Node's resolver 134674f0 @bep #15041
  • markup: Standardize behavior when external converters are missing 147f605f @jmooring #14222

v0.163.1

The majority of the fixes in this release are security related (including the upstream fix in 93c8c7d3 (golang.org/x/image)). Thanks to @vnth4nhnt for finding the issues fixed in a00b5c72 and cf9c8f93 (I will do the CVE work on this later). There has been a uptick in security reports lately, which doesn't mean that Hugo has gotten less secure, this is mostly the work of the new and powerful AI tools using Hugo's restrictive security model as their baseline. Just take a look at Go's recent security issue list to see a demonstration of this.

What's Changed
  • build(deps): bump golang.org/x/image from 0.41.0 to 0.42.0 93c8c7d3 @dependabot[bot]
  • Fix multi --renderSegments merge behavior 95e5e9f4 @bep #15024
  • security: Normalize integer IPv4 host encodings in http.urls check a00b5c72 @bep
  • Drop symlinks in os.ReadDir, os.ReadFile, os.Stat and os.FileExists cf9c8f93 @bep #15019
  • commands: Fix convert command 2602796c @jmooring #15012

v0.163.0

The main topic in this release is improvements to the AVIF image handling that we introduced in v0.162.0. See the docs for details, but:

  • We have turned down the default quality for AVIF to 60. Turns out, JPEG/WebP with quality 75 is comparable to AVIF with quality 60. You can now also set quality per image format in your project config (and also per image processed if needed).
  • We have added a hint to the AVIF with the same values as for WEBP. For lossy compression, the photo/picture hints (and the default) encodes with YUV420 chroma subsampling instead of YUV444, keeping 444 for text/icon/drawing. This greatly reduces the memory needed to encode these images.
Improvements
  • resources/jsconfig: Remove deprecated baseUrl setting ff2903a9 @bep #14991 #14996
  • all: Adjust tests for deprecated link and image render hook settings ca68936d @jmooring
  • all: Run go fix ./... 781fabf4 @bep
  • pagesfromdata: Use relative path for content adapter template metrics 1d018ef8 @anupamojha-eng #14999
  • ci: Re-add macos-latest to the test matrix 121bc6ce @bep
  • images: Deprecate Imaging.Compression and move it down to webp and avif configs cf18b827 @bep #14998
  • Only support the latest Go version 98ad9b3c @bep #14997
  • page: Add IsBranch and deprecate IsNode b89e7fe6 @bep #11574
  • images: Force cache invalidation for AVIF target e8fefc83 @bep #14990
  • images: Add a per-format AVIF hint setting a043d3ec @bep #14992
  • images: Make AVIF chroma subsampling content-aware via the hint 341f575d @bep #14987
  • Cap AVIF lossy quality at 99 248241b6 @bep #14981
  • config: Deprecate the glogal imaging quality setting 4e47d95d @bep #14979
  • images: Make 60 the default quality for AVIF 03b4b542 @bep #14979
  • livereload: Disconnect from websocket server on pageswap 79be0532 @bep #14983
  • tpl/tplimpl/embedded: Prevent leading newline in sitemap template 0f440460 @bep #14977
  • images: Recover from memory alloc errors in WASM image processors 4e17421e @bep #14985
  • images: Add quality setting per image format b01ecd4c @bep #14957
  • misc: Remove duplicate words in comments 45c00b7c @jmooring #14936 #14950 #14965
  • Add some PNG to AVIF golden test cases 28d882ab @bep
Dependency Updates
  • build(deps): bump github.com/bits-and-blooms/bitset 0d29fc81 @dependabot[bot]
  • build(deps): bump github.com/tetratelabs/wazero bb57404f @dependabot[bot]
  • build(deps): bump github.com/rogpeppe/go-internal from 1.14.1 to 1.15.0 7d1b1fb3 @dependabot[bot]
  • build(deps): bump github.com/getkin/kin-openapi from 0.138.0 to 0.139.0 77a11470 @dependabot[bot]

v0.162.1

What's Changed
  • modules/npm: Fix false stale warning after npm pack 59f35cd9 @jmooring #14959
  • Revert "tpl/collections: Make dict return nil when no values are provided" c2709750 @bep #14958
  • tpl/time: Fix locale-specific month abbreviations ea8b48af @jmooring #14948

v0.162.0

The notable new feature in this release is support for AVIF images (both encoder and decoder). There's a demo site set up that demonstrates the difference between HDR AVIF and SDR JPEG images. Note that that demo is only really interesting if viewed on an HDR capable screen (e.g. Apple Retina).

Security fixes

There are some notable security fixes in this release.

Security fixes in Go

This release upgrades from Go 1.26.1 to 126.3, which brings a set of security fixes. Some relevant for Hugo are:

  • XSS in html/template (CVE-2026-39826 & CVE-2026-39823): Two separate vulnerabilities where escaper bypasses in html/template could lead to Cross-Site Scripting (XSS).
  • html/template: Fixes an issue where JS template literal contexts were incorrectly tracked across template branches, which could lead to improper content escaping.
Security fixes and hardening in Hugo

The following changes either fix a concrete issue or reduce the default attack surface of hugo builds.

  • Disallow text/html content files by default (e41a064). A new security.allowContent policy gates which content media types may be used for pages under /content. text/html is denied by default; sites that rely on hand-authored or adapter-emitted HTML content can opt back in with security.allowContent = ['.*'].
  • Re-check security.http.urls on every redirect hop in resources.GetRemote (86fbb0f).
  • Reject symlinked entries in resources.Get (f8b5fa0).

We will update this section later with links to CVEs where applicable.

All changes
  • hugolib: Fix Page.GitInfo for modules with go.mod in a repo subdirectory df542191 @bep #14942
  • Fix typo in CONTRIBUTING.md 4bc7caea @bep
  • resources: Fix the :counter placeholder 5d51b82a @jmooring #14921
  • commands: Fix import from Jekyll 81d77620 @jmooring #14795 #14906
  • Fix prevention of direct symlink reads in resources.Get f8b5fa09 @bep
  • commands: Fix github-dark chromastyles 88d838a9 @xndvaz #14831
  • Disallow HTML content by default e41a0644 @bep
  • Add image processing support for AVIF 90d9f812 @bep #7837
  • config: Preserve intentionally empty maps 80e60847 @jmooring #14944
  • hugolib: Merge existing hugo_stats.json when renderSegments is set aeb9a5cc @bep #14939
  • all: Replace RWMutex struct caches with ConcurrentMap c4bbc280 @bep
  • tpl/tplimpl: Consolidate and improve embedded template integration tests d8c70218 @jmooring #14932
  • parser: Drop empty sub maps from hugo config output ee4f1acd @bep #14855
  • markup/highlight: Allow overriding type and code via options b6133657 @bep #11872
  • Update AI assistance disclosure requirements d2c821b5 @bep
  • hugolib: Use AllTranslated in IsTranslated 4ed7600f @bep
  • tpl: Simplify sitemap template cbe4339a @bep #14912
  • tpl: Use AllTranslations in sitemap template 6475d308 @bep #14912 #14917
  • tpl/collections: Make dict return nil when no values are provided 67aede43 @bep
  • Sync Go template package to 1.26.3 87f194b2 @bep #14897
  • Upgrade to Go 1.26.3 d81e3c29 @bep #14897
  • ci: Check embedded template formatting with gotmplfmt 7c65a4db @bep
  • tpl: Run gotmplfmt -w . d31a9275 @bep
  • markup/goldmark/codeblocks: Always split Chroma options into .Options c36608c5 @jmooring #14909
  • hugolib: Allow empty params front matter 2f361a8e @xndvaz #14886
  • common/hmaps: Merge slice-valued module config into site config 55592633 @jmooring #13869
  • tpl: Use GetMatch for both local and global image resources 656fc040 @bep #14062
  • Revert "markup/tableofcontents: Skip empty TOC levels" a20cb5b1 @bep #14898
  • tpl/templates: Reject Defer inside partialCached 4d775cbe @bep #13492
  • common/hexec: Make NODE_PATH a fallback for ESM bare imports ae7bf74b @bep #13987
  • config: Allow repeating the root key in /config files ba5d8126 @bep #12899 #14882
  • Revise test naming guidelines in AGENTS.md be4a0df3 @bep
  • Update AGENTS.md e4cf565c @bep
  • js: Return error for missing batch imports 9e649533 @xndvaz #13737
  • resources/images: Keep smart crop target size f0cfc28c @xndvaz #13688
  • testing: Use synctest where relevant 16e854a4 @bep
  • security: Validate redirects against security.http.urls 86fbb0f7 @bep #14871
  • markup/tableofcontents: Skip empty TOC levels 7d4af7a1 @xndvaz #7128
  • Fall back to hugo.buildDate in hugo.BuildDate() in non-vcs builds 28147cb0 @bep #14862
  • css: Make css.Build's file-loader URLs absolute to web context root e51e761d @bep #14849
  • hugolib: Don't warn about lang/kind/path coming from cascade.params 70112392 @bep #14848
  • markup/goldmark: Unwrap inner HTML for plain code blocks 694906f6 @cyphercodes #14820
  • tpl/tplimpl: Extend page image lookup to include global resources d27b9c06 @ogulcanaydogan #14062
  • security: Allow hostnames starting with digits in default http.urls 62cef367 @bep #14837
  • commands: Improve description of command flags ff22c62a @jmooring #14817
  • build(deps): bump golang.org/x/net from 0.54.0 to 0.55.0 4f444c81 @dependabot[bot]
  • build(deps): bump golang.org/x/image from 0.40.0 to 0.41.0 fe6c7265 @dependabot[bot]
  • build(deps): bump github.com/getkin/kin-openapi from 0.137.0 to 0.138.0 6a2a0380 @dependabot[bot]
  • build(deps): bump github.com/JohannesKaufmann/html-to-markdown/v2 cf1de598 @dependabot[bot]
  • build(deps): bump golang.org/x/image from 0.39.0 to 0.40.0 97f990cc @dependabot[bot]
  • build(deps): bump golang.org/x/tools from 0.44.0 to 0.45.0 b99634e2 @dependabot[bot]
  • build(deps): bump github.com/aws/aws-sdk-go-v2/service/s3 fdd977e9 @dependabot[bot]
  • build(deps): bump github.com/pelletier/go-toml/v2 from 2.3.0 to 2.3.1 123018de @dependabot[bot]
  • deps: Upgrade to Chroma v2.24.1 b88fa8cc @bep #14839

v0.161.1

What's Changed
  • resources: Honor Retry-After header in resources.GetRemote retries c4eba928 @bep #14828
  • warpc: Move to parson.c in https://github.com/kgabis/parson 8b40a96b @bep #14823
  • config/security: Add AllowChildProcess to security.node.permissions d65af84d @bep #14824
  • config/security: Restrict default http.urls "@" deny to userinfo 454450a6 @bep #14825

v0.161.0

This release contains two security hardening fixes:

  • We now run the Node tools PostCSS, Babel and TailwindCSS, by default, with the --permission flag with the permissions defined in security.node.permissions. This means that you need Node >= 22 installed and that css.TailwindCSS now requires that the Tailwind CSS CLI must be installed as a Node.js package. The standalone executable is no longer supported
  • We have made the defaults in security.http.urls more restrictive.

But there are some notable new features, as well:

Nested vars support in css.Build and css.Sass

A practical example in css.Build would be to have something like this in hugo.toml:

[params.style]
    primary    = "#000000"
    background = "#ffffff"
    [params.style.dark]
        primary    = "#ffffff"
        background = "#000000"

And in the stylesheet:

@import "hugo:vars";
@import "hugo:vars/dark" (prefers-color-scheme: dark);

:root {
  color-scheme: light dark;
}
Slice-based permalinks config

The permalinks configuration is now much more flexible (the old setup still works). It uses the same target matchers as in the cascade config, meaning you can now do:

permalinks:
  - target:
      kind: page
      path: "/books/**"
    pattern: /books/:year/:slug/
  - target:
      kind: section
      path: "/{books,books/**}"
    pattern: /libros/:sections[1:]
  - target:
      kind: page
    pattern: /other/:slug/

The above example isn't great, but it at least shows the gist of it.

A more flexible scheme for identifiers in filenames

What we had before was e.g. content/mypost.en.md which told Hugo that the content files was in English. With the new setup you could also name the file content/mypost._language_en_.md. This alone doesn't sound very useful, but this allows you to use more prefixes:

PrefixDescriptionRelevant for
language_LanguageContent and layout files.
role_RoleContent and layout files.
version_VersionContent and layout files.
outputformat_Output formatLayout files.
mediatype_Media typeLayout files.
kind_Page kindLayout files.
layout_LayoutLayout files.
All Changes
  • langs/i18n: Fix translation lookup when using language variants 72b85d5f @jmooring #7982
  • create: Fix non-deterministic conflict detection in hugo new content 6436deb3 @jmooring #12602 #12786 #14112 #14769
  • commands: Fix environment isolation for configuration settings 1eea9fba @jmooring #14763
  • Fix filename dimension identifiers (role_X, version_X) to replace mount config 8d6145f3 @bep #14756
  • Fix it so we never auto-fallback to page resources in other roles/versions 97477242 @bep #14749 #14752
  • css: Support nested hugo:vars/ imports 7622dd86 @bep #14705
  • github: Update GitHub actions versions 0814059b @bep #14810
  • hugolib: Do not render aliases if the page is not rendered 8920d56e @jmooring #14807
  • langs/i18n: Improve default content language fallback 633cc772 @jmooring #14243
  • helpers: Remove unused code 4c40c6d5 @bep
  • common/constants: Remove unused consts d2594db6 @bep
  • common/paths: Remove unused code ab2de51e @bep
  • tests: Update Ruby setup action to v1.305.0 75f61832 @jmooring
  • langs: Use Language.Locale as primary localization key 1b7495bc @jmooring #9109
  • config/security: Add "! " negation to Whitelist, harden default http.urls 79f030be @bep #14792
  • Harden Node tool execution with --permission flag a54c398b @bep #7287
  • tpl/collections: Honor the Eqer interface in where comparisons f5fce935 @bep #14777
  • modules: Ignore non-require blocks in go.mod rewrite 4169c1f7 @bep #14783
  • Replace the concurrent map with an identical upstream version 7574e35b @bep
  • Add slice-based permalinks config with PageMatcher target 017a7cd6 @bep #14744
  • commands: Add missing import e3413d92 @bep
  • Revert "common/hugo: Deprecate extended and extended_withdeploy editions" b01cc147 @bep #14771
  • Adjust the SECURITY.md slightly 8ee19ff9 @bep
  • resources/page: Add passing test for Issue #14325 0d58e428 @jmooring
  • Add a more flexible filename identifier scheme that also allows setting roles and versions (#14754) ce2a156a @bep #14750
  • common/hugo: Deprecate extended and extended_withdeploy editions a17bdbc5 @jmooring #14696
  • parser/pageparser: Add a parser fuzz test 8f94d65c @bep
  • Replace deprecated .Site.Sites/.Page.Sites with hugo.Sites intests 90d8bf34 @bep
  • agents: Add a note about having the issue ID in test names bbb42b5a @bep
  • build(deps): bump github.com/getkin/kin-openapi from 0.135.0 to 0.137.0 d4ae662d @dependabot[bot]
  • build(deps): bump github.com/mattn/go-isatty from 0.0.21 to 0.0.22 9ede5fb9 @dependabot[bot]
  • build(deps): bump github.com/tdewolff/minify/v2 from 2.24.12 to 2.24.13 833a878e @dependabot[bot]
  • build(deps): bump github.com/magefile/mage from 1.17.1 to 1.17.2 4c03129f @dependabot[bot]
  • deps: Upgrade github.com/bep/imagemeta v0.17.1 => v0.17.2 080970bc @bep
  • build(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudfront (#14789) 896bc89a @dependabot[bot]
  • build(deps): bump github.com/mattn/go-isatty from 0.0.20 to 0.0.21 (#14788) 100dde53 @dependabot[bot]
  • build(deps): bump github.com/bep/mclib (#14787) bdebb797 @dependabot[bot]
  • build(deps): bump google.golang.org/api from 0.267.0 to 0.276.0 52123ae2 @dependabot[bot]
  • build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.41.5 to 1.41.6 38b8afdc @dependabot[bot]
  • build(deps): bump github.com/getkin/kin-openapi from 0.134.0 to 0.135.0 (#14781) 92766600 @dependabot[bot]
  • build(deps): bump github.com/bep/goportabletext from 0.1.0 to 0.2.0 (#14779) 790f4084 @dependabot[bot]
  • build(deps): bump golang.org/x/image from 0.38.0 to 0.39.0 (#14780) de6955ba @dependabot[bot]
  • deps: Upgrade github.com/bep/imagemeta v0.17.0 => v0.17.1 (#14775) a77bd527 @bep #14758
  • build(deps): bump golang.org/x/tools from 0.43.0 to 0.44.0 547ab29c @dependabot[bot]
  • build(deps): bump github.com/evanw/esbuild from 0.27.4 to 0.28.0 9a5c7e0d @dependabot[bot]
  • build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.41.1 to 1.41.5 6613b08e @dependabot[bot]
  • build(deps): bump github.com/pelletier/go-toml/v2 from 2.2.4 to 2.3.0 582c26ef @dependabot[bot]
  • build(deps): bump github.com/tdewolff/minify/v2 from 2.24.11 to 2.24.12 a4f2a8a5 @dependabot[bot]

v0.160.1

What's Changed
  • Fix panic when passthrough elements are used in headings 8b00030b @bep #14677
  • Fix panic on edit of legacy mapped template names that's also a valid path in the new setup c4855167 @bep #14740
  • Fix RenderShortcodes leaking context markers when indented 161d0d47 @bep #12457
  • Strip nested page context markers from standalone RenderShortcodes 45e45966 @bep #14732
  • Rename deprecated cascade._target to cascade.target in tests 58927aa1 @bep
  • Fix auto-creation of root sections in multilingual sites ce009e3a @bep #14681
  • readme: Fix links 07558724 @chicks-net

Discussion