Docs

Upgrading to Hinode V2

Upgrade your existing Hinode site to take advantage of the refactored architecture introduced in 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 sass binary is available on your PATH. 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-blocks import is required if your site uses any of the following blocks or components: hero, contact, faq, menu, testimonial-carousel, or section. 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:update

Switching 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 = true

The 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: none

After:

- _bookshop_name: hero
  hide_empty: false
  header_style: none

Mod-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 test

Migrating 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:

  1. Remove the purgecss-whitelister import and whitelister([...]) call.
  2. Replace the flat safelist array with a structured object containing standard, deep, and greedy arrays.
  3. Expand dynamicAttributes to 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
        ;;
    esac

Update 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@v5

Updating 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.