Problem
Sometimes you have specific requirements not covered by built-in features. For example, you might need to fetch data from an internal API during the build process or perform complex transformations on the generated HTML.
Why it matters
Extensibility separates a static tool from a professional documentation framework. Without a clean way to inject custom logic, teams maintain fragile shell scripts or post-processing wrappers. This makes the build process difficult to manage and debug.
Approach
docmd features a reliable, hook-based Plugin API. Write simple Node.js modules that intercept the documentation lifecycle at various stages. This allows you to arbitrarily modify content and behaviour from initial configuration to final HTML generation.
Implementation
1. Create a Local Plugin
A plugin is a standard JavaScript module that exports a descriptor and lifecycle hooks.
// plugins/version-injector.js
let latestVersion = "0.0.0";
export default {
// Plugin Descriptor
plugin: {
"name": "version-injector",
"version": "1.0.0",
"capabilities": ["init", "build"]
},
// Lifecycle Hooks
async onConfigResolved(config) {
// Fetch external data once during initialisation
const response = await fetch("https://api.example.com/version");
latestVersion = await response.text();
console.log(`[Plugin] Fetched version: ${latestVersion}`);
},
// Modify HTML before writing
async onBeforeRender(page) {
if (!page.html) return;
page.html = page.html.replace(/\{\{VERSION\}\}/g, latestVersion);
page.frontmatter.computedVersion = latestVersion;
}
};
2. Register the Plugin
Register your local plugin by importing it into your docmd.config.js (or docmd.config.ts). JSON config files cannot use imports - use the .js or .ts format for plugin registration.
import VersionInjector from "./plugins/version-injector.js";
export default {
"title": "My Project Docs",
"plugins": {
// Inject the local plugin object
"version-injector": VersionInjector
}
};
Trade-offs
Custom plugins run in the Node.js environment during build time. While powerful, they can impact build performance if unoptimised. Any logic in hooks like onAfterParse or onPageReady runs for every page in your site. Ensure your transformations are efficient (e.g., using optimised Regex) to keep build times fast.