✨ 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.
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:
- 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
Ntimes. - 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_modulesand the user’s terminal). - A missing
package.jsonproduces a single, actionable hint pointing atnpx @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