Docs

Upgrading to Hinode V3

Upgrade your existing Hinode site to the v3 module generation with its redesigned argument validation engine.

  Note

Still on Hinode v1 or earlier? Check out Upgrading to Hinode V2 first and work your way up one major version at a time.

Hinode v3.0.0  is a coordinated release of the theme and its companion modules, known as the v3 module generation. At its heart is a redesigned argument validation engine in mod-utils v6: arguments passed to shortcodes, partials, and content blocks are now validated recursively at any nesting depth, with clearer diagnostics and substantially faster builds. The engine keeps full compatibility with existing call sites, so most sites upgrade by updating module versions alone. This guide targets users of the Hinode template  running a v2-compatible site. Please use GitHub discussions  when encountering any challenges, or the issue tracker  for bug reports.

Meeting the Prerequisites  

The prerequisites are unchanged from v2: Hugo Extended 0.146.0 or later, and the Dart Sass transpiler. If your site pins an older hugo-bin or hugo-extended package, bump it to a release that provides Hugo 0.146+.

Updating the Module Imports  

Hinode v3 uses a new Go module path (hinode/v3) and pins a coordinated set of module majors. Update the import paths in config/_default/hugo.toml for every module your site uses:

Module Version Import path
hinode v3.0.1 github.com/gethinode/hinode/v3
mod-utils v6.4.1 github.com/gethinode/mod-utils/v6
mod-blocks v2.0.2 github.com/gethinode/mod-blocks/v2
mod-fontawesome v6.0.0 github.com/gethinode/mod-fontawesome/v6
mod-flexsearch v5.0.0 github.com/gethinode/mod-flexsearch/v5
mod-leaflet v3.0.0 github.com/gethinode/mod-leaflet/v3
mod-lottie v3.0.1 github.com/gethinode/mod-lottie/v3
mod-mermaid v5.0.0 github.com/gethinode/mod-mermaid/v5
mod-simple-datatables v4.0.0 github.com/gethinode/mod-simple-datatables/v4
mod-hanko v3.0.0 github.com/gethinode/mod-hanko/v3
mod-hubspot v4.0.0 github.com/gethinode/mod-hubspot/v4
mod-llm v2.0.0 github.com/gethinode/mod-llm/v2
mod-bootstrap-icons v2.0.0 github.com/gethinode/mod-bootstrap-icons/v2
mod-flaticon v2.0.0 github.com/gethinode/mod-flaticon/v2

Modules not listed, such as mod-bootstrap, mod-csp, and mod-katex, are unaffected and keep their current versions.

As an example, update the Hinode import as follows:

Before:

[[module.imports]]
  path = "github.com/gethinode/hinode/v2"

After:

[[module.imports]]
  path = "github.com/gethinode/hinode/v3"

Next, refresh the module dependencies and vendor folder:

hugo mod get github.com/gethinode/hinode/v3@v3.0.1
npm run mod:tidy
npm run mod:vendor

  Important

Adopt the generation together: update Hinode and all listed modules in a single step. Adding a single v3-generation module to a v2 site switches the entire site to the new validation engine through Hugo’s module mounts — technically compatible, but easy to do by accident and confusing to debug.

Reconciling Customized Templates and Styles  

The steps above cover sites that consume Hinode as-is. If your project overrides Hinode by shadowing its files — placing a copy of a layout, partial, or SCSS file at the same mount path so Hugo prefers yours — those copies are pinned to the version you forked from and do not follow the module upgrade. A shadowed file that built cleanly under v2 can reference partials, arguments, or variables that moved or changed in v3.

The reliable way to reconcile a shadow is to diff it against the vendored v3 copy and re-apply your customizations onto the v3 version, rather than the reverse:

# run from your project root, after vendoring the v3 modules
diff assets/scss/common/_variables-dart.scss \
     _vendor/github.com/gethinode/hinode/v3/assets/scss/common/_variables-dart.scss

Shadowed SCSS Variables  

  Note

A missing SCSS variable surfaces as a build error inside a vendored component, not your own file — for example Undefined variable in _vendor/.../hinode/v3/assets/scss/components/_table.scss. The fix belongs in your shadow of common/_variables-dart.scss, not in the file the error points to.

If you shadow common/_variables-dart.scss to override Bootstrap variables, add the variables v3 introduced so the vendored components can resolve them:

$main-breakpoint:       h.$main-breakpoint;
$padding-x:             h.$padding-x;
$padding-y:             h.$padding-y;
$theme-mode-transition: background-color .5s ease-in-out, color .5s ease-in-out, border-color .5s ease-in-out !default;

The SCSS Entry Point  

Hinode selects the stylesheet entry point from your transpiler: app-dart.scss for Dart Sass and app.scss for libsass. If your project shadows the entry point — often a leftover from an early Dart Sass workaround — re-sync its import list with the vendored v3 copy. In v3 the entry adds the lightbox component and imports scrollbar ahead of the components so they can @include its mixin. Unless you genuinely customize the import list, the simplest fix is to remove your shadow and let the vendored entry point run; it still picks up your shadowed _variables-dart.scss and theme/ files.

Moved Partials and Changed Signatures  

Custom layouts that call Hinode partials directly may need small updates. The most common in v3:

Call site (v2) v3
partial "assets/navbar-item.html" partial "assets/helpers/navbar-item.html" — and the menu argument is deprecated in favor of menu-entry
partial "page/blocks.html" . partial "page/blocks.html" (dict "page" . "embed" true)
partial "assets/sidebar.html" (docs layout) partial "page/sidebar-cached.html"
partial "assets/image.html" (dict "src" …) add "page" $page — the global-context fallback is deprecated and logs a warning

When passing a menu that may be empty, hand the partial a nil rather than an empty string; the v6 engine type-checks the argument.

Exercise the Paths Your Own Content Does Not  

A clean build of your site does not exercise override code hidden behind conditionals. Force each path with throwaway content before you trust the upgrade:

  • a footer menu entry with a child (a childless entry never reaches the item partial),
  • a type: docs section with one page, to render the docs layout,
  • a page with tags set, to render tag output.

Build, confirm there are no warn-invalid-arguments warnings, then remove the temporary content. This matters most for shared themes consumed by other sites, where the override paths are not reachable from the theme repository’s own content.

Reviewing the Build Output  

The new engine validates arguments recursively and reports every problem it finds, not just the first. Newly detectable problems — wrong-typed values, unknown nested attributes, and excess positional arguments — surface as warnings in this generation. They will be promoted to errors in a future major release, so use the quiet period to clean up your content and custom templates.

The most common warning after upgrading is an empty string passed where an argument should simply be omitted:

# triggers a warning: empty string is not a valid select value
navigation:
  color: ""

Remove the key instead of assigning an empty value.

Two behavioral refinements are worth knowing when reviewing custom templates:

  • Argument defaults defined in the schema are now applied consistently, including false and 0 values that previous releases silently skipped.
  • When a component declares both a current argument and a deprecated alias (such as show-preview and show_preview), the current argument always takes precedence and deprecated aliases no longer receive defaults.

Rendered output is intended to be identical to v2. The generation was validated against Hinode’s full block and component library; if you spot a visual difference after upgrading, please open an issue.

Updating CloudCannon Configurations  

If your site uses CloudCannon  with the setup-cloudcannon-cms utility, update any expose globs that reference vendored module paths, for example:

# before
- _vendor/github.com/gethinode/mod-utils/v5/layouts/**/*.html
# after
- _vendor/github.com/gethinode/mod-utils/v6/layouts/**/*.html

Regenerate the Bookshop configuration afterwards (npm run config) and verify visual editing on your connected site.

Adopting the New Argument API (Optional)  

Sites and themes with custom shortcodes or partials can keep using InitArgs.html — it remains fully supported as a compatibility shim. When you are ready, migrate to the new Args.html partial for a cleaner contract: a separated result envelope (args, err, errmsg, warnmsg, defaulted), camelCase argument keys, and strict validation. See the mod-utils documentation  for the full API reference and migration notes.