✨ Highlights

This release closes the long-running #175 (GitHub Pages subpath assets 404 on nested pages), unifies navigation trailing-slash handling across project types, bundles MiniSearch locally so keyword search works without a CDN, and silences the duplicate auto-install spam that appeared when running docmd in a directory without a package.json.

No breaking changes. No new config required. Existing configurations, plugins, and CI pipelines work unchanged.

🐛 Fix: Subpath Deploy Asset Resolution (#175)

The 0.8.14 approach combined a <base href> tag with depth-relative asset paths (../../assets/...). On a subpath deploy (e.g. https://user.github.io/repo/), the browser resolved the depth-relative path against the <base> URL, which stripped the /repo/ prefix and 404’d every asset on nested pages (/repo/guide/).

The fix: subpath deploys now emit root-relative asset and navigation URLs (/repo/assets/css/...) and the <base> tag is no longer emitted for non-offline builds. Root-relative paths resolve correctly at any page depth, work with fetch() and SPA navigation, and no longer break hash-anchors on nested pages. Offline builds keep their existing depth-relative + index.html design untouched.

No config change needed

The fix is automatic. Whether you set "base": "/repo/", omit base entirely (auto-derived from url), or deploy at the root, assets now resolve correctly on every page.

🧹 Fix: Navigation Trailing-Slash Consistency

In non-i18n projects using a local navigation.json, sidebar and prev/next links omitted the trailing slash (./guide) whilst markdown body links kept theirs (./guide/). The local navigation.json was loaded after the normalisation pass ran, so its paths bypassed the centralised normalizeNavPaths step.

The fix: the local navigation.json is now normalised at load time, matching the treatment that inherited config navigation and auto-generated navigation already received. All navigation surfaces now agree on the trailing-slash convention.

🔒 Bundled MiniSearch (No CDN Dependency)

Keyword search previously loaded MiniSearch from cdn.jsdelivr.net at runtime. This broke search in air-gapped environments, behind corporate firewalls, and during the sandboxed browser test suite.

The fix: MiniSearch is now copied from node_modules into site/assets/js/vendor/minisearch.js at build time — the same asset pipeline used by docmd-search.js, docmd-git.js, and other plugin bundles. The version is read dynamically from the installed package, so it stays in sync automatically. The CDN is kept only as a last-resort fallback if local resolution fails.

This adds zero weight to the published @docmd/plugin-search package: MiniSearch was already a declared runtime dependency, just not bundled into the output.

🧹 Auto-Install Output De-duplicated

Two issues produced noisy, repetitive output when running docmd in a directory without a package.json:

  1. Worker-thread duplication: the build engine’s worker pool (one thread per core) each attempted to auto-install the same missing plugin, printing the same failure N times.
  2. Missing package.json: with no project to install into, every package manager refused — but docmd reported each refusal as an opaque “unknown error”, once per missing plugin.

The fix:

  • Worker threads now skip auto-install entirely (only the main thread has write access to node_modules and the user’s terminal).
  • A missing package.json produces a single, actionable hint pointing at npx @docmd/core init, instead of a wall of spawn failures.

Migration

Zero. Existing configurations, plugins, and CI pipelines work unchanged.

Full changelog: https://github.com/docmd-io/docmd/compare/0.8.14...0.8.15