Docs
Upgrading to Hinode V2
Note
Still on Hinode v0.x? Check out Upgrading to Hugo Modules and Upgrading to Hinode V1 first.
Hinode v2.0.0 is a major architectural refactoring of the theme. Content blocks are now published as a standalone module, the Dart Sass transpiler is required, and several companion modules have bumped major versions with breaking changes. This guide targets users of the Hinode template running a v1-compatible site. The template repository has been fully updated for v2 and can be used as a reference for any of the changes described below. Please use GitHub discussions when encountering any challenges, or the issue tracker for bug reports.
Meeting the Updated Prerequisites
Hugo Extended is still required. In addition, Dart Sass is now required — the libsass transpiler is no longer supported.
Important
Install Dart Sass on your local machine before upgrading. Download the latest release from the Dart Sass releases page and ensure the
sassbinary is available on yourPATH. If you use CI/CD automation, see Updating the CI/CD Pipeline below.
The minimum Hugo version remains 0.146.0, unchanged from v1.
Updating the Module Imports
Hinode v2 uses a new Go module path (hinode/v2). Content blocks are also no longer bundled with the core theme — they are now published as a separate mod-blocks module.
Update config/_default/hugo.toml to replace the existing Hinode import and add mod-blocks:
Before:
[[module.imports]]
path = "github.com/gethinode/hinode"After:
[[module.imports]]
path = "github.com/gethinode/hinode/v2"
[[module.imports]]
path = "github.com/gethinode/mod-blocks"Note
The
mod-blocksimport is required if your site uses any of the following blocks or components:hero,contact,faq,menu,testimonial-carousel, orsection. Sites that do not use content blocks can omit this import.
Once the import paths are updated, run the following command to update go.mod and go.sum and vendor all modules:
npm run mod:updateSwitching to Dart Sass
Update the [main.build] block in config/_default/params.toml to use the Dart Sass transpiler:
Before:
[main.build]
transpiler = "libsass"After:
[main.build]
transpiler = "dartsass"
silenceDeprecations = trueThe silenceDeprecations = true setting suppresses deprecation warnings emitted by Bootstrap’s upstream Sass code during compilation.
Reviewing Companion Module Upgrades
Running npm run mod:update automatically resolves all module path changes. Review the following breaking changes in each module to determine whether your site is affected.
Mod-Blocks
Content blocks — including hero, contact, faq, menu, testimonial-carousel, and section — were previously bundled with the core Hinode theme. They are now published as a standalone module at github.com/gethinode/mod-blocks. See
Updating the Module Imports
above.
Breaking change: Block arguments now use snake_case instead of kebab-case. Update any content block definitions in your frontmatter accordingly. For example:
Before:
- _bookshop_name: hero
hide-empty: false
header-style: noneAfter:
- _bookshop_name: hero
hide_empty: false
header_style: noneMod-Fontawesome V5
The module path changed from github.com/gethinode/mod-fontawesome/v4 to github.com/gethinode/mod-fontawesome/v5.
Breaking change: FontAwesome icons using mode="svg" are now rendered as build-time inline SVGs instead of being converted by a JavaScript runtime. Icons injected dynamically after page load via custom JavaScript will no longer be automatically converted to SVG. Migrate any such patterns to use static markup or the built-in Hinode shortcodes.
Mod-Flexsearch V4
The module path changed from github.com/gethinode/mod-flexsearch/v3 to github.com/gethinode/mod-flexsearch/v4. This version requires Hinode v2 and mod-utils v5. If you are not yet ready to upgrade to Hinode v2, stay on mod-flexsearch v3.
Mod-Mermaid V4
The module path changed from github.com/gethinode/mod-mermaid/v3 to github.com/gethinode/mod-mermaid/v4. This version introduces stricter argument validation. Review any custom Mermaid shortcode invocations and remove deprecated arguments flagged in the build output.
Updating the Npm Toolchain
Several npm packages were updated or replaced. Apply the following changes to package.json and run npm install when done.
Hugo Binary
Replace hugo-bin with hugo-extended. The new package targets Hugo Extended directly without requiring the buildTags configuration block.
Remove from dependencies (and delete the top-level "hugo-bin" config object if present):
"hugo-bin": "0.149.2"Add to dependencies:
"hugo-extended": "^0.158.0"ESLint
ESLint v10 drops support for the neostandard shareable config in favor of a flat config with explicit plugins.
Remove from devDependencies:
"neostandard": "^0.12.2"Add to devDependencies:
"@eslint/js": "^10.0.1",
"@stylistic/eslint-plugin": "^5.10.0",
"eslint": "^10.1.0",
"globals": "^17.4.0"Stylelint
Upgrade to v17:
"stylelint": "^17.5.0",
"stylelint-config-standard-scss": "^17.0.0"PostCSS and PurgeCSS
Upgrade @fullhuman/postcss-purgecss from v7 to v8 and remove purgecss-whitelister (replaced by an explicit safelist — see
Updating the PostCSS Configuration
):
Remove from dependencies:
"purgecss-whitelister": "^2.4.0"Add or update in dependencies:
"@fullhuman/postcss-purgecss": "^8.0.0",
"cssnano": "^7.1.3",
"cssnano-preset-advanced": "^7.0.11",
"postcss-cli": "^11.0.1"Husky and Commitlint (Optional)
The template now ships with Husky v9 git hooks that enforce Conventional Commits . This is optional but recommended for consistency with the upstream template.
Add to devDependencies:
"@commitlint/cli": "^20.5.0",
"@commitlint/config-conventional": "^20.5.0",
"husky": "^9.1.7"Add a prepare script to scripts:
"prepare": "node .husky/install.mjs"Create the following three files in a .husky/ directory at the repository root:
.husky/install.mjs — skips Husky in CI and production environments:
// Skip Husky in CI and production
if (process.env.CI === 'true' || process.env.NODE_ENV === 'production') process.exit(0)
const husky = await import('husky')
husky.default().husky/commit-msg — validates commit message format:
npx --no -- commitlint --edit $1.husky/pre-commit — runs linting before each commit:
npm testMigrating the ESLint Configuration
Rename eslint.config.js to eslint.config.mjs and replace its contents. The new config uses ESM imports and the @eslint/js + @stylistic/eslint-plugin plugins instead of neostandard.
Before (eslint.config.js, CommonJS):
'use strict'
module.exports = require('neostandard')({
ignores: [
'assets/js/vendor/**',
'node_modules/**'
]
})After (eslint.config.mjs, ESM):
import js from '@eslint/js'
import stylistic from '@stylistic/eslint-plugin'
import globals from 'globals'
export default [
js.configs.recommended,
stylistic.configs.customize({
indent: 2,
quotes: 'single',
semi: false,
arrowParens: false,
braceStyle: '1tbs',
commaDangle: 'never'
}),
{
languageOptions: {
globals: {
...globals.browser
}
},
rules: {
'@stylistic/space-before-function-paren': ['error', 'always'],
'@stylistic/arrow-parens': ['error', 'as-needed'],
'@stylistic/operator-linebreak': ['error', 'after', { overrides: { '?': 'before', ':': 'before' } }],
'@stylistic/max-statements-per-line': 'off',
'no-unused-vars': ['error', { vars: 'all', args: 'after-used', argsIgnorePattern: '^_', ignoreRestSiblings: true }]
}
},
{
ignores: [
'assets/js/vendor/**',
'node_modules/**'
]
}
]Delete the old eslint.config.js once the new file is in place.
Updating the PostCSS Configuration
The config/postcss.config.js safelist approach changed significantly. The previous config used purgecss-whitelister to scan SCSS files in _vendor/ by path. Those paths reference the hinode module (not hinode/v2) and will no longer resolve after upgrading.
Replace the old whitelister approach with an explicit pattern-based safelist. At minimum, update the following:
- Remove the
purgecss-whitelisterimport andwhitelister([...])call. - Replace the flat
safelistarray with a structured object containingstandard,deep, andgreedyarrays. - Expand
dynamicAttributesto include'data-bs-main-theme'and'data-transparent':
dynamicAttributes: ['data-bs-theme', 'data-bs-main-theme', 'data-bs-theme-animate', 'data-transparent', 'role'],Copy the full reference postcss.config.js from the
Hinode template repository
to ensure all component patterns are covered, including patterns for the new testimonial-, preview-, and d-none-main classes introduced in v2.
Updating the CI/CD Pipeline
If your site uses GitHub Actions, update .github/workflows/lint-build.yml to install Dart Sass and upgrade the Go and cache actions.
Add the DART_SASS_VERSION environment variable at the top of the workflow (or job):
env:
DART_SASS_VERSION: "1.98.0"Add a Dart Sass installation step before the Hugo build step. The following example handles Linux, macOS, and Windows:
- name: Install Dart Sass
shell: bash
run: |
case "${{ runner.os }}" in
Linux)
URL="https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
curl -fsSL "$URL" | tar -xz -C /usr/local/bin --strip-components=1 dart-sass/sass
;;
macOS)
URL="https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-macos-x64.tar.gz"
curl -fsSL "$URL" | tar -xz -C /usr/local/bin --strip-components=1 dart-sass/sass
;;
Windows)
URL="https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-windows-x64.zip"
curl -fsSL "$URL" -o dart-sass.zip
unzip -q dart-sass.zip
echo "$PWD/dart-sass" >> $GITHUB_PATH
;;
esacUpdate the Go setup step to use the stable release:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "stable"Upgrade the cache action from v4 to v5:
- uses: actions/cache@v5Updating the Netlify Configuration
If you deploy to Netlify, update the environment variable pins in netlify.toml:
[build.environment]
DART_SASS_VERSION = "1.98.0"
HUGO_VERSION = "0.158.0"
NODE_VERSION = "24.12.0"The DART_SASS_VERSION variable is picked up by the Netlify build image to install Dart Sass before the Hugo build runs.