Skip to content

Releases: docmd-io/docmd

docmd@0.8.9 🔒 (Plugin Hardening + Semantic 0.1.0)

Choose a tag to compare

@mgks mgks released this 26 Jun 18:04

docmd logo

docmd 0.8.9 🔒 Plugin + Semantic 0.1.0

Build production-ready documentation from Markdown in seconds.

✨ Highlights

This release is a hardening pass on the plugin and template ecosystem. The biggest change is structural: every official @docmd/* package now carries a docmd namespace in its package.json, and a build-time registry generator reads those namespaces to produce the single source of truth that the runtime loader consumes. The plugin auto-installer is now resilient to packages that ship import-only exports fields, and a new docmd doctor pre-flight command catches configuration drift before a build. Two previously-silent bugs in published tarballs are also fixed: the 404 page now renders with the summer template and translated strings instead of falling back to the default template with raw translation keys.

No public API changes. No breaking config changes. Purely a hardening release.

🔌 Build-time plugin registry (single source of truth)

A new workspace-level script — scripts/build-plugin-registry.mjs — walks packages/{plugins,templates,engines}/*, reads each package's package.json#docmd namespace, and emits a generated JSON catalog (packages/api/registry/plugins.generated.json). Wired as the prebuild step of @docmd/api, so the registry is regenerated on every build.

The runtime loader (packages/api/src/hooks.ts getPluginRegistry) now reads from the generated file, with two resolution paths (published layout <pkg>/registry/... and monorepo dev layout <repo>/packages/api/registry/...). The hand-maintained packages/plugins/installer/registry/plugins.json that lived in the installer is no longer consulted at runtime.

📦 docmd namespace standardisation

Every official @docmd/* package now carries a docmd namespace in its package.json. The namespace is the contract that the registry generator reads and the loader cross-checks against the JS descriptor at load time. Fields: key (user-facing identifier), kind (plugin / template / engine), displayName, tagline, capabilities (required for plugins and templates, used by the build-time cross-check), and preview (template only).

Engines get the same shape but no capabilities — they don't participate in the hook system. The auto-installer checks kind === 'engine' and refuses to install them.

🩺 docmd doctor — pre-flight check

A new CLI subcommand for diagnostics. No filesystem writes, no build side-effects — purely diagnostic.

npx @docmd/core doctor [options]
Option Description
--config <path> Path to a non-default docmd.config.json (or .ts/.js/.mjs).
--fix Auto-install missing official plugins or templates.
--json Emit the report as machine-readable JSON.

By default, doctor prints a human-readable summary covering the installed @docmd/core version, every configured plugin (with version and ✓ installed / ⚠ missing status), the active template, the requested engines (js always-on, rust opt-in), and a list of auto-install candidates. With --fix, it shells out to the project's package manager to install the candidates. With --json, the same data is emitted as a single JSON object — useful for pre-commit hooks and CI gates.

Also available as pnpm doctor (which routes through the workspace docmd script in the monorepo).

🛠 New pnpm scripts in the monorepo

The monorepo's package.json gets a batch of new pnpm scripts, all pointing at the playground via the existing --cwd flag (same pattern as pnpm dev and pnpm live):

pnpm doctor           # → docmd doctor
pnpm validate         # → docmd validate
pnpm migrate          # → docmd migrate
pnpm gen:deploy       # → docmd deploy
pnpm mcp              # → docmd mcp
pnpm plugin:add foo   # → docmd add foo
pnpm plugin:remove foo # → docmd remove foo
pnpm build:playground # → docmd build (separate from `pnpm build` which is the monorepo-wide build)

🐛 Bug fixes

  • Plugin auto-install: resilient to import-only exports. The auto-installer in @docmd/api previously used require.resolve to resolve installed packages, which throws ERR_PACKAGE_PATH_NOT_EXPORTED for packages that ship only an import condition in exports. The retry path now uses await import(name) directly, which honours the exports field natively. A defense-in-depth registry re-check is performed inside the retry path — the set of names that can be auto-installed is unchanged, only the set of exports conditions they can carry is larger.
  • Plugin loader: capability cache and manifest drift check. A per-key capability set cache avoids re-walking the registry on every dev-server rebuild. A new manifest drift check warns if the JS descriptor's capabilities array doesn't match the manifest's capabilities array — closing the silent-hook-drop bug where a plugin that implemented a hook but forgot the corresponding capability in its descriptor would have its hook silently skipped.
  • Better "Could not load X after auto-install" errors. The post-install retry's catch block now surfaces err.code (e.g. ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_MODULE_NOT_FOUND) and the first line of err.message. The autoInstallPlugin catch block also surfaces the underlying stderr from the package manager and prints a hint for the most common cases.
  • @docmd/ui: include translations/ in the published tarball. The server-side translation loader reads translation JSON files at __dirname/../translations/. The package.json#files was missing "translations", so npm packed the tarball without the translation files. The 404 page was the most visible symptom: rendered lazily by the deployed site's static-file fallback, the translation cache was empty, and the keys leaked. Now all 7 locale files ship.
  • @docmd/template-summer: include templates/ and assets/ in the published tarball. The summer template's runtime uses new URL('../templates/...', import.meta.url) inside dist/index.js, which resolves to <package-root>/templates/... (not <package-root>/dist/templates/...). The package.json#files was just ["dist"], so the published tarball only contained dist/, and the resolver fell back to the default template. Now the published tarball matches the monorepo dev layout and the summer template renders correctly.
  • Dev server: strip leading slash before safePath(). The CWE-22 fix from 0.8.9 (replacing filePath.startsWith(rootAbs) with safePath(rootAbs, ...)) had a regression in the dev server: URL pathnames always start with /, and path.resolve('/abs/root', '/index.html') returns /index.html — which always failed the safePath boundary check and produced 403 Forbidden for every legitimate request. Fix: strip the leading / from the URL pathname before passing to safePath().
  • Live editor, port probe, and Docker docs default to loopback. The live editor's server.listen and the checkPortInUse probe now bind to 127.0.0.1 instead of 0.0.0.0. LAN access is opt-in via DOCMD_HOST=0.0.0.0 or --host 0.0.0.0, with a TUI warning when active. The docker/DOCKER.md examples now use the loopback default.
  • Utils: scriptLiteral and jsonInject harden inline script escaping. Both now properly escape </script, <!--, U+2028, and U+2029 in addition to the existing JSON-safe encoding. The hardening is silent for non-conflicting strings; round-trips through JSON.parse still work because the escape uses JSON-safe sequences.

Changelog

  1. Registry: New scripts/build-plugin-registry.mjs — generates packages/api/registry/plugins.generated.json from each official package's docmd namespace.
  2. Loader: getPluginRegistry reads the generated file with two resolution paths; the hand-maintained installer/registry/plugins.json is no longer consulted at runtime.
  3. Namespace: docmd namespace added to all 14 official @docmd/* packages (12 plugins, 2 engines) and updated on @docmd/template-summer with key: "summer".
  4. Loader: Per-key capability set cache + manifest drift check (checkManifestCapabilityDrift).
  5. Auto-install: Retry path uses await import(name) instead of require.resolve + import(file://path), with a defense-in-depth registry re-check.
  6. Auto-install errors: err.code + first line of err.message surfaced; package-manager stderr + hint printed.
  7. CLI: docmd doctor subcommand added with --config, --fix, --json flags. Registered in the CLI dispatcher; help text updated.
  8. CLI: New pnpm scripts in the monorepo — doctor, validate, migrate, gen:deploy, mcp, plugin:add, plugin:remove, build:playground.
  9. UI: packages/ui/package.json#files now includes translations/.
  10. Template: packages/templates/summer/package.json#files now includes templates/ and assets/.
  11. Dev server: safePath() in serveStatic strips the leading / from URL pathnames.
  12. Live editor: server.listen and checkPortInUse bind to 127.0.0.1; DOCMD_HOST=0.0.0.0 opt-in.
  13. Docker docs: Three command: dev --host 0.0.0.0 examples replaced with the loopback default; "Network Issues" troubleshooting documents the opt-in path.
  14. Utils: scriptLiteral and jsonInject escape </script, <!--, U+2028, U+2029.
  15. Tests: packages/utils/test/html-escape.test.js updated to assert the new escape behaviour.
  16. Docs: New "ESM Exports — the default Condition" section in building-plugins.md and building-templates.md; new "Bundled registry removal in 0.9.0" callout; new docmd doctor entry in `reference/cl...
Read more

docmd@0.8.8 🛡️ (Security Hardening + OKF)

Choose a tag to compare

@mgks mgks released this 25 Jun 19:56

docmd logo

docmd 0.8.8 🛡️ Security + OKF Integration

Build production-ready documentation from Markdown in seconds.

A focused hardening release with OKF (Open Knowledge Format) Integration.
Every change here is either a regression caught by users, a CI workflow bug, or a build-time reliability issue.

🐛 Bug fixes

Docker: volume mount permissions fixed

docmd init and other file-writing commands failed with "Permission denied" when /docs was a host-mounted volume owned by a uid other than the container's built-in docmd user (uid 1001).
The image now ships with su-exec and the entrypoint detects the host uid:gid of the mounted directory and re-execs as that identity before running any command — same pattern used by the official postgres and redis images.

# All of these now work without -u flags on a host volume
docker run -v $(pwd):/docs ghcr.io/docmd-io/docmd:latest init
docker run -v $(pwd):/docs -p 3000:3000 ghcr.io/docmd-io/docmd:latest

The cp -a (archive) mode that triggered "Operation not permitted" warnings on ownership preservation is gone.
The -u $(id -u):$(id -g) workaround is no longer required and has been removed from all READMEs and the Docker deployment guide.

Docker: init now non-blocking in CI

The interactive "Do you want to override these files?" prompt hung in non-TTY environments (CI, docker run without -it, piped input).
The CLI now detects non-interactive mode and skips the prompt automatically — keeping existing files by default (safe), or accepting -y/--yes to opt into overwrite.
A new --force flag also works in any environment for explicit override.

# Force overwrite in CI / Docker / piped input
docker run --rm -v $(pwd):/docs ghcr.io/docmd:latest init --force

# Or use -y
docker run --rm -v $(pwd):/docs ghcr.io/docmd:latest init -y

docmd add on npx: false "npm not found" on Windows

npx @docmd/core add <plugin> on Windows PowerShell printed "The package manager 'npm' was not found on your system PATH" even though npm --version worked fine in the same shell.
Root cause: when @docmd/core is launched through npx, the spawned child process inherits a stripped PATH on Windows.
The installer now resolves npm/pnpm/yarn/bun relative to process.execPath (Node's own location), which always works regardless of how @docmd/core was launched.

The error message also now detects the specific case (Node reachable + binary missing) and suggests installing the plugin via the host package manager directly.

Template registry lookup for @docmd/template-*

Setting theme.template to an official template like summer or @docmd/template-summer printed:

⬢ Plugin "template-summer" not found in official registry - manual installation required

Root cause: the auto-install registry lookup stripped @docmd/plugin- from the package name to derive the registry key, but didn't strip @docmd/template-.
So @docmd/template-summer resolved to key template-summer instead of summer, which doesn't exist in the registry.
Now both prefixes are stripped correctly.
Custom/third-party templates were never affected.

Semantic search peer dependency handling

When plugins.search.semantic = true was set and the ML peer dependencies (@huggingface/transformers, onnxruntime-node) weren't present, the build silently fell back to keyword search with a confusing error buried deep inside docmd-search:

⬢ Semantic indexing failed: Embedding failed: Failed to load model "Xenova/all-MiniLM-L6-v2": Cannot find package '@huggingface/transformers'

Two improvements:

  1. Clear pre-flight check — the plugin now verifies the peer dependencies are resolvable after auto-install and emits an actionable error naming the missing package, instead of letting the failure surface from inside docmd-search.
  2. Stale module cache fix — after auto-installing docmd-search mid-build, the current Node process's module cache couldn't see the new packages.
    Indexing now runs in a child process so it starts with a clean module resolution.
    npm install auto-install also passes --foreground-scripts so onnxruntime-node's postinstall (native binary download) actually runs in CI environments with npm's allow-scripts security feature enabled.

npm-publish: packages/templates/* now in the publish loop

The npm-publish.yml workflow was iterating packages/*, packages/legacy/*, packages/plugins/*, packages/engines/* but missing packages/templates/*.
Templates like @docmd/template-summer and @docmd/template-rain were not being released.
Now included.

docmd init no longer makes a network call by default

Previously docmd init always fetched SKILL.md from raw.githubusercontent.com/docmd-io/docmd-skills on every run.
The fetched content overrode the bundled default if it succeeded.
Two changes:

  • Default is now local-only — the bundled SKILL.md content ships with the package and is written without any network call.
  • Opt in via --with-skill flag or DOCMD_FETCH_REMOTE_SKILL=1 env var to fetch the latest SKILL.md from the docmd-skills repo (CI environments and offline workstations can keep using the bundled default).
docmd init --with-skill    # fetch latest SKILL.md from docmd-skills
DOCMD_FETCH_REMOTE_SKILL=1 docmd init   # same, via env var

docker-publish: stopped firing on every push to main

The docker-publish.yml workflow had a push: branches: [main] trigger that caused it to run on every commit to main, not just on release events. Removed — it now only fires on v* tag pushes, published releases, and manual dispatch.

Dockerfile: pnpm install made reliable in CI

The production stage was using corepack prepare pnpm@10.33.2 --activate (with explicit version), but the builder stage's corepack prepare --activate (no version) failed in GitHub Actions CI because it required a package.json in the current working directory.
Both stages now use npm install -g pnpm@10.33.2 directly — simpler, no corepack resolution steps, and works identically in CI and local.
On a clean build, pnpm also refused to remove the existing node_modules directory without interactive confirmation in the non-TTY Docker environment.
The install command now passes --config.confirmModulesPurge=false, which is pnpm's targeted flag for this case.
The broader ENV CI=true route was considered and rejected because it leaks into every subsequent RUN.

UI translation keys render as literal text in published package

builtWith, copyContext, copiedToClipboard and other template-translated strings rendered as literal key text in built output when using the published @docmd/ui package.
The monorepo worked fine because packages/ui/translations/ existed alongside dist/, but the published package's files array didn't include the translations/ directory, so pnpm pack stripped it from the tarball.
Added translations to the files array; loadTranslations now also emits a clear warning when the directory is missing so future regressions don't surface as silent literal-key output.

@docmd/template-* registry key mismatch

Setting theme.template to summer or @docmd/template-summer printed "Plugin 'template-summer' not found in official registry — manual installation required" even though the package was installed.
Root cause: the auto-install registry lookup stripped @docmd/plugin- from the package name to derive the registry key, but didn't strip @docmd/template-.
So @docmd/template-summer resolved to the key template-summer instead of summer.
Both prefixes are now stripped correctly.
Custom/third-party templates were never affected — they bypass the registry lookup entirely.

--offline mode: navigation links don't navigate (#164)

Clicking a navigation sidebar child link in an --offline build only toggled the parent's collapse state instead of opening the target page.
Root cause: the data-spa-enabled flag stayed true for offline builds, so the SPA click handler bound and consumed clicks with preventDefault().
But file:// has no fetch for the SPA path-fetch, so the navigation never happened.
Fixed in two places:

  • data-spa-enabled is now false when isOfflineMode is true, so the SPA handler never binds and the browser does normal full-page navigation.
  • A safety-net check in the main SPA click handler bails out for file:// protocol, so the click isn't consumed even if the flag is wrong.
docmd build --offline   # SPA now disabled automatically
# Workaround on 0.8.7: open via local server, or set layout.spa: false

--offline mode: comprehensive file:// robustness pass

While fixing #164, audited every other place the client-side JS touches localStorage, fetch, XMLHttpRequest, or relies on SPA/network.
All localStorage writes (sidebar collapse, theme toggle, locale preference, cookie consent) are now wrapped in try/catch so file:// builds don't throw in Chromium-based browsers where local storage is blocked.
The version switcher's HEAD fetch check is skipped under file:// (browsers block it anyway), going straight to direct navigation.
XHR in the noStyle i18n loader is wrapped with onerror handling.
URL builder already appended /index.html for offline mode (unchanged).
Result: opening a built site via file:// now works end-to-end with no JS errors, no broken navigation, and no silent feature loss.

📚 Documentation updates

The following docs were updated to reflect the fixes above:

  • **[Deployment → Docker]...
Read more

docmd@0.8.7 🎭 (Custom Templates API)

Choose a tag to compare

@mgks mgks released this 21 Jun 15:24

docmd logo

docmd 0.8.7 • Custom Templates API

Build production-ready documentation from Markdown in seconds.

Templates are now plugins. The first official template, Summer, ships alongside two new opt-in UI features — cookie consent and an announcement banner — built directly into @docmd/ui. Also includes a Docker :latest fix so quick-start works out of the box, and a handful of post-release hardening fixes below.

✨ What's new

Templates are now plugins

A template package declares capabilities: ['template'] and ships layout overrides plus its own CSS/JS. The new resolver checks four levels, falling back to the default at any step:

frontmatter.template  →  config.templates[glob]  →  config.theme.template  →  built-in default
// template-summer/index.js
export default {
  plugin: { name: 'template-summer', version: '0.1.0', capabilities: ['template'] },
  templates: [
    { type: 'layout', templatePath: '...' },
    { type: 'sidebar', templatePath: '...' },
  ],
  templateAssets: [
    { type: 'css', path: '.../summer.css', priority: 10, position: 'head' },
  ],
};

Templates can override any of 14 supported slots (layout, 404, sidebar, header, footer, banner, cookie-consent, and more) and can be set per-page via frontmatter, or site-wide via config. User customCss always wins — templates can't use !important.

Templates — architecture & authoring guide

☀️ Summer — the first official template (Preview)

summer preview

A bright, airy layout with a top search bar, soft halo accents, and a denser card grid.

docmd add summer       # installs and switches your config
docmd remove summer    # reverts to default

🍪 Cookie consent dialog

Built into the default UI. Off unless you opt in.

{
  "cookie": {
    "enabled": true,
    "message": "We use cookies to ensure you get the best experience.",
    "policyUrl": "/privacy",
    "position": "bottom-right",
    "expiryDays": 180
  }
}

Fires a docmd:cookie-consent event on choice, so plugins and templates can react.

📢 Site-wide announcement banner

Sits above the menubar. Supports inline markdown or raw HTML.

{
  "layout": {
    "banner": {
      "content": "**v0.9 ships Friday** — read the announcement.",
      "type": "info",
      "link": { "text": "Read more", "url": "/blog/v0-9" }
    }
  }
}

Dismiss state is stored per-session, so the banner reappears on a fresh visit.

Fixed

Issue Fix
Docker :latest tag never published Workflow now tags :latest automatically on release events #153
Quick-start crashed on empty /docs in Docker Entrypoint seeds /docs from the bundled template when empty #154
xdg-open crash on dev server A missing browser-launch binary no longer crashes docmd dev #156
Sidebar nav double-click bug The main UI script could load twice under certain serving conditions, causing click handlers to fire twice and nav state to get stuck, now guarded against double-execution
Docker healthcheck always "unhealthy" Now probes ports 3000–3005 to match the dev server's auto-increment
i18n strings not translating in sidebar/nav partials t() function now passed to all layout partials; 13 missing keys added across all 7 locales
Copy-code button floated above the code block Button now anchors to the outer wrapper instead of an inner one
Mermaid diagrams broke on SPA navigation (not on full reload) Plugin <script> tags are now synced into the live DOM on every page swap, not just initial load
Non-English search results jumped to the page top instead of the heading Semantic-search client now uses a Unicode-aware slug regex, matching the parser-side generator (fixes Chinese, Japanese, Korean, Cyrillic, diacritics) #148
appearance: "system" issue Default-theme partial now reads DOCMD_APPEARANCE (the canonical name) and only honours localStorage when it holds a concrete light/dark value #160
Dev server kept rebuilding every few seconds with no edits New content-signature tracker ignores phantom fs.watch events from Spotlight/iCloud/Time Machine; config watcher now watches the parent directory instead of the file directly
tag container didn't accept quoted URLs or the external: prefix Parser regex now supports "..." and '...' around option values; url: is the canonical property name, link: kept as an alias

Improved

  • Conditional plugin asset loading — plugins can now declare a condition on their assets so JS/CSS only ship to pages that actually need them. Verified on the playground: Mermaid's ~500 KB library now loads on 3/11 pages (was 11/11) and KaTeX's ~30 KB CSS on 1/1 math page (was 11/11).
  • Sensible config defaults — a fresh docmd.config.json (or no config at all) now ships a fully-featured site: page navigation, copy-code buttons, breadcrumbs, search, theme switch, and more are all on by default. Full defaults table →
  • Tighter UI — header and menubar height reduced 52px → 44px; smaller heading-anchor icons; denser card grids.
  • New default 404 page — glass-card layout with soft halo background, Return Home / Go Back actions, fully translated and RTL-aware.
  • Step permalinks — every <li> in a docmd steps list now carries a globally-unique id="step-N" and a hidden link-2 icon that fades in on hover or focus, so individual steps are easy to share and deep-link.
  • Contrast pass — text and link colors adjusted across light and dark themes to meet WCAG AA.
  • Redesigned active sidebar link — a "node on thread" pill replaces the old left-border style.
  • Keyboard focus is now visible:focus-visible gets a halo glow site-wide.
  • Changelog entry permalinks — mirrors the step-permalink pattern: every changelog entry date now carries an id and a hidden link-2 icon that fades in on hover, so individual releases are easy to share and deep-link.
  • --verbose is now universal — previously only respected by add/remove. Now sets DOCMD_VERBOSE=true in the environment so every subcommand (build, dev, live, init, validate) can opt-in to detailed logs, and is also forwarded to buildSite and buildLive for the structured path.
  • Docker image works with zero setupdocker run ghcr.io/docmd-io/docmd:latest now seeds a demo site automatically; no volume mount required.
  • @docmd/plugin-search missing runtime dependencymarkdown-it was incorrectly listed as dev-only; installing the plugin now works on first try.
  • Docker tags simplified — releases now publish exactly two tags: the version number and :latest.

Looking ahead — Node 20+ in v0.9.0

The next minor release raises the floor to Node.js 20+ (from 18+), bringing the engine requirement, shipped Docker runtime, and CI environment all onto Node 22. Node 18 reached end-of-life in April 2025; this keeps docmd on a supported runtime with room to spare.

This release (0.8.7) is unaffected — the >=18 floor stays until 0.9.0 ships.

Now (0.8.x) Next (0.9.0)
Minimum Node 18+ 20+
Docker base 20-alpine 20-alpine
Type Node ^24 ^24
CI target 24 24

Skills Update (docmd-skills@1.1.0)

Skills have been updated for 0.8.7 with three specialised skills that work together. The agent automatically selects the most relevant skill based on the current task and context, reducing unnecessary token usage while maintaining accuracy.

npx docmd-skills [dir]

Replace [dir] with the directory location where you keep agent skills — common choices are ~/.claude/skills/, ~/.cursor/skills/, or a project-level folder like ./.skills/.

Thanks 💖

Thanks to all contributors and community members who reported issues and provided feedback.

Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd
Skills: https://github.com/docmd-io/docmd-skills

Full Changelog: 0.8.6...0.8.7

docmd@0.8.6 🧠 (AI-First Integration & Native MCP Server)

Choose a tag to compare

@mgks mgks released this 05 Jun 10:36

docmd logo

docmd 0.8.6 • Native MCP + Agentic Skills

Build production-ready documentation from Markdown in seconds.

✨ Highlights

This release officially establishes docmd as the premier "AI-First" documentation engine. The centrepiece is a native Model Context Protocol (MCP) server enabling AI agents to interact with documentation workspaces via docmd mcp.

Alongside this, the release delivers a modular agent instruction set (docmd-skills), an official Docker image with multi-architecture support, client-side "Copy Markdown" and "Copy Context" widgets for LLMs, a search tokeniser overhaul supporting CJK and spaceless languages, critical enhancements to the Table of Contents layout, and a visual overhaul of the UI featuring radial top glows, a continuous changelog timeline, and upgraded steps components.

🔌 Native Model Context Protocol (MCP) Server

You can now start a native MCP server directly from your workspace:

docmd mcp

The server runs in local stdio mode (protocol version 2025-03-26), allowing AI developer agents (like Claude Desktop, Cursor, or Windsurf) to securely interface with your documentation workspace to:

  • Perform full-text and semantic documentation searches (search_docs)
  • Read markdown files and configurations (read_doc)
  • Run hyperlink and relative path validations (validate_docs)
  • Retrieve the unified repository context (get_llms_context)

Full protocol compliance including ping health checks and notifications/initialized lifecycle.

📖 Modular Agent Instruction Set (docmd-skills)

When running docmd init, a version-controlled SKILL.md is generated in the project root. The full instruction set is maintained as a modular collection in the docmd-skills repository:

  • cli.md: Setup, all CLI commands with flags and per-command options.
  • config.md: Complete docmd.config.json schema with defaults and inline comments.
  • plugins.md: Every built-in plugin with all config keys, defaults, and behaviour.
  • plugin-development.md: Hook signatures, lifecycle, ActionContext, custom plugin creation guide.
  • formatting.md: Container syntax, frontmatter reference, self-closing rules.
  • api.md: Node.js build API, browser API, MCP server, URL utilities, client-side events.
  • validation.md: Link checking and CI/CD integration.

All skill files include inline comments explaining defaults, reference links to full documentation, and llms-full.txt discoverability guidance.

🐳 Official Docker Image

docmd is now available as an official Docker image with multi-architecture support (linux/amd64 and linux/arm64):

# Pull and run with demo site
docker pull ghcr.io/docmd-io/docmd:latest
docker run -p 3000:3000 ghcr.io/docmd-io/docmd:latest

# Build your docs
docker run -v $(pwd)/docs:/docs -v $(pwd)/site:/site ghcr.io/docmd-io/docmd:latest build

Features include Docker Compose and Kubernetes deployment examples, non-root security, Alpine Linux base, health checks, and GitHub Actions CI/CD integration.

🧠 AI-First Context Extraction Widgets

To enable seamless documentation ingestion by AI assistants, we have introduced two new localised buttons next to page breadcrumbs:

  • Copy Markdown: Copies the clean body content of the document, automatically stripping YAML frontmatter metadata so LLMs ingest pure content.
  • Copy Context: Copies structured context containing the page URL, title, tags, version, and text, optimised for direct copy-pasting into AI chat windows.
  • Localisation: Supports translations and copied confirmations for all 7 primary languages (en, de, es, fr, hi, ja, zh).

🔍 Spaceless Script Search Tokenization (CJK, Thai, Lao, etc.)

We have resolved a search indexing limitation in MiniSearch for languages that do not use spaces between words. Previously, continuous character blocks (such as Chinese, Japanese, Korean, Thai, Lao, Khmer, Burmese, or Tibetan text) were indexed as single giant tokens, causing partial/sub-word matches to fail.

A unified CJK_AND_SPACELESS_REGEX tokenizer has been added. It splits spaceless character scripts into individual character tokens while preserving default space-based tokenization for English and other languages. This tokenizer runs symmetrically on:

  • The build-time offline index generator.
  • The multi-threaded background build worker.
  • The client-side browser query parser.

🔢 docmd-search 0.1.0-alpha.1

This release includes docmd-search 0.1.0-alpha.1, which fixes a critical bug where confidence percentages in search results could exceed 100% in certain edge cases. The scoring algorithm has been corrected to properly normalise relevance scores within the expected 0-100% range.

📚 Table of Contents Enhancements

The table of contents (TOC) component has received significant improvements in this release, addressing long-standing issues with scrolling behaviour and heading coverage.

H1 Heading Support

H1 headings (# Heading) are now properly included in the table of contents. Previously, only H2-H4 headings were displayed in the TOC, which meant important top-level headings were missing from the navigation sidebar.

Improved Scrolling Behaviour

The TOC sidebar now scrolls independently when it contains many items, preventing it from overlapping or interfering with the page footer. The active heading is automatically centred in the TOC view as you scroll through the content, making it easier to track your position in long documents.

Smooth scrolling has been optimised with debouncing to prevent jittery or jarring movements, providing a more polished reading experience.

Changelog

  1. MCP: Implemented native docmd mcp server capabilities running on local stdio.
  2. MCP: Updated protocol to 2025-03-26 — added ping handler, fixed notifications/initialized lifecycle.
  3. MCP: Fixed readline output pollution that corrupted the JSON-RPC stream.
  4. MCP: Added dedicated MCP Server documentation page.
  5. Skills: Modularized agent manuals into 7 skill files under docmd-skills/ with inline defaults and doc references.
  6. Skills: Added api.md (Node.js, browser, MCP, URL utilities) and plugin-development.md (hooks, lifecycle) modules.
  7. Skills: Added llms-full.txt discoverability guidance and agent usage instructions.
  8. Docker: Added official Docker image with multi-architecture support (amd64/arm64).
  9. Docker: Added Docker Compose, Kubernetes, and GitHub Actions deployment examples.
  10. Docker: Non-root security, Alpine base, health checks, SBOM attestation.
  11. AI: Added "Copy Markdown" and "Copy Context" UI widgets with translations for 7 languages.
  12. Search: Added a unified tokeniser for CJK, Thai, Lao, Khmer, Burmese, and Tibetan scripts in MiniSearch. #145
  13. Search: Fixed confidence percentage calculation in docmd-search 0.1.0-alpha.1 to prevent scores exceeding 100%.
  14. TOC: Added support for H1 headings in the table of contents with proper anchor links and styling.
  15. TOC: Implemented independent scrolling for the TOC sidebar with max-height constraints to prevent footer overlap.
  16. TOC: Added automatic centring of active TOC items during page scroll with debounced smooth scrolling.
  17. TOC: Extended scroll spy to observe H1 headings alongside H2-H4.
  18. Parser: Updated heading anchor injection to include H1 headings for permalink icons.
  19. UI: Fixed footer rendering issues caused by TOC overflow on pages with many headings.
  20. UI: Upgraded steps component with precise alignments, hover states, and glowing brand nodes.
  21. UI: Refactored changelog timeline to utilize a continuous grid axis with interactive expandable markers.
  22. UI: Added a modern adaptive radial halo glow at the top of the content page (light and dark modes).
  23. UI: Redesigned copy widgets as a unified, sleek segmented control button group.
  24. UI: Fixed a critical SPA routing bug where head assets (stylesheets and icons) were duplicated during client-side navigation due to relative path resolution shifts.

Thanks 💖

Thanks to all contributors and community members who reported issues and provided feedback on TOC behaviour and AI integrations.

Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd

Full Changelog: 0.8.5...0.8.6

docmd@0.8.5 ⚡️ (Offline Semantic Search Preview)

Choose a tag to compare

@mgks mgks released this 31 May 10:39
6d64122

docmd logo

docmd 0.8.4 • Semantic Search 0.1.0-alpha.0

Build production-ready documentation from Markdown in seconds.

✨ Highlights

This release introduces semantic search as an alpha preview, adds automatic robots.txt generation in the SEO plugin, fixes Mermaid C4Context rendering, and includes a new config upgrade command for modernising existing projects.

Semantic Search (Alpha Preview)

docmd now supports semantic search powered by local embeddings, enabling context-aware search results beyond simple keyword matching.

Features

  • Context-aware search beyond exact keyword matches
  • Natural typo tolerance
  • Finds related content even when different terminology is used
  • Fully local processing with no external services or API calls

Enable semantic search by adding semantic: true to your configuration:

{
  "plugins": {
    "search": {
      "semantic": true
    }
  }
}

The search plugin automatically installs docmd-search and downloads required models, if failed to do so, it falls back to keyword search.

image

Documentation - https://docs.docmd.io/plugins/search/#semantic-search-alpha-preview

Note: Multilingual models are available but still being tested. docmd currently uses docmd-search@0.1.0-alpha.0, so you may encounter bugs or inaccurate confidence scores while development continues.

Introducing Offline Semantic Search Engine (docmd-search)

We're excited to introduce docmd-search.

npm install docmd-search

docmd-search is a semantic search engine built for documentation sites. It runs entirely in the browser or CLI, requires no servers or API keys, and keeps all processing local.

Although created for docmd, it can be integrated into other documentation platforms, websites, and web applications.

This is an early alpha release and will continue to evolve, but the foundation is already in place.

GitHub: https://github.com/docmd-io/docmd-search
Documentation: https://docs.docmd.io/search/

SEO Plugin: robots.txt Auto-Generation

The SEO plugin now automatically generates a robots.txt file during the build process if one does not already exist.

Features

  • Smart defaults with User-agent: * and Allow: /
  • Automatic sitemap references when config.url is configured
  • Optional AI crawler controls
  • Existing robots.txt files are never overwritten
{
  "plugins": {
    "seo": {
      "aiBots": false
    }
  }
}

By default AI crawlers are allowed. Setting aiBots: false adds directives for GPTBot, ChatGPT-User, Google-Extended, CCBot and other supported AI crawlers.

Mermaid C4Context Fix

C4Context diagrams now render correctly instead of appearing as blank white boxes.

The issue was caused by a missing SVG namespace generated by Mermaid when rendering C4Context diagrams. docmd now automatically injects the required namespace before parsing, ensuring these diagrams render correctly.

Thanks to @sinsombat for the fix and accompanying test suite.

Config Upgrade Command

A new --upgrade flag has been added to the docmd migrate command.

npx @docmd/core migrate --upgrade

Running the command automatically updates older configuration files to the modern schema.

The following legacy keys are migrated automatically:

Legacy Key Modern Key
projects workspace.projects
siteTitle title
siteUrl / baseUrl url
srcDir / source src
outputDir out
defaultLocale i18n.default

Existing values are preserved during migration.

TOC HTML Entity Decoding

Heading text containing special characters such as <, >, &, and smart quotes now displays correctly in the Table of Contents sidebar.

Previously, these characters appeared as raw HTML entities instead of their intended representation.

Changelog

New Features

  1. Added alpha preview support for semantic search via docmd-search.
  2. Added automatic robots.txt generation to the SEO plugin.
  3. Added search.showFilters to hide the version filter bar above search results.
  4. Added search.showConfidence to display semantic search confidence percentages.
  5. Added right-aligned search result metadata for versions and confidence badges.

Bug Fixes

  1. Fixed Mermaid C4Context diagrams rendering as blank white boxes.
  2. Fixed Live Editor template rendering crash caused by early workspace access.
  3. Fixed HTML entity decoding in the Table of Contents.
  4. Fixed excessive dev server reloads caused by duplicate fs.watch events on macOS.

Improvements

  1. Added docmd migrate --upgrade for automated configuration modernisation.
  2. Restyled the Project Switcher to align with the appearance and language controls.
  3. Config and navigation.json changes now trigger fast targeted rebuilds instead of full restarts.
  4. The dev server now automatically opens the documentation URL in the default browser on startup.

Thanks 💖

Thanks to all contributors, testers, and issue reporters who helped improve this release.

Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd

What's Changed

  • fix(mermaid): resolve C4Context white-page caused by missing xmlns:xlink namespace declaration in #140

Full Changelog: 0.8.4...0.8.5

docmd@0.8.4 🚀 (Deployer V2 for Vercel, Netlify & GH Pages)

Choose a tag to compare

@mgks mgks released this 19 May 13:18

docmd logo

docmd 0.8.4 • Deployer V2

Build production-ready documentation from Markdown in seconds.

✨ Highlights

This release introduces the new Deployer V2 system, alongside improvements to plugin safety, build reliability, and development workflows.

Deployment targets

The deployment engine has been extracted into a dedicated @docmd/deployer package with provider-based deployment targets.

You can now generate deployment files directly for GitHub Pages, Vercel, and Netlify:

docmd deploy --github-pages
docmd deploy --vercel
docmd deploy --netlify

Generated files automatically inherit values from your docmd.config.json, including the output directory, site URL, SPA routing, and Node.js version.

Existing deployment targets for Docker, Nginx, and Caddy continue to work unchanged.

Markdown line breaks

A new markdown.breaks option has been added to docmd.config.json.

Set this to false to disable automatic markdown line breaks and preserve wrapped markdown formatting.

{
  "markdown": {
    "breaks": false
  }
}

Changelog

  1. Deployer: Extracted the deployment engine into @docmd/deployer with native support for GitHub Pages, Vercel, and Netlify targets.
  2. Markdown formatting: Added the markdown.breaks configuration option to control automatic soft-wrap line breaks (#137, #127).
  3. Installer security: Restricted plugin installs to the official npm registry and replaced unsafe shell-based execution paths.
  4. Threads plugin: Disabled raw HTML rendering inside thread comments whilst preserving standard markdown formatting (#136).
  5. Build reliability: The parser and build lifecycle now exit with non-zero status codes on plugin failures, improving CI pipeline behaviour (#134).
  6. Developer experience: Reduced development server noise during hot reloads and added filePath arguments to parser lifecycle hooks (#135).
  7. UI updates: Refined the version switcher with Lucide icons and aligned Project Switcher dropdown styles with the standard theme menus.
  8. Bug fixes: Fixed project-switching cache overlaps, translation fetch issues on noStyle pages, and copy-code icon hover states.

Thanks 💖

Thanks to all contributors, testers, and issue reporters who helped improve this release. Special thanks to security researchers for coordinating responsible disclosures.

Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd

New Contributors

Full Changelog: 0.8.3...0.8.4

docmd@0.8.3 🗂️ (Workspaces & Enhanced Security)

Choose a tag to compare

@mgks mgks released this 16 May 20:45

docmd logo

docmd v0.8.3 is a major architectural update that introduces Workspaces, enabling centralised management of multiple documentation projects. This release also prioritises Security & Stability with hardened rendering across the ecosystem and improved routing reliability.

✨ Highlights

🚀 Workspaces Architecture

The multi-project system has been completely reimagined as Workspaces. You can now manage multiple independent documentation projects from a single root configuration with powerful new capabilities:

  • Global Configuration Cascading: Define your theme, menubar, navigation, and logo at the root to apply them across all projects automatically.
  • Premium Project Switcher: A new slim UI component for seamless navigation between projects, supporting multiple positions (sidebar-top, sidebar-bottom, and options-menu).
  • Flexible Overrides: Projects can selectively override global defaults in their own local configuration.
  • Backward Compatibility: Existing multi-project configurations are automatically normalised to the new workspace schema.

Check complete Workspaces documentation.

🛡️ Enhanced Security & Stability

This release introduces a series of internal improvements to harden the documentation engine and its plugins against edge-case rendering issues:

  • Hardened Rendering: Systematically replaced innerHTML usage with secure DOM APIs (createElement, DOMParser) across the core and plugins.
  • Universal Security Audit: The monorepo Failsafe pipeline now includes a specialised, AST-based security audit to detect and block unsafe DOM patterns (innerHTML, outerHTML, document.write) before any release.
  • Improved Search Safety: Search results now use a more robust rendering pipeline to ensure content is always handled securely.
  • Dev Server Isolation: Enhanced directory traversal protection in the local development server for improved environment isolation.

🛠 Improvements & Fixes

Auto-Designated Index Normalisation

Fixed a bug in the Zero-Config auto-router where files designated as directory indexes (when no index.md is present) failed to render correctly due to a trailing slash mismatch. The engine now correctly normalises these paths, ensuring stable routing and correct index.html generation for all auto-indexed directories.

Routing Stability

Improved path predictability in the Auto-Router to resolve trailing slash inconsistencies in directories without a dedicated index file.

TUI Pipeline & Workspace Build Clarity

Refined the terminal output (TUI) for multi-project Workspace builds. Build logs are now consistently structured into strict sections (Data Indexing, Publishing, etc.) across both standalone and workspace builds, preventing overlapping text, looping spinners, and disconnected status messages.

UI Sidebar Adjustments

Fixed a layout bug where dropdown menus (Version, Language, and Project Switchers) inside the sidebar would get cropped by the sidebar's bounding box. These menus now securely render over the main content area and dynamically align to the sidebar width, preventing them from overflowing the browser viewport.

📦 Package Updates

  • Node.js Types: Updated @types/node to v25.8.0.
  • GitHub Actions: Updated CI/CD workflows to latest stable versions for improved reliability.

📝 Complete Changelog

🚀 New Features

  • Core Engine: Introduced workspace schema for centralised project management.
  • UI Components: Added project-switcher partial and event delegation logic.
  • Config Loader: Implemented global default merging and menubar item aliasing (title/path).
  • Pipeline: Integrated a static-analysis Security Audit into the Universal Failsafe V5.0 to enforce strict DOM safety standards across all packages.

🐛 Bug Fixes

  • Threads Plugin: Hardened comment rendering and metadata escaping by moving to DOMParser.
  • Search Plugin: Improved results rendering and data attribute safety, replacing innerHTML.
  • Icon Renderer: Hardened icon attribute rendering for SVG icons.
  • Tabs Component: Improved attribute safety in tab navigation items.
  • Core Engine: Fixed path normalisation for auto-designated index files in the generator.
  • Routing: Removed implicit index designation in the Auto-Router to improve path predictability.
  • Dev Server: Enhanced path validation for static file serving.
  • UI Assets: Removed overflow: hidden from sidebar and refactored positioning contexts to prevent cropped dropdown menus.
  • CLI / TUI: Fixed dangling status messages and unclosed UI sections during workspace and dev builds.

Infrastructure

  • Refactoring: Renamed workspace engine to workspace.ts and refactored terminology across the monorepo.
  • Dependencies: Bumped @types/node from 25.7.0 to 25.8.0.
  • Workflows: Updated GitHub Actions group to latest versions.

📥 Upgrade

npm install -g @docmd/core

What's Changed

  • fix(core): strip trailing slash from _sourceFile in navDesignatedIndexFiles by @sinsombat in #131
  • fix(core): remove implicit file-promotion + clean dev output + full rebuild on watch by @sinsombat in #133

New Contributors

Full Changelog: 0.8.2...0.8.3

docmd@0.8.2 🩹 (Patch Release)

Choose a tag to compare

@mgks mgks released this 14 May 15:11

docmd logo

This is a critical patch release that resolves installation issues for users using npm and standardises the monorepo's internal dependency resolution.

🚀 Highlights

Fixed npm install Compatibility

Resolved a critical issue where packages published to the NPM registry contained unresolved workspace: protocol references in their optionalDependencies. This caused npm install to fail with an EUNSUPPORTEDPROTOCOL error. The publishing pipeline has been updated to ensure all dependency types are correctly resolved to semver ranges.

🛠 Improvements & Fixes

  • Publishing Pipeline: Fixed scripts/resolve-ws-deps.js to correctly transform optionalDependencies during the release process.
  • Dependency Standardisation: Updated all internal package references to ensure consistency across the ecosystem.
  • Workflow Optimisation: Updated GitHub Actions to use stable runner configurations for reliable binary generation.

📦 Package Updates

All packages in the @docmd ecosystem have been bumped to v0.8.2 to ensure full compatibility and lock-step versioning.

For a full list of architectural changes introduced in the v0.8 series, please refer to the v0.8.1 Release Note.

Full Changelog: 0.8.1...0.8.2

docmd@0.8.1 ⚙️ (Pluggable Rust Engine - Preview)

Choose a tag to compare

@mgks mgks released this 14 May 14:31

docmd logo

⚠️ Deprecated: npm install fails due to a packaging defect. Please use v0.8.2 instead.

docmd v0.8.1 introduces a pluggable engine architecture, major improvements to git indexing performance, and important fixes for SPA navigation.

✨ Highlights

Pluggable Engine Architecture (Preview)

docmd now supports a pluggable engine system. The new @docmd/engine-rust package provides a foundation for accelerated I/O operations, designed to work seamlessly with existing plugins.

{
  "engine": "rust"
}

The engine is optional - the default JavaScript engine handles all workloads. The Rust engine provides measurable gains for large repositories (1000+ files) where git indexing and batch file operations dominate build time.

Architecture highlights:

  • Pluggable design: Engines are packages under @docmd/engine-*, following the same pattern as plugins
  • Bundled pre-built binaries: All supported platform binaries are now delivered via a single centralised @docmd/engine-rust-binaries package
  • Lazy loading: Native binaries are only loaded when the engine is explicitly selected
  • Plugin-compatible: Plugins can leverage the engine API for accelerated I/O
  • Automatic fallback: If the native binary isn't available, the JS engine takes over transparently

Available engine packages:

Package Description
@docmd/engine-js Default JavaScript engine (always available)
@docmd/engine-rust Rust engine loader (orchestrates native acceleration)
@docmd/engine-rust-binaries Centralised native binary distribution for all platforms

Note: The Rust engine is in preview. In the initial v0.8.1 rollout, pre-compiled native binaries are exclusively published for macOS ARM64 (Apple Silicon) platforms within the binaries package. Builds executed on other architectures automatically and transparently fallback to the high-performance JS engine. Internal benchmarks show a ~25% improvement on cold builds and ~17% on warm builds for an 886-page multi-project site.

Git Indexing: Persistent Disk Cache

The git plugin now persists indexing results to disk across builds. Previously, git metadata was re-indexed from scratch on every build - even when no files had changed. The new cache system:

  • Routes cache storage cleanly to your operating system's isolated temporary directory (os.tmpdir()), preventing top-level directory clutter.
  • Secures cache retrieval persistently across directory renames or moves by generating a robust hash anchored to your repository's Git tracking URL or unique OS inode identifiers.
  • Supports configurable storage paths via the new tmp configuration parameter.
  • Works with both engine paths (Rust and JS) and the execFile fallback.
  • Provides ~45% faster warm builds on the official documentation site (886 pages).

Configurable tmp Directory

By default, docmd now routes internal state and build caches to your system's isolated temporary folder to keep your project root clean. For environments that require persistent caching in specific locations (e.g., CI/CD pipelines with cache-key requirements), you can now configure the full storage path using the new tmp key:

{
  "src": ".",
  "out": "site",
  "tmp": ".docmd-cache"
}

This allows you to anchor the .docmd/ state folder to any directory, ensuring it can be easily cached and restored across build sessions. As suggested in #124

JSON Configuration Standard

Starting with v0.8.0, docmd.config.json is the recommended configuration format. All v0.8 documentation has been updated to use JSON examples. The .js and .ts formats remain fully supported as fallbacks for dynamic configuration logic.

🐛 Bug Fixes

External Links in SPA Navigation

Fixed an issue where external links defined in navigation.json with external: true were incorrectly resolved as relative paths after navigating to another internal page via the SPA router. The links now correctly preserve their absolute URLs during client-side navigation.

Navigation External Link Shorthand

The external: prefix, previously available only in Markdown content, now works in navigation.json as a convenient shorthand:

[
  { "title": "GitHub", "path": "external:https://github.com/docmd-io/docmd" }
]

This is equivalent to:

[
  { "title": "GitHub", "path": "https://github.com/docmd-io/docmd", "external": true }
]

Git Cache Directory Stability & Relocation

Fixed a bug where the git plugin's disk cache was written to shifting directories during multi-project builds. The cache has been cleanly relocated out of the project root directory directly into os.tmpdir() using a persistent repository identifier, fully supporting the custom tmp override path parameter.

Engine Configuration Respected

The git plugin now respects the engine configuration key. Previously, it always attempted to load the Rust engine first regardless of configuration. Setting "engine": "js" now correctly forces the JavaScript engine.

📝 Complete Changelog

🚀 Engine & Architecture

  • Pluggable Engine System: New Engine interface in @docmd/api for build acceleration
  • JS Engine Package: Default engine extracted to @docmd/engine-js
  • Rust Engine Ecosystem: Native Rust acceleration with centralised binary distribution via @docmd/engine-rust-binaries
  • Engine Loader API: loadEngine() and registerEngine() for custom engine registration
  • Engine Config Key: New engine key in docmd.config.json to select build engine
  • Engine Prominence: Elevated top-level logging prominence for custom build engines inside TUI layouts

⚡ Performance

  • Git Disk Cache: Engine-path results now persisted to disk for warm builds
  • Persistent Identification: Dual-mode cache identification using Git remote URL hashing and OS inode fallback
  • Configurable Storage: Added support for overriding cache destination via the tmp config parameter
  • Config Resolvers: Added seamless detection support for standard JSON config files in multi-project sub-project loops
  • Disk Cache Pre-warming: Build pipeline reads disk cache before engine/subprocess calls

🐛 Bug Fixes

  • SPA Router: External links in sidebar navigation now correctly preserved during client-side navigation. Fixed #123
  • Navigation Config: external: prefix now supported as shorthand in navigation.json
  • Link Resolution: Fixed URL resolution edge case for protocol-relative URLs
  • Git Plugin: Now respects the engine configuration key instead of always defaulting to Rust
  • Multi-Project Cache: Relocated state storage to deterministic temporary OS structures to prevent loss between loop boundaries

📥 Upgrade

npm install -g @docmd/core

Full Changelog: 0.8.0...0.8.1

docmd@0.8.0 ⚡ (The Parallel Engine Era)

Choose a tag to compare

@mgks mgks released this 11 May 19:04
8629270

docmd logo

docmd v0.8.0 introduces a new parallel build engine, first-class multi-project support, and major improvements to indexing performance. Large documentation sites can now build significantly faster while maintaining low incremental rebuild latency during development.

✨ Highlights

  • Native multi-threaded build engine with WorkerPool support
  • First-class multi-project documentation builds
  • Persistent Git indexing cache with parallel I/O
  • Worker-thread APIs for plugins
  • TypeScript and JSON configuration support
  • Improved Mermaid diagram controls and fullscreen support

⚡ Benchmarks

This release introduces a new parallel build pipeline, persistent worker pools, and AST caching. Large documentation sites now rebuild significantly faster, with incremental performance continuing to improve across subsequent builds.

docmd < 0.7.9

  • 544 pages
  • ~16s rebuild time on every build
image

docmd 0.8.0+

  • 883 pages
  • ~4.3s rebuild time with persistent optimisation
image

🚀 New Features

Parallel Build Engine

docmd now processes pages in parallel using a native WorkerPool architecture. Markdown parsing and processor hooks can run across multiple CPU cores, significantly reducing build times for large documentation sites.

  • Up to 10x faster builds on large sites
  • Persistent workers during development
  • Automatic CPU-aware thread allocation
  • Reduced incremental rebuild latency

Multi-Project Support

You can now build multiple independent documentation projects into a single site output. This is ideal for monorepos and large documentation ecosystems.

  • Shared output directory across projects
  • Independent versioning and i18n contexts
  • Separate plugin configurations per project
  • Supports unified documentation domains

Plugin Worker API

Plugins can now offload expensive tasks to background threads using the new ctx.runWorkerTask() API.

  • Background processing for indexing and parsing
  • Better main-thread responsiveness
  • Shared WorkerPool support across plugins
  • Available across plugin lifecycle hooks

Persistent Git Indexing

The Git plugin has been redesigned with persistent disk caching and parallel I/O processing.

  • Subsequent indexing reduced from ~18s to ~3.5s on large repositories
  • Automatic pruning for deleted or renamed files
  • Parallel Git metadata syncing
  • Reduced redundant git log operations

SEO-Friendly README Routes

README.md files are now automatically treated as directory indexes.

  • /guide/README.md resolves to /guide/ #117
  • index.md remains the primary priority
  • Clean URL generation for README and index routes

Modern Configuration Support

docmd configuration can now be written in TypeScript or JSON.

  • docmd.config.ts with type-safe defineConfig #115
  • Lightweight docmd.config.json support
  • Improved configuration discovery
  • Fully serialisable resolved config output

Note: We will soon migrate all default configs to .json file type with .ts and .js as fallback.

Better Mermaid Diagrams

The Mermaid plugin now provides a cleaner experience for large diagrams.

  • Zoom and pan controls moved to the bottom-left
  • Improved fullscreen navigation #120
  • Better interaction for oversized diagrams

🛠 Developer & Architecture Changes

Worker Pipeline

  • Added dynamic markdown processor hydration inside worker threads
  • Added MD5-based AST caching for unchanged files
  • Added persistent development worker pools
  • Added CPU-aware worker throttling
  • Added dynamic EventEmitter listener scaling for large builds

Plugin System

  • Added onBeforeBuild lifecycle hook
  • Added ctx.runWorkerTask() across plugin contexts
  • Added worker-thread search indexing support
  • Added persistent Git cache infrastructure
  • Added parallel Git metadata processing

Terminal Interface

  • Added stable in-place TUI progress bars
  • Added plugin-level progress rendering support
  • Improved indexing visibility during builds

Infrastructure

  • Added docmd.config.ts and docmd.config.json discovery
  • Added direct utility exports from @docmd/utils
  • Improved config serialisability across worker boundaries
  • Centralised Git root and branch utilities

⚠️ Breaking Changes

Utility Imports

Custom plugins relying on internal core imports must migrate to @docmd/utils.

Serialisable Hooks

markdownSetup hooks must now be serialisable to support worker-thread execution.

🔄 Migration Guide

Most projects can upgrade without configuration changes.

If you maintain custom plugins:

  • migrate internal imports to @docmd/utils
  • ensure markdownSetup hooks are serialisable

See Building Plugins for a full api walkthrough.

📥 Upgrade

npm install -g @docmd/core

Full Changelog: 0.7.9...0.8.0