# docmd docs - Full Context > Generated by docmd --- ## [Browser API (Client-Side)](https://docs.docmd.io/04/advanced/browser-api/) --- title: "Browser API (Client-Side)" description: "How to use the docmd engine directly in the browser to render documentation dynamically without a server." --- `docmd` features an **isomorphic core**. This means the exact same engine that builds your static site in Node.js can also run entirely inside a web browser. This is powerful for: * Building **CMS Previews** (Type markdown, see result instantly). * Creating **Playgrounds** (Like [CodePen](https://codepen.io) for docs). * Embedding documentation rendering into existing React/Vue/Angular apps. ## Installation via CDN You don't need to install Node.js. You can simply include the scripts and styles from a CDN like `unpkg` or `jsdelivr`. ```html ``` ## Usage Once the script loads, it exposes a global `docmd` object. ### `docmd.compile(markdown, config)` Compiles Markdown text into a complete HTML document string. **Parameters:** * `markdown` (String): The raw Markdown content. * `config` (Object): Configuration overrides (same structure as `docmd.config.js`). **Returns:** * `String`: The full HTML string (including ``, ``, ``, ``). ### Example: Live Preview Iframe The safest way to render the output is inside an ` ``` ## Advanced: Raw Content (No-Style) If you only want the HTML content *without* the `docmd` sidebar, header, or footer (for example, to inject into a `div` on your own site), use the `noStyle` frontmatter option in your input. ```javascript const markdown = `--- noStyle: true components: css: true --- # Just Content This will render without the sidebar layout.`; const html = docmd.compile(markdown, { /* config */ }); ``` ## Limitations The Browser API has a few limitations compared to the Node.js CLI: 1. **No File System Access:** It cannot scan folders to auto-generate navigation. You must provide the `navigation` array explicitly in the config object if you want a sidebar. 2. **Plugins:** Some Node.js-specific plugins (like Sitemap generation) will not run. However, client-side plugins (like Mermaid diagrams) work perfectly. --- ## [Client-Side Events](https://docs.docmd.io/04/advanced/client-side-events/) --- title: Client-Side Events description: Hook into the docmd SPA router for custom interactive features. --- `docmd` uses a lightweight Single Page Application (SPA) router to provide instant page transitions. Because the page does not fully reload when navigating, standard `DOMContentLoaded` scripts might not trigger on subsequent page views. To solve this, `docmd` dispatches a custom event called `docmd:page-mounted` whenever a new page renders. ## The `docmd:page-mounted` Event You can listen for this event in your custom JavaScript files to re-initialise libraries or trigger custom logic. ### Usage Create a custom script (e.g., `assets/js/my-plugin.js`) and add it to your `docmd.config.js` under `customJs`. ```javascript document.addEventListener('docmd:page-mounted', (e) => { console.log('New page loaded:', e.detail.url); // Re-initialise your libraries here // Example: MathJax.typeset(); }); ``` ### Event Detail The event object contains a `detail` property with the following data: | Property | Type | Description | | :--- | :--- | :--- | | `url` | `string` | The full URL of the page that just loaded. | | `initial` | `boolean` | `true` if this is the first initial load, `undefined` on navigation. | ## Example: Integrating MathJax If you want to use MathJax for LaTeX equations, standard integration won't work with SPA navigation. Use the event listener: ```javascript // assets/js/math-support.js (function() { // 1. Load MathJax (if not using CDN in head) // ... // 2. Define the render function function renderMath() { if (window.MathJax) { window.MathJax.typesetPromise(); } } // 3. Hook into events document.addEventListener('DOMContentLoaded', renderMath); document.addEventListener('docmd:page-mounted', renderMath); })(); ``` --- ## [Programmatic API](https://docs.docmd.io/04/advanced/node-api/) --- title: "Programmatic API" description: "Programmatic API for building docmd sites from your own scripts." --- You can use `docmd` programmatically inside your own Node.js scripts or task runners (Gulp, Grunt, custom CI). ## Installation ```bash npm install @docmd/core ``` ## Usage ```javascript const { build, buildLive } = require('@docmd/core'); async function generateDocs() { try { console.log('Starting build...'); // 1. Build the Static Site await build('./docmd.config.js', { isDev: false, // true = enables hot-reload logic (internal) offline: false // true = optimise links for file:// access }); console.log('Static site generated in ./site'); // 2. Build the Live Editor (Optional) // Generates the browser-based editor bundle in ./dist await buildLive({ serve: false // true = starts local server, false = build only }); } catch (error) { console.error('Build failed:', error); process.exit(1); } } generateDocs(); ``` --- ## [CLI Commands](https://docs.docmd.io/04/cli-commands/) --- title: "CLI Commands" description: "A complete reference guide to the docmd command-line interface and its available options." --- The Command Line Interface (CLI) is the primary way you will interact with `docmd` while building and testing your documentation. ## `docmd init` Initialises a new `docmd` project in your current directory. **Usage:** ```bash docmd init ``` This command safely generates the necessary boilerplate to get you started without overwriting existing files. It creates: * A `docs/` folder containing a sample `index.md` file. * An `assets/` folder structure for your custom CSS, JS, and images. * A modern `docmd.config.js` file pre-filled with sensible defaults. * A `package.json` file with standard build scripts. ## `docmd dev` Starts a local development server with hot-reloading. **Usage:** ```bash docmd dev [options] ``` This is the command you will use most often. It builds your site into memory, starts a local web server (usually at `http://localhost:3000`), and watches your `docs/` folder and config file. Whenever you save a file, it instantly rebuilds the changes and triggers a live reload in your browser. **Options:** * `-c, --config `: Specify a custom path to your configuration file (defaults to `docmd.config.js`). * `-p, --port `: Force the server to start on a specific port. If the port is busy, `docmd` will ask if you want to try the next available one. ## `docmd build` Compiles your Markdown files into a production-ready static website. **Usage:** ```bash docmd build [options] ``` This command reads your source directory, processes all Markdown and assets, minifies CSS/JS, and outputs a complete static website into your `site/` folder (or whatever you defined as your `outputDir`). The resulting folder can be uploaded to any static web host. **Options:** * `-c, --config `: Specify a custom configuration file. * `--offline`: Optimises the generated HTML links to end in `/index.html` so the site can be browsed directly from a local hard drive without a web server (using `file:///` protocols). ## `docmd migrate` Upgrades an older configuration file to the newest architecture. **Usage:** ```bash docmd migrate ``` If you are upgrading from an older version of `docmd` that used a "flat" configuration structure, this command will intelligently rewrite your config file to the modern layout. * It creates a safe backup named `docmd.config.legacy.js`. * It maps your old settings into the new `layout`, `optionsMenu`, and `footer` objects. * It preserves your existing plugins and navigation arrays. ## `docmd live` Builds and launches the browser-based Live Editor. **Usage:** ```bash docmd live [options] ``` This command bundles the core `docmd` engine into a standalone web application. It starts a local server where you can write Markdown in a split-pane view and see the rendered documentation instantly, demonstrating our isomorphic browser engine. **Options:** * `--build-only`: Generates the `dist/` folder containing the Live Editor but does not start the local server. Use this if you want to host the Live Editor itself on a platform like GitHub Pages. ## Global Options These flags can be appended to any command. * `-v, --version`: Displays the currently installed version of `docmd`. * `-h, --help`: Displays help information and available options for the CLI. --- ## [Comparing Documentation Tools](https://docs.docmd.io/04/comparison/) --- title: "Comparing Documentation Tools" description: "See how docmd stacks up against Docusaurus, MkDocs, Mintlify, and other documentation generators." --- Choosing the right tool depends on your team's workflow and your project's scale. `docmd` was engineered to fill a specific gap: the space between "too simple" (basic Markdown parsers) and "too heavy" (full React/framework applications). ## Feature Matrix Here is how `docmd` compares to the industry standards across key metrics. | Feature | docmd | Docusaurus | MkDocs (Material) | Mintlify | | :--- | :--- | :--- | :--- | :--- | | **Core Architecture** | Node.js (Isomorphic) | React.js | Python | Proprietary | | **Navigation** | **Instant SPA** | React SPA | Page Reloads | Hosted SPA | | **Client JS Payload** | **Tiny (< 20kb)** | Heavy (> 200kb) | Minimal | Medium | | **Search Engine** | **Built-in (Offline)** | Algolia (Cloud) | Built-in (Lunr) | Built-in (Cloud) | | **Custom Containers** | **Deep Nesting** | MDX / React | Admonitions | MDX | | **Setup Time** | **< 1 minute** | ~15 mins | ~10 mins | Instant | | **Browser API**| **Yes (Live Editor)** | No | No | No | | **Cost** | **Free OSS** | Free OSS | Free OSS | Freemium | ## The docmd Advantage If you are trying to decide if `docmd` is right for you, here are the three areas where it truly shines. ### 1. The "Isomorphic" Engine Unlike Docusaurus or MkDocs, which are strictly "Build Tools" that must run on a server or CI/CD pipeline, `docmd` has a modular core. You can run the exact same `docmd` compilation engine directly inside a web browser. This enables features like our Live Editor, allowing you to build CMS interfaces or live preview tools for your users without needing a backend server. ### 2. Privacy-First, Offline Search Most documentation generators push you toward third-party services like Algolia DocSearch. While Algolia is fantastic for enterprise scale, it requires API keys, crawler configurations, and sends user search data to external servers. `docmd` includes a production-grade search engine out of the box. It generates a highly optimised local index during the build. This means your documentation is searchable even if the user loses their internet connection, and respects user privacy completely. ### 3. Pure HTML + SPA Speed We believe reading documentation shouldn't require downloading a massive JavaScript framework. When you build a `docmd` site, it generates pure, semantic HTML. This results in perfect SEO and instant initial page loads. However, once the page is open, our lightweight client-side router takes over. Clicking links feels exactly like a modern React or Next.js app-content swaps instantly without the browser ever flashing or reloading. ## When to choose something else We are proud of what `docmd` does, but it isn't for everyone. * **Choose Docusaurus if:** You need to embed highly interactive, custom React components directly inside your Markdown files, or if you are building a massive corporate portal with extreme internationalization needs. * **Choose MkDocs if:** Your entire engineering team strictly works in Python and you want to utilize the existing Python plugin ecosystem. --- ## [General Configuration](https://docs.docmd.io/04/configuration/general/) --- title: "General Configuration" description: "Configure the core settings, layout, and appearance of your docmd site." --- The `docmd.config.js` file is the heart of your project. It exports a JavaScript object that controls everything from your site title to the footer layout. ## Core Metadata These settings define the identity of your site. ```javascript const { defineConfig } = require('@docmd/core'); module.exports = { siteTitle: 'My Project', siteUrl: 'https://mysite.com', // Important for SEO & Sitemap plugins srcDir: 'docs', // Default: 'docs' outputDir: 'site', // Default: 'site' // Branding logo: { light: 'assets/logo-dark.png', // Shown in light mode dark: 'assets/logo-light.png', // Shown in dark mode href: '/', // Link destination alt: 'Project Logo' }, favicon: 'assets/favicon.ico' } ``` ## Layout Architecture `docmd` (v0.4.8+) uses a nested `layout` object to organise UI components. ```javascript layout: { // 1. Single Page Application Router // Enables seamless page transitions without refresh. spa: true, // 2. Header Configuration header: { enabled: true }, // 3. Sidebar Configuration sidebar: { collapsible: true, // Adds the toggle button to header defaultCollapsed: false // Initial state }, // 4. Options Menu (Search, Theme, Sponsor) // Consolidates utility buttons into one location. optionsMenu: { position: 'header', // 'header' or 'sidebar-bottom' components: { search: true, themeSwitch: true, sponsor: 'https://github.com/sponsors/my-name' } }, // 5. Footer Configuration footer: { style: 'complete', // 'minimal' or 'complete' copyright: '© 2026 My Project', description: 'Documentation built with docmd.', // Only used if style is 'complete' columns: [ { title: 'Resources', links: [ { text: 'Guide', url: '/guide' }, { text: 'API', url: '/api' } ] } ] } } ``` ## Theme & Styles Control the visual appearance. ```javascript theme: { name: 'default', // 'default', 'sky', 'ruby', 'retro' defaultMode: 'system', // 'light', 'dark', or 'system' codeHighlight: true, // Enable syntax highlighting // Array of paths relative to outputDir customCss: ['assets/css/custom.css'] } ``` ## Feature Toggles Disable specific features if you don't need them. ```javascript // Global Feature Flags minify: true, // Minify HTML/CSS/JS in production autoTitleFromH1: true, // Use first # Heading as title if frontmatter missing copyCode: true, // Show copy button on code blocks pageNavigation: true, // Show Next/Prev links at bottom of pages ``` --- ## [Layout & UI Slots](https://docs.docmd.io/04/configuration/layout-slots/) --- title: "Layout & UI Slots" description: "Master the structure of docmd by controlling headers, sidebars, and functional slots." --- `docmd` treats the interface as a series of "Slots." Every major component-from the navigation sidebar to the search bar, can be toggled, moved, or customised to fit your project's specific needs. ## Visual Overview A standard `docmd` page is divided into the following structural areas: 1. **Header:** The top bar containing the title and utility buttons. 2. **Sidebar:** The left-hand navigation and category tree. 3. **Content Area:** The primary Markdown rendering zone. 4. **TOC (Table of Contents):** The right-hand heading navigation. 5. **Footer:** The bottom area for copyright, links, and branding. ## The Header Slot The header is enabled by default. You can disable it site-wide or customise its content. ```javascript // docmd.config.js layout: { header: { enabled: true, // Set to false to hide the entire top bar } } ``` ### Hiding the Page Title in Header By default, the header displays the `title` defined in your page frontmatter. If you prefer to show the title only within the text body (using an `

`), you can hide it in the header on a per-page basis. **In your Markdown file:** ```yaml --- title: "Advanced Guide" hideTitle: true // Hides "Advanced Guide" from the sticky header --- ``` ## Functional "Options Menu" The `optionsMenu` is a unique functional slot that bundles the **Search**, **Theme Toggle**, and **Sponsor** buttons. You have full control over where this bundle appears. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom' components: { search: true, themeSwitch: true, sponsor: 'https://github.com/sponsors/yourname' } } } ``` ## Sidebar & Navigation The sidebar is your project's backbone. It can be made collapsible to give users more reading space. ```javascript layout: { sidebar: { collapsible: true, // Adds the toggle icon to the header defaultCollapsed: false, // Initial state for new visitors position: 'left' // Standard docs layout } } ``` ## The Footer Slot `docmd` offers two footer designs. The choice depends on the scale of your project. ### 1. Minimal Style A single-line footer for copyright and branding. Great for clean, simple projects. ```javascript footer: { style: 'minimal', content: '© 2026 My Project' } ``` ### 2. Complete Style A multi-column footer designed for professional ecosystems. Supports descriptions and categorized links. ```javascript footer: { style: 'complete', description: 'Built with docmd.', columns: [ { title: 'Community', links: [{ text: 'GitHub', url: '...' }] } ] } ``` ## Hiding docmd Branding While we appreciate you sharing the love, you can natively hide the "Built with docmd" badge in the footer for white-label or enterprise projects. ```javascript layout: { footer: { hideBranding: true // Removes the docmd logo/link from the footer } } ``` --- ## [Navigation Configuration](https://docs.docmd.io/04/configuration/navigation/) --- title: "Navigation Configuration" description: "Configure your sidebar links, nested groups, icons, and category labels." --- The sidebar navigation is controlled by the `navigation` array in your `docmd.config.js`. It allows you to define links, nest items into groups, and add visual icons. ## Basic Structure Each item in the array is an object representing a link or a group. ```javascript module.exports = { navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Installation', path: '/guide/install', icon: 'download' } ] } ``` ## Properties | Property | Type | Description | | :--- | :--- | :--- | | **`title`** | `String` | **Required.** Text displayed in the sidebar. | | **`path`** | `String` | Path to the page relative to your `srcDir`. Starts with `/`. | | **`icon`** | `String` | Name of a [Lucide](https://lucide.dev/icons) icon (e.g., `rocket`, `settings`). | | **`children`** | `Array` | An array of nested navigation items. | | **`collapsible`**| `Boolean` | If `true` (on a parent), allows the user to expand/collapse the group. | | **`external`** | `Boolean` | If `true`, opens the link in a new tab. | ## Grouping & Nesting You can nest items infinitely. Groups can be either **Clickable Pages** or **Static Labels**. ### 1. Clickable Parent (Folder Page) If you provide a `path` to a parent item, clicking it will take the user to that page *and* expand the menu. ```javascript { title: 'Guides', path: '/guides/index', // Clicking "Guides" goes here children: [ { title: 'Setup', path: '/guides/setup' } ] } ``` ### 2. Static Label (Category Header) If you **omit the `path`** (or set it to `'#'`), the item becomes a non-clickable category label. This is useful for grouping related links visually. ```javascript { title: 'Advanced Settings', icon: 'settings', // No path defined = Label only children: [ { title: 'Theme Config', path: '/config/theme' }, { title: 'Plugins', path: '/config/plugins' } ] } ``` ## Icons `docmd` includes the full **Lucide** icon set. You can use any icon name (kebab-case) in the `icon` property. * `home` → 🏠 * `book-open` → 📖 * `rocket` → 🚀 * `puzzle` → 🧩 ## External Links You can link to external websites directly from your sidebar. ```javascript { title: 'GitHub Repo', path: 'https://github.com/my-project', icon: 'github', external: true } ``` --- ## [Buttons](https://docs.docmd.io/04/content/containers/buttons/) --- title: "Buttons" description: "Create call-to-action buttons for links, downloads, and external resources." --- Buttons are perfect for "Call to Action" links, such as downloads, sign-ups, or navigating to key sections. ::: callout warning Self-Closing The button container is **self-closing**. Do not add a closing `:::` tag, or it may accidentally close parent containers (like Cards). ::: ## Syntax ```markdown ::: button "Label Text" Link [Options] ``` ## Examples ### Internal Links Use relative paths to link to other pages in your documentation. ```markdown ::: button "Get Started" /getting-started/installation ``` ::: button "Get Started" /getting-started/installation ### External Links Prepend `external:` to the URL to force it to open in a new tab with `target="_blank"`. ```markdown ::: button "View Source" external:https://github.com/docmd-io/docmd ``` ::: button "View Source" external:https://github.com/docmd-io/docmd ### Custom Colours You can customise the button colour using a hex code or CSS colour name. ```markdown ::: button "Critical Action" /delete-account color:#ef4444 ::: button "Success" /confirm color:green ``` ::: button "Critical Action" /delete-account color:#ef4444 ::: button "Success" /confirm color:green --- ## [Callouts](https://docs.docmd.io/04/content/containers/callouts/) --- title: "Callouts" description: "Highlight important information using semantic callout blocks." --- Callouts allow you to highlight specific information that exists outside the normal flow of text. `docmd` supports five semantic types. ## Syntax ```markdown ::: callout type Title Content goes here. ::: ``` If you omit the title, it defaults to the type name (e.g., "Info"). ## Available Types ### Info General information or "Did you know?" boxes. ```markdown ::: callout info Note This is a standard informational callout. ::: ``` ::: callout info Note This is a standard informational callout. ::: ### Tip Best practices and shortcuts. ```markdown ::: callout tip Pro Tip You can nest other containers inside callouts! ::: ``` ::: callout tip Pro Tip You can nest other containers inside callouts! ::: ### Warning Things the user should be careful about. ```markdown ::: callout warning Caution Proceed with care. ::: ``` ::: callout warning Caution Proceed with care. ::: ### Danger Critical warnings, data loss risks, or errors. ```markdown ::: callout danger **Critical Error:** Do not delete the database file. ::: ``` ::: callout danger **Critical Error:** Do not delete the database file. ::: ### Success Confirmation of actions or positive outcomes. ```markdown ::: callout success Build completed successfully! ::: ``` ::: callout success Build completed successfully! ::: --- ## [Cards](https://docs.docmd.io/04/content/containers/cards/) --- title: "Cards" description: "Group content into visually distinct, framed boxes." --- Cards are versatile containers used to group related content. They are excellent for creating grid layouts, feature lists, or summarizing sections. ## Syntax ```markdown ::: card Optional Title Card content goes here. ::: ``` ## Examples ### Basic Card With a title and simple text. ```markdown ::: card Features * Fast Build * Offline Search * No Config ::: ``` ::: card Features * Fast Build * Offline Search * No Config ::: ### Nested Content Cards are structural elements. You can put almost anything inside them, including buttons and code blocks. ````markdown ::: card Download Get the latest version. ```bash npm i -g @docmd/core ``` ::: button "Download Now" /install color:#2563eb ::: ```` ::: card Download Get the latest version. ```bash npm i -g @docmd/core ``` ::: button "Download Now" /install color:#2563eb ::: --- ## [Changelogs](https://docs.docmd.io/04/content/containers/changelogs/) --- title: "Changelogs" description: "Create beautiful, timeline-based version history pages." --- The `changelog` container formats version history into a clean, vertical timeline. It is specifically designed to parse date/version headers and body content separately. ## Syntax Use `==` to separate entries. The text on the `==` line becomes the timeline badge (left side), and the content below becomes the body (right side). ```markdown ::: changelog == Version 2.0 Description of version 2.0. == Version 1.0 Description of version 1.0. ::: ``` ## Example ```markdown ::: changelog == v2.0.0 (2026) ### Major Overhaul We rewrote the core engine for better performance. * Added SPA Router * Added Plugin System == v1.5.0 (2025) ### Maintenance Bug fixes and performance improvements. ::: callout info This was the last version to support Node 14. ::: == v1.0.0 (2024) Initial Release. ::: button "Just Getting Started" # ::: ``` **Rendered Output:** ::: changelog == v2.0.0 (2026) ### Major Overhaul We rewrote the core engine for better performance. * Added SPA Router * Added Plugin System == v1.5.0 (2025) ### Maintenance Bug fixes and performance improvements. ::: callout info This was the last version to support Node 14. ::: == v1.0.0 (2024) Initial Release. ::: button "Just Getting Started" # ::: --- ## [Collapsible](https://docs.docmd.io/04/content/containers/collapsible/) --- title: "Collapsible" description: "Create toggleable accordion sections for FAQs and advanced details." --- The `collapsible` container creates an accordion-style toggle. It is perfect for FAQs, spoilers, or hiding complex configuration options that aren't relevant to every reader. ## Syntax ```markdown ::: collapsible [open] Title Text Content goes here. ::: ``` * **`open`**: (Optional) If present, the section defaults to expanded. * **`Title Text`**: The text shown on the clickable bar. Defaults to "Click to expand". ## Examples ### Default (Closed) Useful for FAQs or spoilers. ```markdown ::: collapsible How do I reset my password? Go to **Settings > Account** and click "Reset Password". ::: ``` ::: collapsible How do I reset my password? Go to **Settings > Account** and click "Reset Password". ::: ### Default (Open) Useful for sections that should be visible but optional to hide. ```markdown ::: collapsible open Prerequisites 1. Node.js v18+ 2. A text editor ::: ``` ::: collapsible open Prerequisites 1. Node.js v18+ 2. A text editor ::: ### Nested Content You can put anything inside a collapsible, including code blocks. ````markdown ::: collapsible View JSON Response ```json { "status": "success", "data": { "id": 123 } } ``` ::: ```` ::: collapsible View JSON Response ```json { "status": "success", "data": { "id": 123 } } ``` ::: --- ## [Custom Containers](https://docs.docmd.io/04/content/containers/) --- title: "Custom Containers" description: "A gallery of the rich UI components available in docmd." --- Standard Markdown is great for text, but sometimes you need more. `docmd` extends Markdown with a set of "Containers" to help you structure complex documentation. Use the syntax `::: container_name` to start a block. ## Nesting Thanks to our advanced parser, you can nest these containers inside each other infinitely. See [Nested Containers](./nested-containers) for examples. --- ## [Nested Containers](https://docs.docmd.io/04/content/containers/nested-containers/) --- title: "Nested Containers" description: "Learn how to use the advanced nested container system to create complex, interactive documentation layouts with seamless container nesting." --- The advanced nested container system in docmd allows you to create complex, interactive documentation layouts by nesting containers within each other. This powerful feature enables you to build rich, structured content that was previously impossible. ## Nesting Rules ### Best Practices 1. **Logical Structure** - Nest containers in a way that makes logical sense 2. **Readability** - Don't nest too deeply (3-4 levels maximum for readability) 3. **Performance** - Complex nesting is supported but keep it reasonable 4. **Content Organisation** - Use nesting to organise related content 5. **Use the Right Tool** - Use steps for simple sequences, cards/tabs for complex content ### Limitations While `docmd` has improved the parser significantly over the period, there are still logical limits: 1. **Steps inside Tabs:** This is technically difficult to parse in Markdown. We recommend keeping Steps as top-level elements or inside Cards, but not inside Tabs. 2. **Buttons:** Buttons are now **self-closing**. Do not add a `:::` after a button line, or it might close a parent container (like a Card) accidentally. ## Examples ### Cards with Nested Content ```markdown ::: card Installation Guide Here's how to install the application: ::: callout tip Pro Tip Make sure to download the correct version for your platform. ::: ::: button "Download Now" /downloads ::: ``` ::: card Installation Guide Here's how to install the application: ::: callout tip Pro Tip Make sure to download the correct version for your platform. ::: ::: button "Download Now" # ::: ### Tabs with Nested Content ```markdown ::: tabs == tab "Windows" Download the Windows installer (.exe) file. ::: callout tip Make sure to run as administrator for best results. ::: ::: button "Download Windows" /downloads/windows == tab "macOS" Download the macOS package (.pkg) file. ::: callout warning You may need to allow the app in Security & Privacy settings. ::: ::: button "Download macOS" /downloads/macos == tab "Linux" Download the Linux tarball (.tar.gz) file. ::: button "Download Linux" /downloads/linux ::: ``` ::: tabs == tab "Windows" Download the Windows installer (.exe) file. ::: callout tip Make sure to run as administrator for best results. ::: ::: button "Download Windows" # == tab "macOS" Download the macOS package (.pkg) file. ::: callout warning You may need to allow the app in Security & Privacy settings. ::: ::: button "Download macOS" # == tab "Linux" Download the Linux tarball (.tar.gz) file. ::: button "Download Linux" # ::: ### Steps Container with Nested Elements Steps containers are designed for simple, sequential instructions and work well with other containers: ```markdown ::: steps 1. **Download the Application** Get the latest version from our download page. ::: button "Download Now" /downloads 2. **Install the Application** Run the installer and follow the setup wizard. ::: callout tip Pro Tip Check our system requirements page for detailed information. ::: 3. **Configure Settings** Set up your preferences and start using the app. ::: card Configuration - Choose your theme - Set up notifications - Configure integrations ::: ::: ``` ::: steps 1. **Download the Application** Get the latest version from our download page. ::: button "Download Now" # 2. **Install the Application** Run the installer and follow the setup wizard. ::: callout tip Pro Tip Check our system requirements page for detailed information. ::: 3. **Configure Settings** Set up your preferences and start using the app. ::: card Configuration - Choose your theme - Set up notifications - Configure integrations ::: ::: ## Troubleshooting ### Common Issues 1. **Container not rendering** - Ensure proper spacing and syntax 2. **Nested content not showing** - Check for proper closing tags 3. **Performance issues** - Reduce nesting depth if experiencing slowdowns ### Debugging Tips - **Check syntax** - Ensure all containers have proper opening and closing tags - **Verify nesting** - Make sure containers are properly nested - **Test incrementally** - Build complex structures step by step - **Use browser dev tools** - Inspect the generated HTML for issues - **Use the right container** - Steps for simple sequences, cards/tabs for complex content --- ## [Steps](https://docs.docmd.io/04/content/containers/steps/) --- title: "Steps" description: "Create beautiful numbered instruction lists for tutorials." --- The `steps` container transforms a standard ordered list into a visual timeline of instructions. It is designed for "How-to" guides. ## Syntax Wrap a standard numbered list in `::: steps`. ```markdown ::: steps 1. **Step Title** Step description. 2. **Next Step** Description. ::: ``` ## Example ```markdown ::: steps 1. **Initialise Project** Run the init command to scaffold your folder. ```bash docmd init ``` 2. **Start Server** Launch the local dev environment. ```bash docmd dev ``` 3. **Deploy** Upload the `site/` folder. ::: ``` **Rendered Output:** ::: steps 1. **Initialise Project** Run the init command to scaffold your folder. ```bash docmd init ``` 2. **Start Server** Launch the local dev environment. ```bash docmd dev ``` 3. **Deploy** Upload the `site/` folder. ::: ## With Nested Elements You can use other containers inside a step to provide extra context. ```markdown ::: steps 1. **Configure Database** Edit your `.env` file. ::: callout danger Do not commit this file to Git! ::: 2. **Run Migrations** Update the schema. ::: ``` ::: steps 1. **Configure Database** Edit your `.env` file. ::: callout danger Do not commit this file to Git! ::: 2. **Run Migrations** Update the schema. ::: ## Customisation Steps containers automatically apply consistent styling and numbering. The container handles: - **Automatic numbering** - Steps are numbered sequentially - **Consistent spacing** - Proper spacing between steps - **Responsive design** - Works on all screen sizes - **Theme integration** - Matches your site's theme - **Smart list handling** - Only step items get special styling, nested lists remain normal --- ## [Tabs](https://docs.docmd.io/04/content/containers/tabs/) --- title: "Tabs" description: "Organise content into switchable tabbed panes." --- Tabs are essential for showing alternative content (like code snippets for different languages or instructions for different OSs) without cluttering the page. ## Syntax Use `== tab "Name"` to define a new tab pane. ```markdown ::: tabs == tab "Tab 1 Name" Content for tab 1. == tab "Tab 2 Name" Content for tab 2. ::: ``` ## Example ### Code Switching ````markdown ::: tabs == tab "JavaScript" ```javascript console.log("Hello World"); ``` == tab "Python" ```python print("Hello World") ``` ::: ```` **Rendered Output:** ::: tabs == tab "JavaScript" ```javascript console.log("Hello World"); ``` == tab "Python" ```python print("Hello World") ``` ::: ## Lazy Rendering `docmd` is smart. If you put heavy content (like a **Mermaid diagram**) inside a hidden tab, it will wait to render it until the user actually clicks the tab. This keeps your page load fast. ## Best Practices 1. **Clear Labels** - Use descriptive tab names 2. **Consistent Content** - Keep similar content types in each tab 3. **Logical Order** - Arrange tabs in a logical sequence 4. **Not Too Many** - Limit to 5-7 tabs for best usability 5. **Mobile Friendly** - Consider mobile users when organising content ## Nesting Limitations - **Tabs cannot contain tabs** - This prevents infinite recursion - **Steps inside tabs not supported** - Use regular ordered lists instead - **Maximum depth** - While technically unlimited, keep it under 3-4 levels for readability - **Performance** - Very deep nesting may impact rendering performance ::: callout warning Steps Inside Tabs **Steps containers cannot be used inside tabs** due to parsing conflicts. If you need step-by-step instructions within tabs, use regular numbered lists or consider restructuring your content. ::: --- ## [Frontmatter Reference](https://docs.docmd.io/04/content/frontmatter/) --- title: "Frontmatter Reference" description: "The complete guide to page-level metadata and configuration in docmd." --- Frontmatter allows you to override global settings on a per-page basis. It must be written in YAML format at the very top of your Markdown file. ## Core Metadata | Key | Type | Description | | :--- | :--- | :--- | | `title` | `String` | **Required.** Sets the HTML `` and the primary page header. | | `description` | `String` | Sets the meta description for SEO and search results. | | `keywords` | `Array` | A list of keywords for the `<meta name="keywords">` tag. | ## Visibility & SEO | Key | Type | Description | | :--- | :--- | :--- | | `noindex` | `Boolean` | Excludes the page from the search index and search engines. | | `llms` | `Boolean` | Set to `false` to exclude this page from the `llms.txt` file. | | `sitemap` | `Object` | Custom sitemap settings: `priority` (0.0-1.0) and `changefreq` (e.g., `daily`). | ## Page Layout | Key | Type | Description | | :--- | :--- | :--- | | `layout` | `String` | Set to `full` to hide the Table of Contents and use the full width. | | `hideTitle` | `Boolean` | If `true`, the title is hidden from the sticky top header. | | `toc` | `Boolean` | Set to `false` to disable the Table of Contents entirely. | | `bodyClass` | `String` | Adds a custom CSS class to the `<body>` tag of this page. | ## Injection Slots Use these keys to add custom HTML/JS to specific pages without changing your global config. * **`customHead`**: Injects HTML into the `<head>`. * **`customScripts`**: Injects HTML at the very end of the `<body>`. ## No-Style Mode (`noStyle: true`) When `noStyle` is enabled, the docmd layout is removed. You must explicitly opt-in to components: ```yaml --- noStyle: true components: meta: true # Injects SEO tags favicon: true # Injects favicon css: true # Injects docmd-main.css theme: true # Injects theme CSS highlight: true # Injects syntax highlighting scripts: true # Injects docmd-main.js layout: true # Injects the content-area wrapper sidebar: true # Injects the navigation sidebar footer: true # Injects the footer branding: true # Injects the "Built with docmd" badge --- ``` ## Plugin Overrides ### SEO Plugin (`seo`) * `description`: Page-specific social description. * `image`: Social share image URL. * `ogType`: Open Graph type (default: `website`). * `twitterCard`: Twitter card type. * `canonicalUrl`: Sets a custom canonical link. --- ## [Live Preview & Browser Support](https://docs.docmd.io/04/content/live-preview/) --- title: "Live Preview & Browser Support" description: "Run docmd entirely in the browser without a server using the new Live architecture." --- ::: button "Open Live Editor" https://live.docmd.io color:#007bff `docmd` features a modular architecture that separates file system operations from core processing logic. This allows the documentation engine to run **entirely in the browser** (client-side), opening up possibilities for live editors, CMS previews, and zero-latency feedback loops. ## The Live Editor `docmd` comes with a built-in "Live Editor" that demonstrates this capability. It provides a split-pane interface where you can write Markdown on the left and see the rendered documentation on the right - instantly, without a server round-trip. ### Running the Editor Locally To launch the live editor on your machine: ```bash docmd live ``` This command will: 1. Bundle the core logic into `dist/docmd-live.js`. 2. Copy necessary assets (CSS, templates). 3. Start a local static server opening the editor. ### Building for Deployment If you want to host the Live Editor itself on a static hosting provider (so your team can write docs in the browser), you can generate the assets without starting the local server: ```bash docmd live --build-only ``` This creates a `dist/` directory containing: * `index.html`: The editor entry point. * `docmd-live.js`: The bundled engine. * `assets/`: Themes and styles. You can simply upload this `dist/` folder to any static host. ## Embedding docmd in Your Site You can use the browser-compatible bundle to add Markdown preview capabilities to your own applications. ### 1. Include the Script and Assets You need to serve the `docmd-live.js` bundle and the `assets/` folder (which contains themes and styles). ```html <link rel="stylesheet" href="/assets/css/docmd-main.css"> <link rel="stylesheet" href="/assets/css/docmd-theme-sky.css"> <script src="/docmd-live.js"></script> ``` ### 2. Use the API The bundle exposes a global `docmd` object. You can use the `compile` function to transform Markdown into a full HTML page string. ```javascript const markdown = "# Hello World\n\nThis is **live** documentation."; const config = { siteTitle: 'My Live Doc', theme: { name: 'sky', defaultMode: 'light' } }; // Compile returns the full HTML string including <head>, <body>, etc. const html = docmd.compile(markdown, config, { // Optional: Help the renderer resolve relative paths relativePathToRoot: './' }); // Inject into an iframe or DOM element document.getElementById('preview-frame').srcdoc = html; ``` ## Important Resources - Check out the [Browser API Guide](/advanced/browser-api/). - [Node API](/advanced/node-api/) for embedded documentation. --- ## [docmd : No-Style Page Example](https://docs.docmd.io/04/content/no-style-example/) --- title: "docmd : No-Style Page Example" description: "An example of a page using the no-style feature" noStyle: true components: meta: true favicon: true css: true theme: true scripts: true mainScripts: true copyCode: true customHead: | <style> body { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; margin: 0; padding: 0; line-height: 1.6; } .container { max-width: 800px; margin: 0 auto; padding: 40px 20px; } .header { text-align: centre; margin-bottom: 40px; } .header h1 { font-size: 3rem; margin-bottom: 10px; color: #4a6cf7; } .header p { font-size: 1.2rem; color: #666; } .content { background-color: #f8f9fa; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); } .button { display: inline-block; padding: 12px 24px; background-color: #4a6cf7; color: white; text-decoration: none; border-radius: 4px; font-weight: 600; margin-top: 20px; } .button:hover { background-color: #3a5ce4; } [data-theme="dark"] { color-scheme: dark; } [data-theme="dark"] body { background-color: #121212; color: #e0e0e0; } [data-theme="dark"] .content { background-color: #1e1e1e; box-shadow: 0 2px 10px rgba(0,0,0,0.2); } [data-theme="dark"] .header p { color: #aaa; } </style> bodyClass: "no-style-example" --- <div class="container"> <div class="header"> <h1>No-Style Page Example</h1> <p>This page demonstrates the no-style feature with a custom layout</p> </div> <div class="content"> <h2>What is this page?</h2> <p> This is an example page that uses the <code>noStyle: true</code> frontmatter option to create a completely custom page layout. Unlike regular documentation pages, this page doesn't use the standard docmd layout with sidebar navigation and table of contents. </p> <h2>How does it work?</h2> <p> The <code>noStyle</code> option tells docmd to use a special template that only includes the components you explicitly request via the <code>components</code> object in frontmatter. This gives you complete control over the page structure. </p> <h2>Features enabled on this page:</h2> <ul> <li><strong>meta</strong>: Meta tags, title, and description for SEO</li> <li><strong>favicon</strong>: The site favicon</li> <li><strong>css</strong>: Basic CSS for markdown content</li> <li><strong>theme</strong>: Theme support for light/dark mode</li> <li><strong>scripts</strong>: JavaScript for functionality</li> </ul> <h2>Custom styling</h2> <p> This page includes custom CSS in the <code>customHead</code> frontmatter field. This allows you to define page-specific styles without affecting the rest of your site. </p> <a href="/content/no-style-pages/" class="button">Get Back to No-Style Pages Documentation</a> </div> </div> --- ## [No-Style Pages](https://docs.docmd.io/04/content/no-style-pages/) --- title: "No-Style Pages" description: "Create landing pages and custom layouts by disabling the default docmd theme." --- Sometimes you need a page that doesn't look like documentation - for example, a Marketing Landing Page, a Login screen, or a completely custom showcase. `docmd` allows you to disable the standard layout (Sidebar, Header, Footer) on a per-page basis using **Frontmatter**. ## Enabling No-Style Add `noStyle: true` to your page's frontmatter. ```yaml --- title: "Welcome" noStyle: true components: meta: true # Keep SEO meta tags favicon: true # Keep the site favicon scripts: false # Disable docmd's main JS (optional) --- <!-- Write raw HTML or Markdown below --> <div class="hero-section"> <h1>My Product</h1> <p>The future of something amazing.</p> </div> ``` ## Controlling Components When `noStyle` is active, `docmd` gives you a blank canvas. You can selectively re-enable specific parts of the system using the `components` object: | Component | Default (in noStyle) | Description | | :--- | :--- | :--- | | `meta` | `false` | Injects `<title>`, `<meta name="description">`, and SEO tags. | | `favicon` | `false` | Injects the favicon link. | | `css` | `false` | Injects `docmd-main.css` (useful if you want to use grid/typography but not layout). | | `theme` | `false` | Injects the active theme CSS (e.g., Sky, Retro). | | `scripts` | `false` | Injects `docmd-main.js` (needed for toggle buttons, copy code, etc). | ## Example: Marketing Landing Page ```yaml --- title: "Home" noStyle: true components: meta: true favicon: true css: true customHead: | <style> .hero { text-align: centre; padding: 100px 20px; } .hero h1 { font-size: 3rem; margin-bottom: 20px; } </style> --- <div class="hero"> <h1>Build Faster.</h1> <p>The ultimate developer tool.</p> ::: button "Get Started" /docs/intro color:blue </div> ``` --- ## [Advanced Syntax](https://docs.docmd.io/04/content/syntax/advanced/) --- title: "Advanced Syntax" description: "Beyond the basic syntax, docmd supports a variety of advanced Markdown features to help you create richer documentation." --- ## GFM (GitHub Flavored Markdown) docmd supports GitHub Flavored Markdown extensions including: ### Task Lists Create interactive checklists: ```markdown - [x] Completed task - [ ] Incomplete task - [ ] Another item ``` - [x] Completed task - [ ] Incomplete task - [ ] Another item ### Autolinked References URL and email addresses are automatically linked: ```markdown Visit https://docmd.io for more information. Contact support@example.com for help. ``` ### Emojis Use emoji shortcodes: ```markdown I :heart: docmd! :rocket: :smile: ``` > I :heart: docmd! :rocket: :smile: ## Custom Attributes (IDs and Classes) You can add custom IDs and CSS classes to headers, images, and links using curly braces `{}`. ### Custom IDs ```markdown ## My Header {#custom-id} ``` ### Custom Classes You can assign classes to elements. **Note:** You must define these classes in your own [Custom CSS](/theming/custom-css-js) file. ```markdown ## Styled Header {.text-centre .text-red} ``` ### Links and Buttons ```markdown [Download Now](/download){.docmd-button} ``` ## Footnotes You can add footnotes to your content for references or additional information[^1]. ```markdown Here's a statement that needs citation[^1]. [^1]: This is the footnote content. ``` Multiple footnotes can be used throughout your document[^2], and the definitions can be collected at the bottom. [^1]: This is the first footnote reference. [^2]: This is the second footnote with more information. ## Definition Lists Some Markdown parsers support definition lists: ```markdown Term : Definition for the term. : Another definition for the same term. Another Term : Definition of another term. ``` Term : Definition for the term. : Another definition for the same term. Another Term : Definition of another term. ## Abbreviations You can define abbreviations in your Markdown (depending on plugin support): ```markdown *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium HTML is defined by the W3C standards. ``` *[HTML]: Hyper Text Markup Language *[W3C]: World Wide Web Consortium HTML is defined by the W3C standards. ## Container Extensions Beyond standard Markdown, docmd provides custom containers for enhanced formatting. These are detailed in the [Custom Containers](/content/custom-containers/) guide, and include: ::: callout info Use containers for callouts, cards, and steps to structure your documentation. ::: --- ## [Code Blocks](https://docs.docmd.io/04/content/syntax/code/) --- title: "Code Blocks" description: "How to display code with syntax highlighting, line numbers, and copy buttons." --- `docmd` includes `highlight.js` for automatic syntax highlighting. ## Fenced Code Blocks Wrap your code in triple backticks (` ``` `) and specify the language. ````markdown ```javascript function hello() { console.log("Hello World"); } ``` ```` **Renders as:** ```javascript function hello() { console.log("Hello World"); } ``` ## Copy Button If `copyCode: true` is enabled in your config (default), a copy button will automatically appear on hover in the top-right corner of every code block. ## Supported Languages Common languages include: `javascript`, `typescript`, `html`, `css`, `bash`, `json`, `python`, `java`, `cpp`, `sql`, `yaml`, `markdown`. If you do not specify a language, it will be rendered as a plain text. --- ## [Images & Lightbox](https://docs.docmd.io/04/content/syntax/images/) --- title: "Images & Lightbox" description: "Adding images, galleries, and enabling lightbox zoom effects." --- ## Basic Images Use standard Markdown syntax to embed images. We recommend storing images in your `assets/images/` folder. ```markdown ![Alt Text](../../assets/images/screenshot.png "Optional Title") ``` ## Image Styling You can add classes to images using the attribute syntax `{ .class }` after the image. ### Sizing ```markdown ![Small](../../assets/icon.png){ .size-small } ![Medium](../../assets/preview.png){ .size-medium } ![Large](../../assets/banner.png){ .size-large } ``` ### Alignment ```markdown ![Centred](../../assets/img.png){ .align-centre } ![Right](../../assets/img.png){ .align-right } ``` ### Shadows & Borders ```markdown ![Styled](../../assets/img.png){ .with-shadow .with-border } ``` ![preview with styling](/assets/images/docmd-preview.png){.with-border .with-shadow .size-medium} ### Responsive Images All images in docmd are responsive by default, automatically scaling to fit their container. ## Image Captions Add captions to your images using the figure syntax: ```markdown <figure> <img src="/path/to/image.jpg" alt="Description of image"> <figcaption>This is the caption for the image</figcaption> </figure> ``` ## Image Galleries and Lightbox docmd includes built-in lightbox functionality for image galleries. When users click on an image in a gallery, it opens in a full-screen lightbox view. ## Image Galleries You can group multiple images into a responsive grid using the `image-gallery` class, use `figcaption` for image captioning. This requires raw HTML wrapping. ```html <div class="image-gallery"> <figure> <img src="../../assets/img1.jpg" alt="View 1"> <figcaption>Dashboard View</figcaption> </figure> <figure> <img src="../../assets/img2.jpg" alt="View 2"> <figcaption>Settings View</figcaption> </figure> </div> ``` <div class="image-gallery"> <figure> <img src="/assets/images/docmd-preview.png" alt="Feature 1"> <figcaption>Feature One</figcaption> </figure> <figure> <img src="/assets/images/docmd-preview.png" alt="Feature 2"> <figcaption>Feature Two</figcaption> </figure> </div> ## Lightbox (Zoom) If `mainScripts` is enabled (default), clicking any image in a gallery or any image with the `.lightbox` class will open a full-screen zoom view. ```markdown ![Click to Zoom](../../assets/diagram.png){ .lightbox } ``` ## Image Optimisation Best Practices For optimal performance: 1. **Use appropriate formats**: - JPEG for photographs - PNG for images with transparency - SVG for icons and logos - WebP for better compression (with fallbacks) 2. **Optimise file sizes**: - Compress images before adding them to your documentation - Consider using tools like ImageOptim, TinyPNG, or Squoosh 3. **Provide responsive images**: - Use the HTML `<picture>` element for advanced responsive image scenarios 4. **Specify dimensions**: - Always include width and height attributes to prevent layout shifts --- ## [Markdown Syntax](https://docs.docmd.io/04/content/syntax/) --- title: "Markdown Syntax" description: "Basic formatting guide for docmd: Headings, lists, bold, italic, and more." --- `docmd` uses standard Markdown syntax. This guide covers the essentials for formatting text. ## Text Formatting | Style | Syntax | Example | | :--- | :--- | :--- | | **Bold** | `**text**` or `__text__` | **Bold Text** | | *Italic* | `*text*` or `_text_` | *Italic Text* | | ~~Strikethrough~~ | `~~text~~` | ~~Deleted Text~~ | | `Code` | `` `text` `` | `Inline Code` | ## Common Elements You can use all standard Markdown elements: ### Headings ```markdown # Heading 1 ## Heading 2 ### Heading 3 ... ###### Heading 6 ``` ### Paragraphs Just type text. Separate paragraphs with a blank line. ### Lists * **Unordered:** ```markdown * Item 1 * Item 2 * Nested Item 2a * Nested Item 2b + Item 3 (using +) - Item 4 (using -) ``` * **Ordered:** ```markdown 1. First item 2. Second item 3. Third item 1. Nested ordered item ``` ### Links ```markdown [Link Text](https://www.example.com) [Link with Title](https://www.example.com "Link Title") [Relative Link to another page](../section/other-page/) ``` ::: callout info For internal links to other documentation pages, use relative paths to the `.md` files. `docmd` will convert these to the correct HTML paths during the build. ::: ### Images ::: callout info See [Images & Media](images.md) for more advanced setup. ::: ```markdown ![Alt text for image](/path/to/your/image.jpg "Optional Image Title") ``` ::: callout tip Place images in your `docs/` directory (e.g., `docs/images/`) or a similar assets folder that gets copied to your `site/` output. ::: ### Blockquotes ```markdown > This is a blockquote. > It can span multiple lines. ``` ### Horizontal Rules ```markdown --- *** ___ ``` ### Inline Code ::: callout info See [Code Blocks](code.md) for codeblocks and more advanced setup. ::: ```markdown Use `backticks` for inline code like `variableName`. ``` ### Tables (GFM Style) You can create tables using GitHub Flavored Markdown syntax: ```bash | Header 1 | Header 2 | Header 3 | | :------- | :------: | -------: | | Align L | Centre | Align R | | Cell 1 | Cell 2 | Cell 3 | | Cell 4 | Cell 5 | Cell 6 | ``` | Header 1 | Header 2 | Header 3 | | :------- | :------: | -------: | | Align L | Centre | Align R | | Cell 1 | Cell 2 | Cell 3 | | Cell 4 | Cell 5 | Cell 6 | ## HTML Because `markdown-it` is configured with `html: true`, you can embed raw HTML directly in your Markdown files. However, use this sparingly, as it can make your content less portable and harder to maintain. ```html <div style="color: blue;"> This is a blue div rendered directly from HTML. </div> ``` ::: callout tip For most formatting needs, standard Markdown and `docmd`'s [Custom Containers](../containers/) should suffice. ::: --- ## [Linking & Referencing](https://docs.docmd.io/04/content/syntax/linking/) --- title: "Linking & Referencing" description: "A guide to internal cross-linking, external links, and asset referencing." --- Learn how to connect your pages and link to external resources. ## Internal Page Links To link to another page in your documentation, use the **relative path** to the markdown file. ::: callout info Smart Rewriting `docmd` automatically converts `.md` extensions to valid HTML links during the build. This ensures links work in your code editor (VS Code) AND on the website. ::: **Examples:** | Goal | Syntax | | :--- | :--- | | Link to a file in the same folder | `[Read Guide](guide.md)` | | Link to a file in a subfolder | `[Read Config](configuration/index.md)` | | Link back to parent | `[Go Back](../index.md)` | ## Anchors (Section Linking) You can link to specific headers on a page using the `#slug`. * **Same Page:** `[Jump to Top](#linking--referencing)` * **Other Page:** `[See Installation](../getting-started/installation.md#global-installation)` ## External Links Standard URL syntax works for external sites. ```markdown [Visit Google](https://google.com) ``` **Protocol Links:** * `[Email Support](mailto:help@docmd.io)` * `[Call Us](tel:+123456789)` ## Linking to Assets To allow users to download files (like PDFs) or view raw assets, place them in your `assets/` folder. **Important:** When linking to files in `assets/`, `docmd` will **NOT** strip the extension. ```markdown [Download PDF](../../assets/manual.pdf) [View Raw Config](../../assets/examples/config.js) ``` --- ## [Contributing](https://docs.docmd.io/04/contributing/) --- title: "Contributing" description: "Learn how you can contribute to the development, design, and documentation of docmd." --- First off, thank you for considering contributing to `docmd`! It's people like you that make the open-source community an amazing place to learn, inspire, and create. We welcome contributions of all kinds, from fixing typos to engineering entirely new plugins. ## Ways to Contribute <div class="docmd-container clear-float"> <div class="image-gallery" style="grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));"> ::: card 🐛 Bug Reports Find something that isn't working right? Open an issue on GitHub. Please include your OS, Node version, and steps to reproduce. ::: ::: card ✨ Feature Requests Have an idea to make docmd better? Open an issue and let's discuss it before you start writing code! ::: ::: card 📝 Documentation This very website is built with docmd! You can contribute by fixing typos, improving recipes, or adding clearer examples. ::: ::: card 💻 Code Contributions Want to get your hands dirty? We happily accept Pull Requests for core engine improvements, UI polish, and new features. ::: </div> </div> ## Development Setup `docmd` is built as a **Monorepo** using `pnpm`. Developing it locally requires a specific workflow to ensure all the internal packages (core, UI, themes, plugins) talk to each other correctly. ::: steps 1. **Prerequisites** Ensure you have Node.js (v18+) and [pnpm](https://pnpm.io/installation) installed on your machine. ```bash npm install -g pnpm ``` 2. **Fork and Clone** Fork the repository on GitHub, then clone your fork locally: ```bash git clone https://github.com/YOUR_USERNAME/docmd.git cd docmd ``` 3. **Install Dependencies** Use `pnpm` to install all dependencies and link the monorepo workspaces together. ```bash pnpm install ``` 4. **Running the Dev Server** We use this documentation site (located in the `docs/` folder) as our primary testing ground. To start the development server and watch for changes in both the documentation *and* the core engine: ```bash # Windows (PowerShell) $env:DOCMD_DEV="true"; pnpm run dev # macOS / Linux DOCMD_DEV=true pnpm run dev ``` *Note: Setting `DOCMD_DEV=true` tells the watcher to monitor the internal templates, UI scripts, and engine logic, automatically rebuilding the site when you edit source files.* ::: ## Testing Your Changes Before submitting a Pull Request, you **must** ensure your changes haven't broken the core engine. `docmd` includes a brutal integration testing suite that verifies HTML generation, path resolutions, and SPA configurations. To run the test suite: ```bash pnpm test ``` If the test passes and outputs `✨ ALL SYSTEMS GO`, your code is safe to commit! ## Pull Request Guidelines 1. **Create a Branch:** Always branch off of `main` for your work (e.g., `feat/new-search-ui` or `fix/broken-link`). 2. **Write Clean Code:** Follow the existing coding style. If you are creating a new file in the `packages/` directory, ensure it includes the standard docmd copyright header at the top. 3. **Commit Messages:** We prefer [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) (e.g., `feat: add new button container` or `fix: resolve sidebar scroll issue`). 4. **Open a PR:** Push your branch to your fork and open a Pull Request against our `main` branch. Provide a clear summary of your changes and reference any related issues. ### Copyright Header All source files in `packages/` must include the standard copyright header. If you create a new file, please copy the header from an existing file. ```html /*! * -------------------------------------------------------------------- * docmd : the minimalist, zero-config documentation generator. * * @package @docmd/core (and ecosystem) * @website https://docmd.io * @repository https://github.com/docmd-io/docmd * @license MIT * @copyright Copyright (c) 2025 docmd.io * * [docmd-source] - Please do not remove this header. * -------------------------------------------------------------------- */ ``` ## Code of Conduct Please note that this project operates with a standard Contributor Code of Conduct. By participating in this project you agree to abide by its terms, ensuring a welcoming and respectful environment for everyone. --- ## [Deployment (Deploy Your Website)](https://docs.docmd.io/04/deployment/) --- title: "Deployment (Deploy Your Website)" description: "Learn how to deploy your docmd-generated static site to modern hosting platforms like GitHub Pages, Vercel, and Netlify." --- Because `docmd` generates a pure, standard static site, you can host your documentation literally anywhere that serves HTML files. When you run the build command, `docmd` processes all your Markdown and places the final, production-ready website into your output directory (default: `site/`). ```bash docmd build ``` The contents of this `site/` folder are all you need. Below are guides for deploying to the most popular modern hosting platforms. ::: tabs == tab "GitHub Pages" The most reliable and automated way to deploy to GitHub Pages is using a **GitHub Actions** workflow. This ensures your site rebuilds automatically every time you push changes to your repository. **1. Create the Workflow File** Create a file in your repository at `.github/workflows/deploy-docs.yml` and add the following content: ```yaml name: Deploy docmd to GitHub Pages on: push: branches: ["main"] # Change this if your default branch is 'master' workflow_dispatch: # Allows manual triggers permissions: contents: read pages: write id-token: write jobs: build-and-deploy: runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '22' # docmd requires Node 18+ cache: 'npm' - name: Install docmd run: npm install -g @docmd/core - name: Build site run: docmd build - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ./site # Your configured outputDir - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ``` **2. Configure Repository Settings** Go to your repository settings on GitHub. Navigate to **Pages**, and under "Build and deployment", change the Source to **GitHub Actions**. The next time you push to your `main` branch, your docs will automatically build and publish! == tab "Vercel" Vercel is an excellent platform for hosting static sites with zero configuration. 1. Push your `docmd` project to a Git repository (GitHub, GitLab, Bitbucket). 2. Log in to Vercel and click **Add New > Project**. 3. Import your repository. 4. Vercel usually detects Node.js projects automatically, but ensure the following settings are applied: * **Framework Preset:** `Other` * **Build Command:** `npm install -g @docmd/core && docmd build` * **Output Directory:** `site` 5. Click **Deploy**. == tab "Netlify" Netlify provides a seamless deployment experience for static site generators. 1. Push your `docmd` project to a Git repository. 2. Log in to Netlify and click **Add new site > Import an existing project**. 3. Connect your Git provider and select your repository. 4. Configure the build settings: * **Base directory:** *(Leave empty unless your docs are in a subfolder)* * **Build command:** `npm install -g @docmd/core && docmd build` * **Publish directory:** `site` 5. Click **Deploy site**. == tab "Traditional Web Server" If you are hosting your documentation on a traditional web server (like Apache, Nginx, or an AWS S3 bucket), deployment is as simple as moving files. 1. Run `docmd build` locally or in your CI/CD pipeline. 2. Copy the entire contents of the generated `site/` folder to your web server's public directory (e.g., `/var/www/html/docs`). ::: callout tip SPA Routing `docmd`'s Single Page Application (SPA) router is built to gracefully degrade. You **do not** need to configure complex URL rewrite rules on your server (like you would for React or Vue apps). If a user accesses a URL directly, the static HTML file is served by the server, and the SPA takes over from there. ::: ::: ## Path Configuration (Subdirectories) If you are not hosting your documentation at the root of a domain (e.g., you are hosting it at `https://mycompany.com/docs/` instead of `https://docs.mycompany.com/`), you must ensure your `docmd.config.js` reflects this so assets and relative links resolve correctly. While `docmd` uses highly resilient relative pathing out of the box, always ensure your `siteUrl` is set accurately in your config if you are using plugins like `sitemap` or `seo` that require absolute URLs. --- ## [Basic Usage](https://docs.docmd.io/04/getting-started/basic-usage/) --- title: "Basic Usage" description: "A quick-start guide to initialising a project, writing content, and building your site." --- Once you have `docmd` installed, creating a beautiful documentation site takes only a few minutes. This guide walks you through the standard workflow. ## 1. Initialise the Project Create a new folder for your documentation and navigate into it using your terminal. ```bash mkdir my-docs cd my-docs ``` Run the initialisation command: ```bash docmd init ``` `docmd` will scaffold a ready-to-use project. Your directory will now look like this: ```text my-docs/ ├── assets/ # Place custom images, CSS, and JS here ├── docs/ # Your Markdown files live here │ └── index.md # The homepage of your documentation ├── docmd.config.js # The main configuration file └── package.json # Contains helpful NPM scripts ``` ## 2. Start the Development Server You don't need to build the site blindly. `docmd` includes a blazing-fast development server that updates your browser the moment you save a file. Run the dev command: ```bash docmd dev ``` Open your browser to `http://localhost:3000`. You will see your newly generated documentation site. Keep this server running in your terminal while you work. ## 3. Write Your Content Open the `docs/` folder in your favourite code editor (like VS Code). `docmd` uses standard Markdown. Any `.md` file you create inside the `docs/` folder will automatically be converted into a web page. Try opening `docs/index.md` and changing the `# Welcome` text. When you save the file, your browser will instantly refresh to show the change. ::: callout tip Organising Content You can create subfolders inside `docs/` (e.g., `docs/api/endpoints.md`). `docmd` will automatically mirror this folder structure when generating your website's URLs. ::: ## 4. Configure the Sidebar By default, `docmd` doesn't guess what your navigation should look like. You define it explicitly to maintain perfect control over your users' experience. Open `docmd.config.js` and locate the `navigation` array. You can add new links, create dropdown categories, and assign SVG icons here. ```javascript navigation:[ { title: 'Home', path: '/', icon: 'home' }, { title: 'Guides', icon: 'book', collapsible: true, children:[ { title: 'Quick Start', path: '/quick-start' }, { title: 'Advanced', path: '/advanced' } ] } ] ``` ## 5. Build for Production When you are ready to share your documentation with the world, stop the development server (press `Ctrl + C` in your terminal) and run the build command: ```bash docmd build ``` `docmd` will process all your Markdown, generate an offline search index, minify your assets, and output a highly optimised static website into a new folder called `site/`. You can now upload the contents of that `site/` folder to any web host (GitHub Pages, Netlify, Vercel, or a traditional server). See our [Deployment Guide](/deployment) for specific instructions. --- ## [Installation](https://docs.docmd.io/04/getting-started/installation/) --- title: "Installation" description: "How to install docmd globally or locally using npm, yarn, or pnpm." --- `docmd` is a Node.js package. It requires **Node.js v18.0.0 or higher**. ## Global Installation (Recommended) For most users, installing `docmd` globally provides the best experience. It gives you access to the `docmd` command anywhere in your terminal. ```bash npm install -g @docmd/core ``` **Verification:** Run the following to check if the installation was successful: ```bash docmd --version ``` ## Local Installation If you prefer to keep dependencies scoped to a specific project (useful for CI/CD pipelines or teams), install it as a dev dependency. ```bash # npm npm install -D @docmd/core # pnpm pnpm add -D @docmd/core # yarn yarn add -D @docmd/core ``` **Running commands locally:** When installed locally, you cannot run `docmd` directly. Instead, use your package manager's runner: ```bash npx @docmd/core dev # or pnpm docmd dev ``` ## CDN Installation (Browser Only) ::: callout warning Developer Use Only This method is **not** for building documentation sites. It is for developers who want to embed the `docmd` parsing engine inside another web application (like a CMS or Live Preview tool). ::: If you are building a React/Vue/Vanilla JS app and want to render `docmd` syntax on the fly without a backend, use the browser build: ```html <!-- 1. Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- 2. Engine --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` See the [Browser API](/advanced/browser-api) guide for implementation details. ## Setup Troubleshooting ::: callout warning Permission Errors If you see `EACCES` errors on macOS/Linux during global installation, it means you don't have permission to write to global directories. **Fix:** Run `sudo npm install -g @docmd/core`. ::: ::: callout info Windows Powershell If you receive an error about "running scripts is disabled on this system", run this command in PowerShell as Administrator: `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` ::: --- ## [docmd: The Minimalist Docs Generator](https://docs.docmd.io/04/) --- title: "docmd: The Minimalist Docs Generator" description: "Generate beautiful, lightweight, and blazing-fast documentation sites directly from your Markdown files. Zero clutter, just content." --- ```text _ _ _| |___ ___ _____ _| | | . | . | _| | . | |___|___|___|_|_|_|___| ``` **Generate beautiful, lightweight documentation sites directly from your Markdown files. Zero clutter, just content.** `docmd` bridges the gap between simple static site generators and heavy, framework-driven applications. It processes standard Markdown into highly optimised static HTML, while delivering a buttery-smooth Single Page Application (SPA) experience for your users. ::: button "Get Started" /getting-started/installation ::: button "View on GitHub" external:https://github.com/docmd-io/docmd color:#333 ## Quick Start You can have a beautiful documentation site running locally in under a minute. Requires [Node.js](https://nodejs.org/) installed on your machine. ```bash # 1. Install docmd globally npm install -g @docmd/core # 2. Initialise a new project in your current directory docmd init # 3. Start the local development server docmd dev ``` Open `http://localhost:3000` in your browser. Any changes you make to the files in the `docs/` folder will instantly update on your screen. ## Why choose docmd? We believe writing documentation should be as frictionless as possible. You shouldn't need to configure complex JavaScript frameworks just to publish text. <div class="image-gallery" style="grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));"> ::: card Seamless SPA Navigation We generate static HTML for ultimate SEO and fast initial loads, but once the page is open, `docmd` intercepts navigation to swap content instantly without ever reloading the browser. ::: ::: card Zero Configuration Run `docmd init` and start writing. Our sensible defaults mean you don't have to touch a configuration file unless you want to customise your branding or layout. ::: ::: card Smart Offline Search Built-in full-text search with fuzzy matching and keyword highlighting. It runs entirely in the browser using a generated index, meaning it works perfectly even on air-gapped networks. ::: ::: card Isomorphic Engine `docmd` isn't just a CLI. The exact same rendering engine can run natively inside a web browser, allowing you to embed live documentation previews directly into your own web apps. ::: </div> ## Rich Content Out of the Box Write naturally. `docmd` extends standard Markdown with intuitive, nestable components to help you structure complex information beautifully. ::: tabs == tab "Containers" Easily highlight information using Callouts. ::: callout tip Pro Tip You can nest containers inside each other infinitely. Try putting a button inside a card inside a tab! ::: ::: button "Get Started with docmd" /getting-started/installation == tab "Diagrams" Native support for **Mermaid.js**. Just create a code block with the `mermaid` language tag, and it automatically renders and adapts to your user's Light/Dark mode preference. ```mermaid graph TD A[Start] --> B{Is it working?} B -->|Yes| C[Great!] B -->|No| D[Debug] D --> E[Fix the issue] E --> B C --> F[Deploy] F --> G[End] ``` == tab "Code" Automatic syntax highlighting powered by `highlight.js`, complete with one-click copy buttons and themes tailored for optimal contrast. ```javascript function hello() { console.log("Hello World"); } ``` ::: Ready to dive in? Check out the [Basic Usage](/getting-started/basic-usage) guide or explore how to [Configure](/configuration/) your site. --- ## [Analytics Integration Plugin](https://docs.docmd.io/04/plugins/analytics/) --- title: "Analytics Integration Plugin" description: "Integrate web analytics services like Google Analytics into your docmd site to track visitor traffic." --- `docmd` allows you to easily integrate popular web analytics services into your documentation site using the built-in analytics plugin. This helps you understand your audience, track page views, and gather insights into how your documentation is being used. ## Enabling Analytics Plugin You enable analytics by adding the analytics plugin and its configuration to the `plugins` object in your config file. **Example:** ```javascript module.exports = { // ... plugins: { // Analytics plugin configuration analytics: { // For Google Analytics 4 (GA4) googleV4: { measurementId: 'G-XXXXXXXXXX' // Your GA4 Measurement ID }, // For Google Universal Analytics (Legacy) // googleUA: { // trackingId: 'UA-XXXXXXXXX-Y' // Your Universal Analytics Tracking ID // } }, // ... other plugins }, // ... }; ``` Choose the analytics service and version you want to use by configuring the appropriate section. ## Available Analytics Options ### Google Analytics 4 (GA4) * **Configuration Key:** `googleV4` * **Description:** Integrates the latest version of Google Analytics, GA4. This is the recommended version for new Google Analytics setups. * **Options:** * `measurementId` (String, Required): Your Google Analytics 4 Measurement ID, which typically looks like `G-XXXXXXXXXX`. * **Action:** Injects the standard Google Analytics 4 `gtag.js` tracking snippet into your pages. ### Google Universal Analytics (Legacy) * **Configuration Key:** `googleUA` * **Description:** Integrates the older version of Google Analytics, known as Universal Analytics (UA). Note that Google has sunset Universal Analytics as of July 2023. * **Options:** * `trackingId` (String, Required): Your Google Universal Analytics Tracking ID, which typically looks like `UA-XXXXXXXXX-Y`. * **Action:** Injects the standard Google Universal Analytics `analytics.js` tracking snippet into your pages. ## Important Considerations * **Choose One Google Analytics Version:** If using Google Analytics, configure *either* `googleUA` *or* `googleV4`, but not both for the same property, to avoid incorrect data collection. * **Privacy and Consent:** * Be mindful of user privacy when implementing analytics. * Clearly disclose your use of analytics (and any cookies set by them) in your site's privacy policy or a cookie consent banner if required by regulations in your target regions (e.g., GDPR, CCPA). * Consider features like IP anonymization if your analytics provider offers them and it's appropriate for your privacy stance. * **Testing:** After enabling the analytics plugin and deploying your site, verify that data is being collected correctly in your analytics provider's dashboard. Use browser developer tools (Network tab) to check if the tracking script is loading. ## Future Analytics Support `docmd` may add support for other privacy-focused or popular analytics providers in the future, such as: * Plausible Analytics * Fathom Analytics * Simple Analytics Check the latest `docmd` documentation or GitHub repository for updates on supported analytics integrations. --- ## [Building Plugins](https://docs.docmd.io/04/plugins/building-plugins/) --- title: "Building Plugins" description: "A guide for developers on how to create and share custom docmd plugins." --- Plugins are the primary way to extend `docmd`. They allow you to hook into the Markdown parser, inject HTML into the layout, and run logic after the build completes. ## Anatomy of a Plugin A plugin is simply a JavaScript object (or a function returning an object) that exports specific hook functions. You can define plugins inline in your `docmd.config.js` or create them as separate NPM packages. ### Available Hooks | Hook | Description | | :--- | :--- | | `markdownSetup(md)` | Access the `markdown-it` instance to add rules or plugins. | | `injectHead(config)` | Return HTML string to inject into `<head>`. | | `injectBody(config)` | Return HTML string to inject at the end of `<body>`. | | `getAssets()` | Return a list of CSS/JS files to copy and inject. | | `onPostBuild(context)` | Run logic after the HTML files are generated (e.g., sitemaps). | ## Creating a Local Plugin You can create a plugin file in your project, for example `my-plugin.js`: ```javascript // my-plugin.js module.exports = { // 1. Extend Markdown markdownSetup: (md) => { // Example: Add a custom container or rule // md.use(require('markdown-it-emoji')); }, // 2. Inject Styles/Scripts injectHead: (config) => { return `<meta name="custom-plugin" content="active">`; }, // 3. Post-Build Action onPostBuild: async ({ config, pages, outputDir, log }) => { log('Plugin: Build finished! Processed ' + pages.length + ' pages.'); } }; ``` To use it, require it in your `docmd.config.js`: ```javascript // docmd.config.js module.exports = { // ... plugins: { './my-plugin.js': {} // Key is path, Value is options object } }; ``` ## Plugin API Reference ### `getAssets()` Used to inject client-side scripts or CSS files. ```javascript getAssets: () => { return [ { src: path.join(__dirname, 'client-script.js'), // Source file dest: 'assets/js/plugin.js', // Destination in site/ type: 'js', // 'js' or 'css' location: 'body' // 'head' or 'body' } ]; } ``` ### `onPostBuild({ config, pages, outputDir, log })` * `config`: The full project configuration object. * `pages`: Array of processed page objects `{ outputPath, frontmatter, htmlContent, searchData }`. * `outputDir`: Absolute path to the build output folder. * `log`: Helper function to print messages to the CLI console. ## Publishing a Plugin To share your plugin with the community: 1. Name your package `docmd-plugin-<name>` (recommended). 2. Export the plugin object as the default export. 3. Publish to NPM. Users can then install it via `npm install docmd-plugin-name` and add it to their config: ```javascript plugins: { 'docmd-plugin-name': { /* options */ } } ``` --- ## [LLM Support (llms.txt) Plugin](https://docs.docmd.io/04/plugins/llms/) --- title: "LLM Support (llms.txt) Plugin" description: "Generate context files for Large Language Models (AI) to better understand your documentation." --- The `llms` plugin generates a standardised `/llms.txt` file at the root of your site. This file is becoming a standard for helping AI agents (like ChatGPT, Claude, or Cursor) discover and read your documentation context efficiently. ## Installation This plugin is included in `@docmd/core` but must be enabled in your config. ## Configuration Add `llms` to your `docmd.config.js`: ```javascript module.exports = { siteUrl: 'https://mysite.com', // REQUIRED plugins: { llms: {} // Enable with default settings } }; ``` ### Options Currently, the plugin uses your existing `siteTitle`, `description`, and page frontmatter to generate the file. ### Excluding Pages To prevent a specific page from appearing in the AI context file, add this to the frontmatter: ```yaml --- title: "Internal Draft" llms: false --- ``` ## Output Example The generated `llms.txt` will look like this: ```md # My Project Documentation > Generated by docmd This is the main description of my project. ## Documentation Files - [Installation](https://mysite.com/install) How to install the CLI. - [Configuration](https://mysite.com/config) Reference for config.js options. ``` --- ## [Mermaid Diagrams Plugin](https://docs.docmd.io/04/plugins/mermaid/) --- title: "Mermaid Diagrams Plugin" description: "Create beautiful diagrams and flowcharts using Mermaid syntax in your docmd documentation." --- Mermaid is a JavaScript-based diagramming and charting tool that uses Markdown-inspired text definitions to create and modify diagrams dynamically. docmd has built-in support for Mermaid diagrams with automatic light/dark theme switching. ::: callout tip All Mermaid diagrams automatically adapt to your site's light/dark theme! ::: ## Flowchart Flowcharts are used to represent workflows or processes. They show the steps as boxes of various kinds, and their order by connecting them with arrows. **Code:** ````markdown ```mermaid graph TD A[Start] --> B{Is it working?} B -->|Yes| C[Great!] B -->|No| D[Debug] D --> E[Fix the issue] E --> B C --> F[Deploy] F --> G[End] ``` ```` **Rendered Preview:** ```mermaid graph TD A[Start] --> B{Is it working?} B -->|Yes| C[Great!] B -->|No| D[Debug] D --> E[Fix the issue] E --> B C --> F[Deploy] F --> G[End] ``` ## Sequence Diagram Sequence diagrams show how processes operate with one another and in what order. They capture the interaction between objects in the context of a collaboration. **Code:** ````markdown ```mermaid sequenceDiagram participant User participant Browser participant Server participant Database User->>Browser: Enter URL Browser->>Server: HTTP Request Server->>Database: Query Data Database-->>Server: Return Results Server-->>Browser: HTTP Response Browser-->>User: Display Page ``` ```` **Rendered Preview:** ```mermaid sequenceDiagram participant User participant Browser participant Server participant Database User->>Browser: Enter URL Browser->>Server: HTTP Request Server->>Database: Query Data Database-->>Server: Return Results Server-->>Browser: HTTP Response Browser-->>User: Display Page ``` ## Pie Chart Pie charts are circular statistical graphics divided into slices to illustrate numerical proportions. **Code:** ````markdown ```mermaid pie title Browser Usage Statistics "Chrome" : 64.5 "Safari" : 18.2 "Firefox" : 8.5 "Edge" : 4.8 "Other" : 4.0 ``` ```` **Rendered Preview:** ```mermaid pie title Browser Usage Statistics "Chrome" : 64.5 "Safari" : 18.2 "Firefox" : 8.5 "Edge" : 4.8 "Other" : 4.0 ``` ## Git Graph Git graphs visualize Git branching and merging operations, making it easier to understand version control workflows. **Code:** ````markdown ```mermaid gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop commit branch feature checkout feature commit checkout main merge feature commit ``` ```` **Rendered Preview:** ```mermaid gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop commit branch feature checkout feature commit checkout main merge feature commit ``` ## XY Chart XY charts display data as a series of points on a coordinate plane, useful for showing correlations and trends. **Code:** ````markdown ```mermaid xychart-beta title "Sales Revenue by Quarter" x-axis [Q1, Q2, Q3, Q4] y-axis "Revenue (in $1000)" 0 --> 100 bar [50, 60, 70, 85] line [45, 55, 75, 80] ``` ```` **Rendered Preview:** ```mermaid xychart-beta title "Sales Revenue by Quarter" x-axis [Q1, Q2, Q3, Q4] y-axis "Revenue (in $1000)" 0 --> 100 bar [50, 60, 70, 85] line [45, 55, 75, 80] ``` ## Best Practices When using Mermaid diagrams in your documentation: 1. **Keep it Simple**: Start with simple diagrams and add complexity only when needed 2. **Use Clear Labels**: Make sure all nodes and connections are clearly labeled 3. **Consider Your Audience**: Adjust the level of detail based on who will read the documentation 4. **Test Both Themes**: Always check how your diagrams look in both light and dark modes 5. **Add Context**: Use callouts or text around diagrams to explain what they represent ::: callout info Visit the [Official Mermaid Documentation](https://mermaid.js.org/) for more types of Mermaid Diagrams and, detailed syntax and options. ::: --- ## [Search Plugin](https://docs.docmd.io/04/plugins/search/) --- title: "Search Plugin" description: "Configure the offline-capable, full-text search engine." --- `docmd` includes a privacy-focused, offline-capable search engine powered by `MiniSearch`. It indexes your content at build time, meaning no external services (like Algolia) are required. ## Configuration The search plugin is enabled by default. You can configure it via the `optionsMenu` in the layout config, or the `plugins` object. ### Enabling/Disabling To toggle the search button in the UI: ```javascript // docmd.config.js module.exports = { layout: { optionsMenu: { components: { search: true, // Set to false to hide the search icon } } } } ``` ### Excluding Pages To prevent specific pages (like drafts or utility pages) from appearing in search results, add `noindex: true` to the frontmatter: ```yaml --- title: "Private Draft" noindex: true --- ``` ## How it Works 1. **Build Time:** The plugin scans all generated HTML, strips tags, and extracts headings/text into `site/search-index.json`. 2. **Runtime:** When a user opens your site, the lightweight index is loaded. 3. **Privacy:** All search logic happens locally in the user's browser. No keystrokes are sent to any server. ## Keyboard Shortcuts * `Cmd + K` (Mac) or `Ctrl + K` (Windows): Open Search * `Arrow Up/Down`: Navigate results * `Enter`: Select result * `Esc`: Close modal ## Comparison vs. Algolia Many documentation generators (like Docusaurus) rely on **Algolia DocSearch**. While Algolia is powerful, it introduces friction: | Feature | docmd Search | Algolia / External | | :--- | :--- | :--- | | **Setup** | **Zero Config** (Automatic) | Complex (API Keys, CI/CD crawling) | | **Privacy** | **100% Private** (Client-side) | Data sent to 3rd party servers | | **Offline** | **Yes** | No | | **Cost** | **Free** | Free tier limits or Paid | | **Speed** | **Instant** (In-memory) | Fast (Network latency dependent) | `docmd` creates a frictionless experience: you write the markdown, we handle the discovery. --- ## [SEO & Meta Tags Plugin](https://docs.docmd.io/04/plugins/seo/) --- title: "SEO & Meta Tags Plugin" description: "Configure Search Engine Optimisation (SEO) meta tags to improve your docmd site's discoverability." --- The `seo` plugin automatically generates important meta tags in the `<head>` of your HTML pages. This helps search engines and social media platforms understand, index, and display your content more effectively. ## Enabling the Plugin Add the `seo` plugin to the `plugins` object in your config file: ```javascript module.exports = { // ... plugins: { seo: { defaultDescription: 'Discover insightful articles and guides on Project X. Your go-to resource for learning and development.', openGraph: { // siteName: 'Project X Documentation', // Optional, defaults to config.siteTitle defaultImage: '/assets/images/default-og-image.png', // Absolute path from site root }, twitter: { cardType: 'summary_large_image', // e.g., 'summary', 'summary_large_image' // siteUsername: '@ProjectX_Docs', // Your site's Twitter handle // creatorUsername: '@YourHandle' // Default author handle (override in frontmatter) } }, // ... other plugins }, // ... }; ``` ## Configuration Options The options in the config file serve as site-wide defaults. For the best results, you should provide specific metadata for each page using frontmatter. ## Frontmatter for SEO To control SEO on a per-page basis, add a nested `seo` object to your page's frontmatter. This keeps all SEO-related settings organised and prevents conflicts with other frontmatter keys. ```yaml --- title: "Advanced Widget Configuration" description: "A detailed guide on configuring advanced settings for the Super Widget." seo: description: "A more specific SEO description for search engines, overriding the main description if needed." image: "/assets/images/widgets/super-widget-social.jpg" ogType: "article" twitterCard: "summary_large_image" twitterCreator: "@widgetMaster" keywords: ["widget", "configuration", "advanced", "performance"] permalink: "https://example.com/docs/widgets/advanced-configuration" noindex: false --- ``` ::: callout info Backward Compatibility For backward compatibility, the plugin will still recognise top-level SEO fields like `image`, `ogType`, etc. However, the nested `seo:` structure is the recommended approach. ::: ### Supported Frontmatter Fields All fields should be placed inside the `seo:` object. * `description` (String): Overrides the main page description for SEO meta tags. * `image` or `ogImage` (String): Path to an image for `og:image` and `twitter:image`. * `ogType` (String): Overrides the default Open Graph type (e.g., `article`, `website`). * `twitterCard` (String): Overrides the default Twitter card type for this page. * `twitterCreator` (String): The Twitter @username of the page's author. * `keywords` (Array of Strings or String): Keywords for the `<meta name="keywords">` tag. * `permalink` or `canonicalUrl` (String): The canonical URL for the page. * `noindex` (Boolean): If `true`, adds `<meta name="robots" content="noindex">` to discourage search engines from indexing this page. ## Structured Data (LD+JSON) The SEO plugin can generate [Structured Data](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) (LD+JSON), which can enable rich search results. This feature is enabled per-page in your frontmatter. ### Enabling Structured Data To generate a default LD+JSON block, add `ldJson: true` inside your `seo` frontmatter object. ```yaml --- title: "My Article" description: "An article about something important." seo: ldJson: true --- ``` This generates a basic `Article` schema using your page's metadata. ### Customising Structured Data For more control, provide an object to `ldJson`. This object will be merged with the default data, allowing you to add or override any properties. **Example: Customising schema type and adding an author** ```yaml --- title: "Advanced Widget Configuration" description: "A detailed guide on configuring advanced settings for the Super Widget." seo: image: "/assets/images/widgets/super-widget-social.jpg" ldJson: "@type": "TechArticle" author: "@type": "Person" name: "Jane Doe" url: "https://example.com/authors/jane-doe" datePublished: "2024-01-15" review: "@type": "Review" reviewRating: "@type": "Rating" ratingValue: "5" bestRating: "5" author: "@type": "Person" name: "John Smith" --- ``` In this example, the schema type is changed to `TechArticle`, and detailed `author`, `datePublished`, and `review` information is added, giving search engines a much richer understanding of your content. --- ## [Sitemap Plugin](https://docs.docmd.io/04/plugins/sitemap/) --- title: "Sitemap Plugin" description: "Automatically generate a sitemap.xml for your docmd site to improve search engine discoverability." --- The `sitemap` plugin automatically generates a `sitemap.xml` file for your documentation site. This helps search engines discover, crawl, and index your content more effectively, which can improve your site's visibility in search results. ## Enabling the Plugin Add the `sitemap` plugin to the `plugins` object in your config file: ```javascript module.exports = { // ... plugins: { sitemap: { defaultChangefreq: 'weekly', defaultPriority: 0.8 }, // ... other plugins }, // ... }; ``` ## Configuration Options All options for the `sitemap` plugin are optional. If an option is not provided, the plugin will use sensible defaults. * `defaultChangefreq` (String): * Specifies how frequently the content is likely to change * Possible values: `'always'`, `'hourly'`, `'daily'`, `'weekly'`, `'monthly'`, `'yearly'`, `'never'` * Default: `'weekly'` * `defaultPriority` (Number): * Indicates the relative importance of a page in your site * Value between 0.0 and 1.0 * Default: `0.8` ## How It Works The sitemap plugin automatically: 1. Scans all generated HTML pages during the build process 2. Creates a `sitemap.xml` file in the root of your site output directory 3. Includes all pages with their URLs, last modification dates, and configured priorities The plugin uses your `siteUrl` property from the config file to create absolute URLs, which is required for a valid sitemap. Make sure you have a `siteUrl` defined: ```javascript module.exports = { siteUrl: 'https://yourdomain.com', // No trailing slash // ... other config }; ``` ## Overriding Per-Page Settings with Frontmatter You can override the default sitemap settings for individual pages by adding specific frontmatter properties: ```yaml --- title: "Important Page" description: "This is a very important page that changes frequently" sitemap: changefreq: 'daily' priority: 1.0 --- ``` ## Excluding Pages from the Sitemap If you want to exclude specific pages from the sitemap, you can add the following to your frontmatter: ```yaml --- title: "Private Page" description: "This page should not appear in search engines" sitemap: false --- ``` ## Verifying Your Sitemap After building your site, check the generated sitemap at `your-site/sitemap.xml`. You can also submit the sitemap URL to search engines like Google Search Console or Bing Webmaster Tools to help them discover and index your content more efficiently. --- ## [Extending docmd with Plugins](https://docs.docmd.io/04/plugins/usage/) --- title: "Extending docmd with Plugins" description: "Extend docmd's functionality with built-in integrations." --- Plugins allow you to add complex features to your documentation site - like analytics tracking or AI context generation - without bloating the core engine. All core plugins are bundled with `@docmd/core`. You simply enable them in your `docmd.config.js` file. ## Configuration Plugins are configured inside the `plugins` object. An empty object `{}` usually enables the plugin with its default settings. To disable a plugin, either remove it or set it to `false`. ```javascript module.exports = { // ... plugins: { // Generates Meta Tags and Open Graph data seo: { defaultDescription: 'My documentation site', openGraph: { defaultImage: '/assets/og-image.png' } }, // Injects Google Analytics analytics: { googleV4: { measurementId: 'G-XXXXXXXXXX' } }, // Generates sitemap.xml sitemap: { defaultChangefreq: 'weekly' }, // Enables Mermaid.js diagrams mermaid: {}, // Offline search (Can also be toggled in layout.optionsMenu) search: {}, // Generates an llms.txt file for AI agents llms: {} } }; ``` ## How Plugins Work Plugins in `docmd` hook into various parts of the build process: * They can add meta tags and scripts to the page head * They can inject content or scripts at the beginning or end of the page body * They can generate additional files in the output directory * They can modify the HTML output of pages All plugins are designed to be configurable through your config file, giving you control over their behaviour. Explore the sidebar to see the specific configuration options available for each plugin. --- ## [Recipe: Adding Custom Fonts](https://docs.docmd.io/04/recipes/custom-fonts/) --- title: "Recipe: Adding Custom Fonts" description: "Personalize your documentation by importing Google Fonts." --- `docmd` uses CSS variables to manage typography. Changing your site's font is as easy as creating a custom stylesheet. ## 1. Create a CSS File Create a file in your project (e.g., `assets/css/fonts.css`). Go to [Google Fonts](https://fonts.google.com), find the font you want (like *Inter* or *Fira Code*), and use the `@import` method. Then, assign that font to the docmd root variables. ```css /* assets/css/fonts.css */ /* Import the fonts */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Fira+Code&display=swap'); :root { /* Override the default sans-serif font */ --font-family-sans: "Inter", -apple-system, BlinkMacSystemFont, sans-serif; /* Override the monospace (code block) font */ --font-family-mono: "Fira Code", monospace; } ``` ## 2. Register the Stylesheet Open your `docmd.config.js` and add the path to your new CSS file in the `theme.customCss` array. ```javascript module.exports = { // ... theme: { name: 'sky', defaultMode: 'light', customCss:[ '/assets/css/fonts.css' // Path is relative to the generated site/ root ] } } ``` Restart your `docmd dev` server. Your entire site will now use your custom typography! --- ## [Recipe: Adding a Custom Favicon](https://docs.docmd.io/04/recipes/favicon/) --- title: "Recipe: Adding a Custom Favicon" description: "How to add a custom favicon to your documentation site." --- A favicon is the small icon that appears in the browser tab next to your page title. `docmd` makes it easy to add your own. ## 1. Prepare your image You can use `.ico`, `.png`, or `.svg` files. For the best compatibility, an `.ico` file is recommended. ## 2. Add to Assets Place your image file in your project's assets directory. ```bash # Example structure my-project/ ├── assets/ │ └── my-icon.ico <-- Your file here ├── docs/ └── docmd.config.js ``` ## 3. Update Configuration Open `docmd.config.js` and update the `favicon` property with the path relative to the output root. ```javascript module.exports = { // ... // Points to site/assets/my-icon.ico favicon: '/assets/my-icon.ico', // ... }; ``` ## 4. Build Run `docmd build` (or `docmd dev`). `docmd` will automatically copy your asset file to the site build and link it in the `<head>` of every page. --- ## [Recipe: Creating a Landing Page](https://docs.docmd.io/04/recipes/landing-page/) --- title: "Recipe: Creating a Landing Page" description: "How to build a custom landing page using noStyle." --- Sometimes you want your `index.html` (the home page) to look completely different from your documentation - like a product marketing page. `docmd` makes this easy with **No-Style Pages**. ## The Concept By adding `noStyle: true` to your frontmatter, `docmd` strips away the sidebar, header, and default CSS, giving you a blank canvas while still keeping helpful meta tags. ## Implementation Create or edit `docs/index.md`: ```html --- title: "My Product" description: " The best product ever." noStyle: true components: meta: true # Keep SEO tags favicon: true # Keep favicon scripts: false # Disable default docmd scripts customHead: | <style> body { font-family: sans-serif; margin: 0; } .hero { background: #111; color: #fff; padding: 100px 20px; text-align: centre; } .btn { background: #3b82f6; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; } </style> --- <div class="hero"> <h1>Welcome to My Product</h1> <p>The ultimate solution for X, Y, and Z.</p> <br> <a href="/getting-started/" class="btn">Read the Docs →</a> </div> <div class="features"> <!-- Your custom HTML features grid here --> </div> ``` This page will be built as `index.html` but will look exactly like your custom HTML, serving as a perfect entry point to your documentation. --- ## [Recipe: Documentation Writing Guide](https://docs.docmd.io/04/recipes/writing-guide/) --- title: "Recipe: Documentation Writing Guide" description: "Best practices for writing clear, scannable, and effective documentation with docmd." --- Great documentation isn't just about correct information; it's about how that information is structured. This guide covers the best practices for using `docmd` features to help your readers. ## Scannability is Everything Users rarely read documentation line-by-line. They scan for answers. * **Use Descriptive Headings:** Instead of "Setup," use "Installing the CLI via NPM." * **Keep Paragraphs Short:** Break up large walls of text into 2-3 sentence chunks. * **Use Bold Text:** Highlight key terms, file paths, or commands so they pop while scanning. ## Choosing the Right Container `docmd` provides several containers. Using them correctly improves the user's mental model. ### Callouts vs. Cards * **Use Callouts** for "interruptions." Use `tip` for helpful shortcuts, `warning` for things that might break, and `danger` for critical errors. * **Use Cards** for "grouping." Cards are great for feature lists on a homepage or summarizing a large section. ### Steps for Tutorials Whenever you have more than two actions the user must perform in order, use the `::: steps` container. It provides a visual timeline that feels much more encouraging than a plain numbered list. ## Linking Best Practices Since `docmd` generates a Single Page Application, navigating between pages is instant. * **Use Relative Paths:** Always link using `./file.md` or `../folder/file.md`. This ensures your links work in your code editor (VS Code), on your web server, and even in offline mode. * **Self-Describing Links:** Avoid "Click here." Instead, use "[Read the Installation Guide](/getting-started/installation)." ## Organising Code Blocks * **Specify Languages:** Always add the language tag (e.g., ` ```javascript `) to enable syntax highlighting. * **Copy Buttons:** Remember that `docmd` automatically adds a copy button to every code block, so you don't need to ask users to "copy and paste" manually. --- ## [Assets Management](https://docs.docmd.io/04/theming/assets-management/) --- title: "Assets Management" description: "Learn how to manage and customise your assets (CSS, JavaScript, images) in your docmd site." --- Managing your custom assets (CSS, JavaScript, images) is an important part of customising your documentation site. `docmd` provides flexible ways to include and manage these assets. ## Project Structure When you initialise a new project with `docmd init`, it creates the following structure: ``` your-project/ ├── assets/ # User assets directory │ ├── css/ # Custom CSS files │ ├── js/ # Custom JavaScript files │ └── images/ # Custom images ├── docs/ # Markdown content ├── docmd.config.js └── ... ``` This structure makes it easy to organise and manage your custom assets. ## How Assets Are Handled There are two main ways to manage assets in your docmd site: ### 1. Root-Level Assets Directory (Recommended) The simplest and recommended approach is to use the `assets/` directory in your project root: **How it works:** - During the build process, docmd automatically copies everything from your root `assets/` directory to the output `site/assets/` directory - Your custom assets take precedence over docmd's built-in assets with the same name - This approach is ideal for GitHub Pages deployments and other hosting scenarios **Example workflow:** 1. Create or modify files in your project's `assets/` directory: ``` assets/css/custom-styles.css assets/js/interactive-features.js assets/images/logo.png ``` 2. Reference these files in your config file: ```javascript module.exports = { // ... theme: { // ... customCss: [ '/assets/css/custom-styles.css', ], }, customJs: [ '/assets/js/interactive-features.js', ], // ... }; ``` 3. Use images in your Markdown content: ```markdown ![Logo](/assets/images/logo.png) ``` 4. Build your site: ```bash docmd build ``` ### 2. Customising Default Assets If you want to modify docmd's default assets: 1. First, build your site normally to generate all assets: ```bash docmd build ``` 2. Modify the generated files in the `site/assets` directory as needed. 3. When rebuilding, use the `--preserve` flag to keep your customised files: ```bash docmd build --preserve ``` 4. If you want to update to the latest docmd assets (for example, after updating the package), run without the preserve flag: ```bash docmd build ``` This approach allows you to: - Get the latest assets by default when you update the package - Preserve your customizations when needed with `--preserve` - See which files are being preserved during the build process The preservation behaviour works with both `build` and `dev` commands: ```bash # Preserve custom assets during development docmd dev --preserve ``` ## Asset Precedence When multiple assets with the same name exist, docmd follows this precedence order: 1. **User assets** from the root `assets/` directory (highest priority) 2. **Preserved assets** from previous builds (if `--preserve` is enabled, which is the default) 3. **Built-in assets** from the docmd package (lowest priority) This ensures your custom assets always take precedence over default ones. ## GitHub Pages Deployment When deploying to GitHub Pages, your assets structure is preserved. If you're using a custom domain or GitHub Pages URL, make sure your asset paths are correctly configured. For more information on deployment, see the [Deployment](/deployment/) documentation. ## Related Topics - [Custom CSS & JS](/theming/custom-css-js/) - Learn how to configure custom CSS and JavaScript - [Theming](/theming/) - Explore other theming options for your documentation site --- ## [Available Themes](https://docs.docmd.io/04/theming/available-themes/) --- title: "Available Themes" description: "An overview of the built-in themes provided by docmd." --- `docmd` allows you to choose from a selection of built-in themes to quickly change the overall look and feel of your documentation site. You can specify the theme in your config file using the `theme.name` property. ```javascript module.exports = { // ... theme: { name: 'theme-name', // Options: 'default', 'sky', 'ruby', 'retro' defaultMode: 'light', // or 'dark' to set as landing mode // ... }, // ... }; ``` ## Try the Themes Click a button below to instantly switch the theme of this website: <div class="theme-picker" style="display: flex; gap: 10px; margin: 20px 0;"> <button onclick="switchDocTheme('default')" class="docmd-button" style="color:#fff;background: #4f4f4f;">Default</button> <button onclick="switchDocTheme('sky')" class="docmd-button" style="color:#fff;background: #0097ff;">Sky</button> <button onclick="switchDocTheme('ruby')" class="docmd-button" style="color:#fff;background: #b30000;">Ruby</button> <button onclick="switchDocTheme('retro')" class="docmd-button" style="color:#fff;background: #0a0a0a; border: 1px solid #0f0;">Retro</button> </div> ## 1. `default` Theme * **`theme.name: 'default'`** * **Description:** The foundation of all docmd themes. This is not a separate theme but the base styling that's always included regardless of which theme you select. It provides: * Basic layout structure with sidebar and content area * Essential typography and spacing * Core styling for documentation elements like code blocks, tables, and custom containers * Light and dark mode foundation * **When to use:** When you want a minimalist, clean interface without additional styling layers. This is the most lightweight option. ## 2. `sky` Theme * **`theme.name: 'sky'`** (This is the default if `theme.name` is not specified) * **Description:** A modern theme inspired by popular documentation platforms, with a fresh and airy design. It features: * A clean, minimalist interface with subtle shadows and rounded corners * Custom typography with improved readability * Refined colour palette for both light and dark modes * Enhanced callout and container styles * Premium documentation feel with careful attention to spacing and contrast * **When to use:** When you want a premium, polished look for your documentation site. ## 3. `ruby` Theme * **`theme.name: 'ruby'`** * **Description:** An elegant, vibrant theme inspired by the precious gemstone. It features: * Rich, jewel-toned colour palette centred around ruby reds and complementary colours * Sophisticated typography with serif headings and sans-serif body text * Distinctive card and callout designs with gem-like faceted styling * Subtle gradients and depth effects that evoke the brilliance of gemstones * Luxurious dark mode with deep, rich backgrounds and vibrant accent colours * **When to use:** When you want your documentation to have a distinctive, premium feel with rich colours and elegant typography. ## 4. `retro` Theme * **`theme.name: 'retro'`** * **Description:** A nostalgic theme inspired by 1980s-90s computing aesthetics. It features: * Terminal-style black backgrounds with phosphor green text in dark mode * Light mode with dark green text on light gray backgrounds * Monospace typography (Fira Code) for authentic retro feel * Neon accent colours (cyan, pink, amber) with glow effects * Animated scanlines and CRT flicker effects * Terminal-style code blocks with `[TERMINAL]` labels * Retro-styled containers with pixel-art inspired elements * Blinking cursor effects on links and active elements * **When to use:** Perfect for developer tools, gaming documentation, tech blogs with vintage computing focus, or anyone wanting a unique, eye-catching retro aesthetic. ## How Themes Work Each theme consists of CSS files located within `docmd`'s internal assets. When you select a theme name, `docmd` links the corresponding stylesheet in your site's HTML: - `default` theme uses the base CSS with no additional theme stylesheet - `sky` theme loads `docmd-theme-sky.css` with its custom styling on top of the default CSS - `ruby` theme loads `docmd-theme-ruby.css` with its custom styling on top of the default CSS - `retro` theme loads `docmd-theme-retro.css` with its custom styling on top of the default CSS You can further customise any chosen theme using the `theme.customCss` option in your config file to add your own overrides or additional styles. See [Custom CSS & JS](/theming/custom-css-js/) for details. --- ## [Custom Styles & Scripts](https://docs.docmd.io/04/theming/custom-css-js/) --- title: "Custom Styles & Scripts" description: "Learn how to add your own custom CSS and JavaScript to your docmd site for advanced customisation." --- While `docmd` themes provide a solid foundation, you can further tailor the appearance and behaviour of your site by injecting custom CSS and JavaScript files. This is configured in your config file. ## Custom CSS You can add one or more custom CSS files using the `theme.customCss` array in your config file. ```javascript module.exports = { // ... theme: { name: 'default', // ... customCss: [ '/assets/css/my-branding.css', // Path relative to your site's root '/css/another-stylesheet.css' ], }, // ... }; ``` **How it works:** * Each string in the `customCss` array should be an absolute path from the root of your generated `site/` directory (e.g., if your file is `site/assets/css/my-branding.css`, the path is `/assets/css/my-branding.css`). * These `<link rel="stylesheet">` tags will be added to the `<head>` of every page *after* the main theme CSS and `highlight.js` CSS. This allows your custom styles to override the default theme styles. > **Note:** For information on how to manage your custom asset files (CSS, JS, images), see the [Assets Management](/theming/assets-management/) documentation. **Use Cases for Custom CSS:** * **Overriding CSS Variables:** The `default` theme uses CSS variables extensively. You can redefine these in your custom CSS. ```css /* my-branding.css */ :root { /* Light mode overrides */ --primary-color: #D65A31; /* Example: Change primary colour */ --font-family-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; --text-color: #222; } body[data-theme="dark"] { /* Dark mode overrides */ --primary-color: #E87A5A; --bg-color: #121212; --text-color: #ddd; } ``` * **Styling Custom Components:** Add styles for specific elements or components unique to your documentation. * **Fine-tuning Layout:** Make minor adjustments to spacing, sizing, or layout elements. ## Custom JavaScript You can add one or more custom JavaScript files using the top-level `customJs` array in your config file. ```javascript module.exports = { // ... customJs: [ '/assets/js/my-interactive-script.js', // Path relative to your site's root '/js/third-party-integration.js' ], // ... }; ``` **How it works:** * Each string in the `customJs` array should be an absolute path from the root of your generated `site/` directory. * These `<script src="..."></script>` tags will be added just before the closing `</body>` tag on every page. This ensures the DOM is loaded before your scripts run and is generally better for page performance. **Use Cases for Custom JS:** * Adding interactive elements (e.g., custom modals, tabs not provided by `docmd`). * Integrating third-party services or widgets. * Performing custom DOM manipulations after the page loads. * Adding simple analytics or tracking snippets if not using a built-in plugin. By using `customCss` and `customJs`, you have significant flexibility to extend and personalize your `docmd` site beyond the standard theming options. --- ## [Customisation & Variables](https://docs.docmd.io/04/theming/customisation/) --- title: "Customisation & Variables" description: "Master the look of your docs by overriding CSS variables and targeting component classes." --- `docmd` uses a "CSS Variable First" architecture. Instead of writing complex CSS rules, you can change the look of your entire site by redefining a few core variables in your `customCss`. ## Variables Reference ### Core Colours | Variable | Usage | | :--- | :--- | | `--bg-color` | The main page background. | | `--text-color` | Standard paragraph text colour. | | `--text-heading` | Contrast colour for H1, H2, etc. | | `--link-color` | Colour for hyperlinks and active states. | | `--border-color` | Standard divider and border colour. | ### Visual Polish | Variable | Usage | | :--- | :--- | | `--ui-element-size` | Height and width for utility buttons (32px). | | `--ui-radius` | Corner rounding for buttons and cards (6px). | | `--sidebar-width` | Width of the navigation column (260px). | ## CSS Class Reference For advanced styling, you can target these classes in your `customCss`: | Class | Target Element | | :--- | :--- | | `.page-header` | The sticky top bar. | | `.sidebar-nav` | The navigation tree container. | | `.nav-category-label`| Non-clickable menu headers. | | `.main-content` | The wrapper for your Markdown content. | | `.docmd-heading` | Container for H2-H4 (includes permalink anchor). | | `.heading-anchor` | The permalink chain icon. | | `.footer-complete` | The advanced multi-column footer. | ## Plugin Component Styling Plugins inject their own classes for targeting: * **Search:** `.docmd-search-modal`, `.search-result-item`. * **Containers:** `.callout`, `.card`, `.docmd-tabs`, `.steps`. ## Adding Custom CSS 1. Create a file in your project: `assets/css/brand.css`. 2. Add your overrides: ```css :root { --link-color: #ff5733; } ``` 3. Register it in `docmd.config.js`: ```javascript theme: { customCss: ['assets/css/brand.css'] } ``` --- ## [Icons](https://docs.docmd.io/04/theming/icons/) --- title: "Icons" description: "How to use and customise Lucide icons in your documentation." --- `docmd` comes with built-in support for the [Lucide](https://lucide.dev/) icon library. Icons can be used in your navigation sidebar, buttons, and custom components to provide visual cues and improve scannability. ## Navigation Icons Assign an icon to any navigation item in your `docmd.config.js`. Use the kebab-case name of any icon found on the Lucide website. ```javascript navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Setup', path: '/setup', icon: 'settings' } ] ``` ## Button Icons You can also use icons inside your button labels by including the raw HTML or using standard Lucide naming if supported by your theme. ```markdown ::: button "Download" /download icon:download ``` ## CSS Styling All icons are rendered as inline SVGs with the class `.lucide-icon`. You can globally change their size or stroke weight in your `customCss`: ```css .lucide-icon { stroke-width: 1.5px; /* Thinner icons for a modern look */ width: 1.2rem; height: 1.2rem; } /* Target a specific icon */ .icon-rocket { color: #ff5733; } ``` ## Icon Reference We support the entire Lucide library. You can browse the thousands of available icons here: ::: button "Browse Lucide Icons" external:https://lucide.dev/icons --- ## [Light & Dark Mode](https://docs.docmd.io/04/theming/light-dark-mode/) --- title: "Light & Dark Mode" description: "How to configure and manage light and dark themes in your docmd documentation." --- `docmd` provides built-in support for light and dark colour schemes to enhance readability and user experience. Users can choose their preferred viewing mode, which improves accessibility and reduces eye strain in different lighting conditions. ## Setting the Default Theme You can set the default theme for your site in the config file: ```javascript module.exports = { // ... other config ... theme: { name: 'default', // or 'sky', 'ruby', 'retro' defaultMode: 'dark', // Can be 'light' or 'dark' enableModeToggle: true, // Enable the toggle button in the UI positionMode: 'bottom', // 'top' or 'bottom' - where to show the toggle }, // ... }; ``` * `defaultMode: 'light'`: The site will initially render with the light colour scheme. * `defaultMode: 'dark'`: The site will initially render with the dark colour scheme. * `enableModeToggle: true`: Shows a toggle button for users to switch modes. * `positionMode: 'bottom'`: Places the toggle button at the bottom of the sidebar (default). * `positionMode: 'top'`: Places the toggle button in the page header (top right). If `defaultMode` is not specified, it defaults to `'light'`. ## How It Works The theme is controlled by a `data-theme` attribute on the `<body>` tag of your HTML pages: * `<body data-theme="light">` for light mode. * `<body data-theme="dark">` for dark mode. For the `sky` theme, the values would be `sky-light` and `sky-dark`. CSS variables in the theme files define colours, backgrounds, fonts, etc., for both modes: ```css /* Example from main.css */ :root { --bg-color: #ffffff; --text-color: #333333; /* ... other light theme variables ... */ } body[data-theme="dark"] { --bg-color: #1a1a1a; --text-color: #e0e0e0; /* ... other dark theme variables ... */ } body { background-color: var(--bg-color); color: var(--text-color); } ``` ## User Preference Toggle When `enableModeToggle` is set to `true`, a toggle button appears that allows users to switch between light and dark modes. The position of this button is controlled by the `positionMode` setting: ```javascript theme: { defaultMode: 'light', enableModeToggle: true, // Shows the toggle button positionMode: 'bottom', // 'bottom' (sidebar) or 'top' (header) }, ``` ### Toggle Button Positions - **`positionMode: 'bottom'`** (default): The toggle button appears at the bottom of the sidebar - **`positionMode: 'top'`**: The toggle button appears in the page header (top right corner) The toggle button uses Lucide icons (`sun` and `moon`) to indicate the current mode and what will happen when clicked. ### User Preference Persistence When a user selects a theme, their preference is saved in their browser's `localStorage` so it persists across sessions and page loads. The implementation uses the following logic: 1. Check if the user has a saved preference in `localStorage` 2. If not, use the `defaultMode` from the configuration 3. When the user clicks the toggle button, update both the display and the stored preference ## Syntax Highlighting Themes `docmd` also includes separate stylesheets for code block syntax highlighting that are compatible with light and dark modes: * `highlight-light.css` for light mode * `highlight-dark.css` for dark mode The correct syntax highlighting theme is loaded automatically based on the current theme mode. When the user toggles the mode, the appropriate syntax highlighting theme is also switched dynamically. ## Customising Theme Colours You can customise the colours for both light and dark modes by adding custom CSS to your project. See [Custom CSS & JS](/theming/custom-css-js/) for more information. ```css /* Example of overriding theme colours in your custom CSS */ :root { --link-color: #0077cc; /* Custom link colour for light mode */ } body[data-theme="dark"] { --link-color: #4da6ff; /* Custom link colour for dark mode */ } ``` --- ## [Browser API (Client-Side)](https://docs.docmd.io/05/advanced/browser-api/) --- title: "Browser API (Client-Side)" description: "How to use the docmd engine directly in the browser to render documentation dynamically without a server." --- `docmd` features an **isomorphic core**. This means the exact same engine that builds your static site in Node.js can also run entirely inside a web browser. This is powerful for: * Building **CMS Previews** (Type markdown, see result instantly). * Creating **Playgrounds** (Like [CodePen](https://codepen.io) for docs). * Embedding documentation rendering into existing React/Vue/Angular apps. ## Installation via CDN You don't need to install Node.js. You can simply include the scripts and styles from a CDN like `unpkg` or `jsdelivr`. ```html <!-- 1. Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- Optional: Theme --> <link rel="stylesheet" href="https://unpkg.com/@docmd/themes/src/docmd-theme-sky.css"> <!-- 2. The Engine Bundle --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` ## Usage Once the script loads, it exposes a global `docmd` object. ### `docmd.compile(markdown, config)` Compiles Markdown text into a complete HTML document string. **Parameters:** * `markdown` (String): The raw Markdown content. * `config` (Object): Configuration overrides (same structure as `docmd.config.js`). **Returns:** * `String`: The full HTML string. ### Example: Live Preview Iframe The safest way to render the output is inside an `<iframe>` using the `srcdoc` attribute. This ensures styles don't bleed into your main application. ```html <!DOCTYPE html> <html> <body> <textarea id="editor"># Hello World</textarea> <iframe id="preview" style="width: 100%; height: 500px; border: 1px solid #ccc;"></iframe> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> <script> const editor = document.getElementById('editor'); const preview = document.getElementById('preview'); function update() { const html = docmd.compile(editor.value, { siteTitle: 'My Preview', theme: { name: 'sky', appearance: 'light' }, layout: { spa: false, header: { enabled: false } } }); preview.srcdoc = html; } editor.addEventListener('input', update); update(); </script> </body> </html> ``` ::: callout tip Because `docmd` is isomorphic, an AI agent can build its own documentation "sandbox" directly in the browser during a development session to verify its understanding of your documentation structure without needing to install the CLI. ::: ## Advanced: Raw Content (No-Style) If you only want the HTML content *without* the `docmd` sidebar, header, or footer (for example, to inject into a `div` on your own site), use the `noStyle` frontmatter option in your input. ```javascript const markdown = `--- noStyle: true components: css: true --- # Just Content This will render without the sidebar layout.`; const html = docmd.compile(markdown, { /* config */ }); ``` ## Limitations The Browser API has a few limitations compared to the Node.js CLI: 1. **No File System Access**: It cannot scan folders to auto-generate navigation. You must provide the `navigation` array explicitly in the config object. 2. **Plugins**: Some Node.js-specific plugins (like Sitemap generation) will not run. --- ## [Client-Side Events](https://docs.docmd.io/05/advanced/client-side-events/) --- title: Client-Side Events description: Hook into the docmd SPA router for custom interactive features. --- `docmd` uses a lightweight Single Page Application (SPA) router for instant page transitions. Because the page does not fully reload, standard `DOMContentLoaded` scripts might not trigger on subsequent page navigations. To solve this, `docmd` dispatches a custom event called `docmd:page-mounted` whenever a new page renders. ## The `docmd:page-mounted` Event Listen for this event in your custom JavaScript files to re-initialise libraries or trigger custom logic. ### Usage Create a custom script (e.g., `assets/js/my-plugin.js`) and add it to your `docmd.config.js` under `customJs`. ```javascript document.addEventListener('docmd:page-mounted', (e) => { console.log('New page loaded:', e.detail.url); // Re-initialise your libraries here // Example: MathJax.typeset(); }); ``` ### Event Detail The event object contains a `detail` property with the following data: | Property | Type | Description | | :--- | :--- | :--- | | `url` | `string` | The full URL of the page that just loaded. | | `initial` | `boolean` | `true` if this is the first initial load, `undefined` on navigation. | ::: callout tip When building AI-powered Search or Chat widgets for `docmd`, always bind their initialisation to `docmd:page-mounted`. This ensures the AI features remain active and aware of the current page context as the user navigates. ::: ## Example: Integrating MathJax Standard integration won't work with SPA navigation. Use the event listener: ```javascript // assets/js/math-support.js (function() { function renderMath() { if (window.MathJax) { window.MathJax.typesetPromise(); } } document.addEventListener('DOMContentLoaded', renderMath); document.addEventListener('docmd:page-mounted', renderMath); })(); ``` --- ## [Developer Guide](https://docs.docmd.io/05/advanced/developer-guide/) --- title: "Developer Guide" description: "Advanced debugging, testing, and contribution tools for developers working directly on the docmd monorepo." --- If you are a contributor who has forked the `docmd` monorepo, understanding the internal testing and debugging infrastructure is important. While `contributing.md` outlines how to get the project running, this guide details **how** to safely develop and test your changes inside the monorepo architecture. ## The Universal Failsafe (`failsafe.js`) Before any release, or when verifying major architectural changes, we rely on the Universal Failsafe. ```bash pnpm test ``` *(This triggers `node scripts/failsafe.js`)* ### What does it do? `failsafe.js` is an aggressive integration testing script. Instead of relying on mocked unit tests, it: 1. Creates a raw, temporary OS directory. 2. Installs the local monorepo packages. 3. Scaffolds dummy Markdown files featuring deep nesting, complex containers, and edge cases. 4. Generates both Legacy and Modern `docmd.config.js` schemas. 5. Executes `docmd build` across these configurations and generates explicit HTML assertions. 6. **Plugin Installer Testing**: It simulates `docmd add search` and `docmd remove search` on a raw environment to prove regex configuration injection and scaffold fallback schemas never break. 7. Compiles and executes the Isomorphic `docmd live` editor runtime inside a sandbox Node instance. **Rule of Thumb:** If you modify core parsers, builders, or installers, run `pnpm test`. If it passes, your code is structurally sound for production releases. ## The Playground Workspace (`_playground`) Developing plugins or tweaking the core engine requires a live environment. We provide a dedicated `packages/_playground` directory specifically for this purpose. ```bash pnpm run dev ``` *(This triggers the Dev Server bound solely to the Playground workspace)* Any changes you make to the core engine, the theme packages, or the UI layout templates will instantly hot-reload in the playground's browser tab. ## Testing the CLI (Add / Remove) When working on CLI features like `docmd add` or `docmd remove`, you shouldn't test them globally, nor should you pollute the root `package.json` with arbitrary plugin additions. We provide dedicated root workspace aliases to proxy CLI commands securely into your playground workspace directory: ```bash pnpm run playground:add search pnpm run playground:remove search ``` **Why use this?** - It runs your *local*, uncompiled code directly from `packages/core/bin/docmd.js`. - It executes the filesystem modifications strictly inside the isolated `packages/_playground` directory maintaining its pristine state. - It guarantees you aren't accidentally tracking plugin additions in your root git tree. ## Arbitrary Executions If you ever need to test an arbitrary CLI command exclusively inside your playground context without `cd`'ing in and out, utilize the pnpm filter bridging syntax natively: ```bash pnpm --filter @docmd/playground exec docmd [command] ``` --- ## [Programmatic Node API](https://docs.docmd.io/05/advanced/node-api/) --- title: "Programmatic Node API" description: "Integrate docmd's build engine directly into your custom Node.js scripts and automation pipelines." --- # Programmatic Node API For advanced workflows, you can import and use the `docmd` build engine directly within your own Node.js scripts. This is ideal for custom CI/CD pipelines, automated documentation generation from source code, or wrapping `docmd` in another tool. ## Installation ```bash npm install @docmd/core ``` ## Core Functions ### `build(configPath, options)` The primary build function used by the CLI. ```javascript const { build } = require('@docmd/core'); async function run() { await build('./docmd.config.js', { isDev: false, // Set to true for watch mode logic offline: false, // Set to true to optimise for file:// access zeroConfig: false // Set to true to bypass config file detection }); } ``` ### `buildLive(options)` Generates the browser-based **Live Editor** bundle. ```javascript const { buildLive } = require('@docmd/core'); async function run() { await buildLive({ serve: false, // true starts a local server; false generates static files port: 3000 // Custom port if serve is true }); } ``` ## Example: Custom Build Pipeline You can combine `docmd` with other tools (like `fs-extra`) to create complex build artifacts. ```javascript const { build } = require('@docmd/core'); const fs = require('fs-extra'); async function deployDocs() { try { // 1. Pre-build logic (e.g. generating markdown from code) await generateMarkdownFromJSDoc('./src', './docs/api'); // 2. Run docmd build await build('./docmd.config.js', { offline: true }); // 3. Post-build logic (e.g. moving files to a server folder) await fs.move('./site', '/var/www/html/docs'); console.log('Documentation successfully deployed!'); } catch (err) { console.error('Build Pipeline Failed:', err); } } ``` ::: callout tip The Programmatic API allows AI agents to act as **Documentation Engineers**. An agent can trigger a `docmd build` after modifying content, verify that the `llms-full.txt` was generated correctly, and then handle the deployment - all without human intervention. ::: --- ## [CLI Commands](https://docs.docmd.io/05/cli-commands/) --- title: "CLI Commands" description: "The complete command-line reference for docmd. Create, build, and deploy your documentation with ease." --- The `docmd` CLI is designed to be minimalist and intuitive. It handles everything from your initial project scaffolding to production-ready builds. ## `docmd init` Scaffolds a new documentation project in the current directory. ```bash docmd init ``` **What it does:** * Creates a `docs/` folder with an `index.md`. * Generates a `docmd.config.js` file with recommended defaults. * Sets up a `package.json` with build scripts. * It does not overwrite your existing `docs/` or configuration files. ## `docmd dev` Starts a local development server with **Instant Hot Reloading**. ```bash docmd dev [options] ``` **Options:** * `-z, --zero-config`: **Magic Mode**. If you don't have a config file, `docmd` will automatically detect your project structure and build your site. * `-p, --port <number>`: Specify a manual port (Default: `3000`). * `-c, --config <path>`: Use a non-standard config file path. ## `docmd build` Generates a production-ready static website to the `site/` folder. ```bash docmd build [options] ``` **Options:** * `--offline`: **File Protocol Friendly**. Rewrites all internal links to end in `.html`. This allow you to browse the site directly from a hard drive (e.g. `file:///Users/me/docs/site/index.html`) without a web server. * `-z, --zero-config`: Build for production using the auto-detection engine. * `-c, --config <path>`: Specify the config file to use. ## `docmd migrate` Upgrades an old configuration file to the modern schema. ```bash docmd migrate ``` It re-maps your legacy keys into the new `layout`, `footer`, and `optionsMenu` objects and saves a backup as `docmd.config.legacy.js`. ## `docmd live` Launches the **Isomorphic Live Editor**. ```bash docmd live ``` This starts a browser-based environment where you can write Markdown on the left and see the rendered `docmd` UI on the right in real-time. Use `--build-only` to generate a shareable static version of the editor. ## `docmd stop` Kills all running background development servers. ```bash docmd stop ``` **What it does:** * Scans active processes for docmd dev or docmd live instances. * Gracefully terminates all background servers. * Automatically identifies servers even if they were started on automated, non-standard ports. * Designed to find orphaned processes in complex workspace structures. ::: callout tip The `docmd` CLI provides structured stdout and clear error logging, making it highly compatible with **Agentic Workflows**. If you are using an AI agent (like me) to manage your site, we can easily parse the logs from `docmd dev` to identify and fix path errors or configuration mismatches. ::: --- ## [Comparing Documentation Tools](https://docs.docmd.io/05/comparison/) --- title: "Comparing Documentation Tools" description: "See how docmd stacks up against Docusaurus, MkDocs, Mintlify, and other documentation generators." --- `docmd` was engineered to fill a specific gap: the space between "too simple" (basic Markdown parsers) and "too heavy" (full React/framework applications). ## Feature Matrix | Feature | docmd | Docusaurus | MkDocs | Mintlify | | :--- | :--- | :--- | :--- | :--- | | **Language** | **Node.js** | React.js | Python | Proprietary | | **Navigation** | **Instant SPA** | React SPA | Page Reloads | Hosted SPA | | **Output** | **Static HTML** | React Hydration | Static HTML | Hosted | | **JS Payload** | **Tiny (< 20kb)** | Heavy (> 200kb) | Minimal | Medium | | **Versioning** | **Easy (Config + Auto)** | Complex (FS) | Plugin (Mike) | Native | | **i18n Support** | **In Pipeline** | Native | Theme-based | Beta | | **Search** | **Built-in (Offline)** | Algolia (Cloud) | Built-in (Lunr) | Built-in (Cloud) | | **PWA** | **Built-in (Plugin)** | Plugin | None | Hosted | | **AI Context** | **Built-in (llms.txt)** | Plugin | None | Proprietary | | **Setup** | **Instant (-z)** | ~15 mins | ~10 mins | ~5 mins | | **Cost** | **Free OSS** | Free OSS | Free OSS | Freemium | ## The docmd Advantage ### 1. AI-Centric Architecture Unlike traditional generators, `docmd` understands that humans aren't the only ones reading your docs. With the **LLM Plugin**, your site automatically generates `llms.txt` and `llms-full.txt` files. These provide instantly ingestible context for AI agents (like GitHub Copilot, ChatGPT, or custom RAG pipelines), making your project significantly easier for AI to support. ### 2. Native PWA Logic While other tools require complex Service Worker configurations, `docmd` offers a **one-line PWA plugin**. This turns your documentation into an installable mobile/desktop app with intelligent offline caching and background auto-updates out of the box. ### 3. Balanced Speed (SPA + Static) We generate pure static HTML for perfect SEO and initial load speed. However, once loaded, our lightweight SPA router handles all further navigations. This gives you the speed of a React app with the simplicity and SEO of a static site. ## When to choose something else * **Choose Docusaurus if:** You need highly interactive, custom React components embedded directly inside your Markdown (MDX), or have extreme multi-language requirements. * **Choose MkDocs if:** Your team is strictly Python-based and you want to use the existing Python plugin ecosystem (though you'll miss out on SPA features). --- ## [General Configuration](https://docs.docmd.io/05/configuration/general/) --- title: "General Configuration" description: "Master the docmd.config.js schema. Configure branding, layout architecture, and core engine features." --- The `docmd.config.js` file is the central brain of your documentation. It defines how your content is structured, how it looks, and how both humans and AI interact with it. ## The Configuration File We recommend using the `defineConfig` helper. It provides full IDE autocomplete and type-checking, making it much easier to discover available settings. ```javascript const { defineConfig } = require('@docmd/core'); module.exports = defineConfig({ title: 'My Project', url: 'https://docs.myproject.com', // ... settings }); ``` ## Core Settings (V3 Schema) `docmd` v0.5.0 introduces a streamlined V3 schema. While legacy keys are still supported, we recommend transitioning to these modern labels: | Key | Description | Default | | :--- | :--- | :--- | | `title` | The name of your documentation site. | `Documentation` | | `url` | Production base URL. **Important for SEO and Sitemap.** | `null` | | `src` | Directory containing your Markdown files. | `docs` | | `out` | Directory for the compiled static site. | `site` | | `base` | The base path if hosting in a subfolder (e.g., `/docs/`). | `/` | ## Branding Customise how your brand appears in the header and browser tabs. ```javascript logo: { light: 'assets/logo-dark.png', // Logo for light mode dark: 'assets/logo-light.png', // Logo for dark mode href: '/', // Click destination alt: 'Company Logo' // Accessibility text }, favicon: 'assets/favicon.ico', ``` ## Layout Architecture `docmd` follows a component-based layout system. You can toggle and configure different parts of the UI via the `layout` object. | Section | Key | Default | Description | | :--- | :--- | :--- | :--- | | **Global** | `spa` | `true` | Enables/Disables Single Page Application navigation. | | **Header** | `header` | `{ enabled: true }` | Toggles the top navigation bar. | | **Sidebar**| `sidebar`| `{ enabled: true, collapsible: true }` | Controls the navigation tree behaviour. | | **Footer** | `footer` | `{ style: 'minimal' }` | Supports `'minimal'` or `'complete'` styles. | ### The Options Menu The Options Menu consolidates utility buttons like **Search**, **Theme Switching**, and **Sponsorship links**. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom', 'menubar' components: { search: true, themeSwitch: true, sponsor: 'https://github.com/sponsors/your-profile' } } } ``` ::: callout info If `optionsMenu.position` is set to `header` or `menubar` but the target container is disabled or null, it automatically falls back to `sidebar-top`. ::: ## Engine Features Fine-tune how `docmd` processes your files. ```javascript minify: true, // Minifies production HTML, CSS, and JS autoTitleFromH1: true, // Automatically use the first # Heading if Frontmatter title is missing copyCode: true, // Adds a 'Copy' button to all code blocks pageNavigation: true, // Adds 'Next' and 'Previous' links at the bottom of pages ``` ## Legacy Support If you are upgrading from an older version of `docmd`, the following keys are automatically mapped to the V3 schema: * `siteTitle` → `title` * `siteUrl` / `baseUrl` → `url` * `srcDir` / `source` → `src` * `outDir` / `outputDir` → `out` ::: callout tip Use `docmd migrate` to automatically upgrade your configuration file to the newest schema while keeping a backup of your old settings. ::: --- ## [Layout & UI Slots](https://docs.docmd.io/05/configuration/layout-slots/) --- title: "Layout & UI Slots" description: "Master the structure of docmd by controlling headers, sidebars, and functional slots." --- A standard `docmd` page is divided into six primary zones: 1. **Menubar**: A full-width top navigation bar. (Added in 0.5.2) 2. **Header**: Secondary bar containing title and utility buttons. 3. **Sidebar**: Left-hand navigation tree. 4. **Content Area**: Primary Markdown rendering zone. 5. **Table of Contents (TOC)**: Right-hand heading navigation. 6. **Footer**: Bottom area for copyright and links. ### Item Properties The menubar is configured within the `layout` section of your `docmd.config.js`. ```javascript module.exports = { layout: { menubar: { enabled: true, position: 'top', // 'top' or 'header' left: [ { type: 'title', text: 'Brand', url: '/', icon: 'home' }, { text: 'Docs', url: '/docs' }, { type: 'dropdown', text: 'Resources', items: [ { text: 'GitHub', url: 'https://github.com/docmd-io/docmd', external: true }, { text: 'Changelog', url: '/changelog' } ] } ], right: [ { text: 'Twitter', url: 'https://twitter.com/docmd', icon: 'twitter' } ] } } }; ``` For a deeper explore menubar layouts, see the [Menubar Configuration](./menubar) page. ## The Header Slot The header is enabled by default. Control it site-wide in your config: ```javascript // docmd.config.js layout: { header: { enabled: true // Set to false to hide the entire top bar } } ``` ### Hiding Page Title in Header Hiding the title from the sticky header on specific pages is handled via frontmatter: ```yaml --- title: "Advanced Guide" hideTitle: true --- ``` ## Multi-Functional Options Menu The `optionsMenu` bundles **Search**, **Theme Toggle**, and **Sponsor** buttons. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom', 'menubar' (Added in 0.5.2) components: { search: true, themeSwitch: true, sponsor: 'https://github.com/sponsors/yourname' } } } ``` ::: callout info "Automatic Container Fallback" If the chosen position targets a disabled or missing container (e.g., `'header'` when header is disabled), `docmd` will automatically default to rendering the options menu in `sidebar-top`. ::: ## Sidebar & Footer Controls ### Sidebar ```javascript layout: { sidebar: { collapsible: true, // Adds the toggle icon defaultCollapsed: false, // Initial state position: 'left' } } ``` ### Footer `docmd` offers **minimal** and **complete** layouts. ```javascript footer: { style: 'complete', description: 'The ultimate docs tool.', hideBranding: false, // Set true to hide "Built with docmd" columns: [ { title: 'Links', links: [{ text: 'GitHub', url: '...' }] } ] } ``` ::: callout tip "AI-Ready Branding 🤖" When designing custom layouts using slots, always ensure the **Search** component is accessible in your `optionsMenu`. AI agents frequently look for the search bar as their primary interaction anchor when exploring your interface to find relevant technical information. ::: --- ## [Menubar](https://docs.docmd.io/05/configuration/menubar/) --- title: "Menubar" description: "How to structure and position your menubar, add links, drop-down menus and icons." --- The `menubar` is a top-level navigation component that can be placed either at the very top of the page (fixed) or within the main content area (above the page header). ## Configuration The menubar is configured within the `layout` section of your `docmd.config.js`. ```javascript module.exports = { layout: { menubar: { enabled: true, position: 'top', // 'top' or 'header' left: [ { type: 'title', text: 'Brand', url: '/', icon: 'home' }, { text: 'Docs', url: '/docs' }, { type: 'dropdown', text: 'Resources', items: [ { text: 'GitHub', url: 'https://github.com/docmd-io/docmd', external: true }, { text: 'Changelog', url: '/changelog' } ] } ], right: [ { text: 'Twitter', url: 'https://twitter.com/docmd', icon: 'twitter' } ] } } }; ``` ### Options | Option | Type | Default | Description | | --- | --- | --- | --- | | `enabled` | `boolean` | `false` | Whether to show the menubar. | | `position` | `string` | `'top'` | Positioning: `'top'` (fixed at absolute top) or `'header'` (above page title in main area). | | `left` | `array` | `[]` | Navigation items for the left section. | | `right` | `array` | `[]` | Navigation items for the right section. | ## Item Types Each item in `left` or `right` can have the following properties: ### Standard Link - `text`: The display text. - `url`: The destination URL. - `icon`: (Optional) Lucide icon name. - `external`: (Optional) Whether to open in a new tab. ### Title Set `type: 'title'` to style the item as a brand/logo link. ### Dropdown Set `type: 'dropdown'` and provide an `items` array of links. ## Options Menu Integration You can integrate the search bar and theme toggle into the menubar by setting `optionsMenu.position` to `'menubar'`. ```javascript module.exports = { layout: { optionsMenu: { position: 'menubar' } } }; ``` When positioned in the menubar, the options menu will appear on the **right region** of the menubar. ::: callout info If the `menubar` is disabled or not configured, the options menu automatically falls back to `sidebar-top`. ::: ## Customisation You can customise the menubar's appearance using CSS variables in your `customCss`: ```css :root { --menubar-height: 52px; --menubar-bg: #1a1b1e; --menubar-border: #2c2e33; --menubar-text: #c1c2c5; } ``` --- ## [Navigation Configuration](https://docs.docmd.io/05/configuration/navigation/) --- title: "Navigation Configuration" description: "How to structure your sidebar, categorize links, and assign icons for both humans and AI models." --- `docmd` provides explicit control over your site's structure. By defining your `navigation` in `docmd.config.js`, you create a logical hierarchy that optimises the Single Page Application (SPA) experience and provides a clear context map for AI models. ## The Navigation Array Each object in the array defines a **Link** or a **Category Group**. ```javascript module.exports = { navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Installation', path: '/getting-started/installation', icon: 'download' } ] } ``` ## Available Properties | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | | **`title`** | `String` | Yes | The display text. Also used as metadata for search and AI. | | **`path`** | `String` | No | Destination URL. Must start with `/` for local markdown. | | **`icon`** | `String` | No | name of a [Lucide Icon](https://lucide.dev/icons) (e.g. `rocket`). | | **`children`** | `Array` | No | Nested items to create a dropdown or group. | | **`collapsible`**| `Boolean` | No | If `true`, the group can be expanded/collapsed. | | **`external`** | `Boolean` | No | If `true`, the link opens in a new tab. | ## Organising Groups You can nest navigation items infinitely. There are two primary ways to organise groups: ### 1. Clickable Group (Folder with Index) If the parent has a `path`, clicking the label navigates to that page and expands the children. ```javascript { title: 'Cloud Setup', path: '/cloud/overview', children: [ { title: 'AWS', path: '/cloud/aws' }, { title: 'GCP', path: '/cloud/gcp' } ] } ``` ### 2. Static Label (Category Wrapper) If you **omit the `path`**, the item becomes a static category header. This is the best way to group related technical sections. ```javascript { title: 'Content & Formatting', icon: 'layout', children: [ { title: 'Syntax Guide', path: '/content/syntax' }, { title: 'Containers', path: '/content/containers' } ] } ``` ## Icons Integration `docmd` comes pre-bundled with the entire **Lucide** icon library. Simply use the icon name in kebab-case. Common examples: `home`, `rocket`, `settings`, `github`, `terminal`, `brain-circuit`. ::: callout tip When defining navigation, use descriptive `title` keys even if the page content starts with a header. Clear navigation titles allow LLMs (using `llms-full.txt`) to understand the relationships between different parts of your project even without reading the full file. ::: --- ## [Redirects & 404](https://docs.docmd.io/05/configuration/redirects/) --- title: "Redirects & 404" description: "Configure instant metadata-based redirects and custom branded 404 error pages for static deployments." --- In a static environment, there is no server-side logic (like `.htaccess` or Nginx rules) to handle routing. `docmd` solves this by generating native HTML failsafes that handle redirection and error states automatically. ## Server-less Redirects You can forward traffic from old URLs to new destinations by defining a mapping in the `redirects` object. ```javascript module.exports = defineConfig({ redirects: { '/setup': '/getting-started/installation', // Redirect /setup to new path '/v1/api': '/api-reference' // Forward legacy API links } }); ``` ### Technical Implementation When you define a redirect, `docmd` creates a directory and an `index.html` at the old path containing a `<meta http-equiv="refresh">` tag. This ensures: 1. **Humans** are redirected instantly after the page loads. 2. **Search Engines** recognise the canonical link to the new content. 3. **Analytics** are preserved across the transition. ## Branded 404 Pages When a user accesses a non-existent URL, most static hosts (Netlify, Vercel, GitHub Pages) look for a `404.html` file in the root. `docmd` automatically generates this file, ensuring that it inherits your theme, sidebar, and Single Page Application (SPA) functionality. ### Customising the Error Content You can customise the 404 messaging in your configuration: ```javascript module.exports = defineConfig({ notFound: { title: '404: Lost in the Docs', content: "We couldn't find the page you're looking for. Use the sidebar to find your way back." } }); ``` ::: callout tip Local development server (`docmd dev`) will automatically serve this custom 404 page whenever a file is missing. ::: --- ## [Versioning](https://docs.docmd.io/05/configuration/versioning/) --- title: "Versioning" description: "Enable multi-version documentation with seamless switching, sticky path preservation, and isolated build directories." --- `docmd` features a native Versioning Engine that allows you to manage and serve multiple versions of your project simultaneously (e.g., `v1.0`, `v2.0`). It automatically handles the URL routing, sidebar updates, and version switching logic. ## Directory Organisation To enable versioning, you must organise your documentation into versioned source folders. The most common pattern is keeping the latest version in `docs` and older versions in folders prefixed with `docs-`. ```text my-project/ ├── docs/ # Version 2 (Main) ├── docs-v1/ # Version 1 (Legacy) ├── docmd.config.js ``` ## Configuration Define your versions in the `versions` object. ```javascript module.exports = defineConfig({ versions: { current: 'v2', // The version ID built to the root (/) position: 'sidebar-top', // Switcher location: 'sidebar-top' or 'sidebar-bottom' all: [ { id: 'v2', dir: 'docs', label: 'v2.x (Latest)' }, { id: 'v1', dir: 'docs-v1', label: 'v1.x' } ] } }); ``` ## Core Features ### 1. Root SEO (The "Current" Version) The version specified in `current` is built directly to your output directory root (e.g., `mysite.com/`). This ensures your primary SEO traffic always lands on your most up-to-date information. ### 2. Isolated Sub-directories Other versions are automatically built into subfolders matching their `id`. * `v2 (Current)` → `mysite.com/` * `v1` → `mysite.com/v1/` ### 3. Sticky Switching (Path Preservation) `docmd` smartly preserves the relative path when a user switches versions. If a user is reading `mysite.com/getting-started` and switches to **v1**, they are automatically taken to `mysite.com/v1/getting-started` instead of being dumped back at the home page. ### 4. Per-Version Assets Each version inherits your global `assets/` folder, but `docmd` ensures they are isolated in the build process, preventing styles from older versions from leaking into newer ones. ## Best Practices 1. **Semantic IDs**: Use short, URL-friendly IDs like `v1`, `v2`, or `beta`. These IDs appear directly in your URLs. 2. **Navigation Parity**: While you can have different navigation for different versions, keeping your folder structure consistent makes "Sticky Switching" much more effective for your users. 3. **One Config to Rule Them All**: You do not need separate configuration files for each version. `docmd` iterates through your `versions.all` array during a single `docmd build` command. --- ## [Buttons](https://docs.docmd.io/05/content/containers/buttons/) --- title: "Buttons" description: "Inject call-to-action buttons for internal routing or external resources. No closing tag required." --- Buttons are used to create prominent links. Unlike most `docmd` containers, the `button` is **self-closing**. You define it on a single line and do not use a closing `:::` tag. ## Syntax ```markdown ::: button "Label" Path [Option] ``` ### Options | Property | Value | Description | | :--- | :--- | :--- | | **Path** | `/path` | Relative URL to a page in your docs. | | **Path** | `external:URL` | Opens the link in a new tab with `target="_blank"`. | | **Colour** | `color:#hex` | Custom background colour (e.g. `color:#4f46e5`). | ## Examples ### 1. Internal Link Use relative paths to link between pages. ```markdown ::: button "Back to Installation" /getting-started/installation ``` ::: button "Back to Installation" /getting-started/installation ### 2. External Link Prepend `external:` to ensure the link opens in a new tab. ```markdown ::: button "View on GitHub" external:https://github.com/docmd-io/docmd ``` ::: button "View on GitHub" external:https://github.com/docmd-io/docmd ### 3. Styled Branding You can use standard CSS colours or Hex codes to match your brand. ```markdown ::: button "Critical Action" /delete-account color:red ::: button "Success" /confirm color:#228B22 ``` ::: button "Critical Action" ./#delete-account color:crimson ::: button "Success" ./#confirm color:#228B22 ## Troubleshooting: Accidental Over-closing Because buttons are self-closing, adding a second `:::` line will actually **close the parent container** (like a Card or a Tab) that the button is sitting inside. **Incorrect (Will break layout):** ```markdown ::: card ::: button "Click" /path ::: ::: ``` **Correct:** ```markdown ::: card ::: button "Click" /path ::: ``` --- ## [Callouts](https://docs.docmd.io/05/content/containers/callouts/) --- title: "Callouts" description: "Highlight critical information using semantic blocks. Supports Tip, Warning, Danger, and Info types." --- Callouts are used to highlight information that requires the user's immediate attention. `docmd` provides five semantic types, each with its own visual styling and icon. ## Syntax ```markdown ::: callout type "Optional Title" Your content here. ::: ``` | Type | Default Title | Best Used For | | :--- | :--- | :--- | | `info` | Info | General help or background context. | | `tip` | Tip | Best practices, shortcuts, or "Pro-tips". | | `warning` | Warning | Actions that might cause minor issues if ignored. | | `danger` | Danger | Critical warnings, data loss, or significant errors. | | `success` | Success | Confirmation of a completed action. | ## Examples ### 1. Simple Note ```markdown ::: callout info This is a standard informational note. ::: ``` ::: callout info This is a standard informational note. ::: ### 2. Custom Title ```markdown ::: callout warning "Action Required" Please back up your configuration before proceeding with the upgrade. ::: ``` ::: callout warning "Action Required" Please back up your configuration before proceeding with the upgrade. ::: ### 3. Rich Content (Nesting) Callouts can contain any Markdown content, including code blocks and buttons. ````markdown ::: callout tip "Try this Shortcut" Use the CLI to instantly verify your build: ```bash docmd dev --preserve ``` ::: button "Learn More" /cli-commands ::: ```` ::: callout tip "Try this Shortcut" Use the CLI to instantly verify your build: ```bash docmd dev --preserve ``` ::: button "Learn More" /cli-commands ::: ::: callout tip For LLMs, callouts act as high-priority anchors. Use a `::: callout danger` block to explicitly document breaking changes or "Gotchas" - AI models are specially tuned to prioritise these blocks in their reasoning. ::: --- ## [Cards](https://docs.docmd.io/05/content/containers/cards/) --- title: "Cards" description: "Organise information into framed, visually distinct blocks. Ideal for landing pages and feature grids." --- Cards are the primary structural component in `docmd`. They group related content into a bordered box with optional titles, providing clear visual hierarchy. ## Syntax ```markdown ::: card "Optional Title" This is the card body. ::: ``` ## Examples ### 1. Feature Highlight ```markdown ::: card "Fast Build Times" `docmd` uses an asynchronous processing engine that can build hundreds of pages in under a second. ::: ``` ::: card "Fast Build Times" `docmd` uses an asynchronous processing engine that can build hundreds of pages in under a second. ::: ### 2. Complex Content Cards can contain any other Markdown elements, including code blocks and buttons. ````markdown ::: card "Quick Install" Get the library via your favourite package manager: ```bash npm install @docmd/core ``` ::: button "Installation Guide" /getting-started/installation ::: ```` ::: card "Quick Install" Get the library via your favourite package manager: ```bash npm install @docmd/core ``` ::: button "Installation Guide" /getting-started/installation ::: ## Creating Grids While `docmd` is purely Markdown-driven, you can easily create responsive multi-column layouts using standard HTML wrappers around your cards. ```markdown <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;"> ::: card "Left Column" Content for the left side. ::: ::: card "Right Column" Content for the right side. ::: </div> ``` ::: callout tip Cards act as **Topic Clusters**. When an LLM parses the `llms-full.txt` context, items wrapped in a `card` are treated as a single cohesive unit of information. Use cards to isolate unrelated technical concepts on the same page. ::: --- ## [Changelogs](https://docs.docmd.io/05/content/containers/changelogs/) --- title: "Changelogs" description: "Create beautiful, timeline-based version history pages." --- The `changelog` container formats version history into a clean, vertical timeline. It is specifically designed to parse date/version headers and body content separately. ## Syntax Use `==` to separate entries. The text on the `==` line becomes the timeline badge (left side), and the content below becomes the body (right side). ```markdown ::: changelog == Version 2.0 Description of version 2.0. == Version 1.0 Description of version 1.0. ::: ``` ::: callout tip Maintaining a clean changelog helps AI agents understand the evolution of your project. An AI can quickly scan a `::: changelog` structure to determine which features were added in a specific version, allowing it to provide more accurate context to users asking about "what's new". ::: ## Example ```markdown ::: changelog == v2.0.0 (2026) ### Major Overhaul We rewrote the core engine for better performance. * Added SPA Router * Added Plugin System == v1.5.0 (2025) ### Maintenance Bug fixes and performance improvements. ::: callout info This was the last version to support Node 14. ::: == v1.0.0 (2024) Initial Release. ::: ``` ::: changelog == v2.0.0 (2026) ### Major Overhaul We rewrote the core engine for better performance. * Added SPA Router * Added Plugin System == v1.5.0 (2025) ### Maintenance Bug fixes and performance improvements. ::: callout info This was the last version to support Node 14. ::: == v1.0.0 (2024) Initial Release. ::: --- ## [Collapsible](https://docs.docmd.io/05/content/containers/collapsible/) --- title: "Collapsible" description: "Create toggleable accordion sections for FAQs and advanced details." --- The `collapsible` container creates an accordion-style toggle. It is perfect for FAQs, spoilers, or hiding complex configuration options that aren't relevant to every reader. ## Syntax ```markdown ::: collapsible [open] Title Text Content goes here. ::: ``` * **`open`**: (Optional) If present, the section defaults to expanded. * **`"Title"`**: The text shown on the clickable bar. Defaults to "Click to expand". ::: callout tip Even when collapsed in the UI, the content inside a `collapsible` is fully indexed by the `docmd` search engine and included in the `llms-full.txt` payload. This means AI can answer questions using hidden details while the interface remains clean for humans. ::: ## Examples ### Default (Closed) Useful for FAQs or spoilers. ```markdown ::: collapsible "How do I reset my password?" Go to **Settings > Account** and click "Reset Password". ::: ``` ::: collapsible "How do I reset my password?" Go to **Settings > Account** and click "Reset Password". ::: ### Default (Open) Useful for sections that should be visible but optional to hide. ```markdown ::: collapsible open "Prerequisites" 1. Node.js v18+ 2. A text editor ::: ``` ::: collapsible open "Prerequisites" 1. Node.js v18+ 2. A text editor ::: ### Nested Content ````markdown ::: collapsible "View JSON Response" ```json { "status": "success", "data": { "id": 123 } } ``` ::: ```` ::: collapsible "View JSON Response" ```json { "status": "success", "data": { "id": 123 } } ``` ::: --- ## [Custom Containers](https://docs.docmd.io/05/content/containers/) --- title: "Custom Containers" description: "A directory of the interactive UI components available in docmd. Cards, Tabs, Callouts, and more." --- Standard Markdown handles basic text well, but professional documentation often requires richer structure. `docmd` extends Markdown with a set of "Containers" that render into beautiful, responsive UI components. ## The Syntax Guide All containers follow a consistent block syntax. ```markdown ::: type "Optional Title" This is the content of the container. It can include **Markdown**, images, and even other containers. ::: ``` | Component | Keyword | Usage | | :--- | :--- | :--- | | **[Callouts](./callouts)** | `callout` | Semantic highlights (tips, warnings) | | **[Cards](./cards)** | `card` | Framed content blocks (perfect for grids) | | **[Tabs](./tabs)** | `tabs` | Switchable content panes | | **[Steps](./steps)** | `steps` | Visual numbered timelines | | **[Buttons](./buttons)** | `button` | Styled CTA links | | **[Collapsible](./collapsible)**| `collapsible` | Hidden content toggles (Accordions) | | **[Changelogs](./changelogs)** | `changelog` | Version and update tracking | ## Why Use Containers? Containers aren't just for humans. They provide high-level semantic signals to the `docmd` engine and LLMs: 1. **AI Context**: Highlighting a block as a `callout tip` tells AI models that this specific information is a recommendation. 2. **Layout Control**: Combining `cards` with standard CSS allows you to build complex landing pages entirely in Markdown. 3. **Clean Source**: No HTML or Class-soup is required in your markdown files. ## Nesting Components One of `docmd`'s most powerful features is **Infinite Nesting**. You can place any container inside another, allowing you to build very complex documentation elements purely with simple Markdown syntax. ```markdown ::: card "Pro Guide" ::: callout warning Reading this out of order may be confusing. ::: ::: button "Let's Begin" /start ::: ``` [Read the Nesting Guide →](./nested-containers) --- ## [Nested Containers](https://docs.docmd.io/05/content/containers/nested-containers/) --- title: "Nested Containers" description: "Master docmd's recursive parser. Learn how to combine cards, tabs, and callouts to build complex, interactive page layouts." --- One of `docmd`’s most powerful features is its recursive parsing engine. You can nest components inside each other infinitely to create professional, interactive layouts that would otherwise require complex HTML templates. ## The One Golden Rule While nesting is infinite, remember the **Self-Closing Button Rule**: ::: callout warning Because `::: button` is self-closing, do **not** add a closing `:::` line after it. Doing so will accidentally close the parent container that contains the button. ::: ## Example: Interactive Landing Page Block You can combine a **Card** for the frame, **Tabs** for technical choices, and **Callouts** for highlighting. ````markdown ::: card "Developer Quickstart" Choose your preferred environment to begin: ::: tabs == tab "NPM" ```bash npm install -g @docmd/core ``` ::: callout success Installation usually takes less than 10 seconds. ::: == tab "Manual" Download the binary from GitHub and add it to your PATH. ::: button "GitHub Downloads" external:https://github.com/docmd-io/docmd ::: ::: ```` ## Example: Documenting a Sequential Hack Nesting **Tabs** inside **Steps** is a great way to show multi-platform instructions. ```markdown ::: steps 1. **Select Platform** Choose your operating system below. ::: tabs == tab "macOS" Run the Homebrew command. == tab "Linux" Use the generic install script. ::: 2. **Verify Setup** Check the installation version. ::: ``` ::: steps 1. **Select Platform** Choose your operating system below. ::: tabs == tab "macOS" Run the Homebrew command. == tab "Linux" Use the generic install script. ::: 2. **Verify Setup** Check the installation version. ::: ## Nesting Constraints While the engine is reliable, follow these best practices for the best experience: * **Tabs in Tabs**: Not recommended. It creates "Context Loops" that are difficult for users to navigate on mobile. * **Steps in Tabs**: High syntax conflict. Use standard ordered lists (`1.`) inside tabs instead of the `::: steps` container. * **Indentation**: `docmd` does **not** require indentation for nested blocks, but adding 2 or 4 spaces makes your Markdown much easier for both humans and LLMs to read. * **Performance**: Deep nesting (over 6 levels) is supported but may impact initial build times on extremely large documentation sites. ::: callout tip Nesting helps segment knowledge. When an LLM reads the `llms-full.txt` stream, a nested `callout` inside a `card` tells the model that the tip is specifically scoped to that card's topic, improving the precision of its generation. ::: --- ## [Steps](https://docs.docmd.io/05/content/containers/steps/) --- title: "Steps" description: "Transform standard numbered lists into high-impact visual timelines of instructions." --- The `steps` container is designed specifically for "How-to" guides and tutorials. It takes a standard Markdown ordered list and converts it into a clean, numbered vertical timeline. ## Syntax Simply wrap your ordered list in a `::: steps` container. ```markdown ::: steps 1. **Preparation** Ensure you have Node.js installed on your machine. 2. **Execution** Run the `init` command. 3. **Completion** Your site is ready! ::: ``` ## Detailed Example: Deployment ```markdown ::: steps 1. **Build the Project** Generate the production-ready static files. ```bash docmd build ``` 2. **Verify Output** Inspect the `site/` directory to ensure all files were generated. 3. **Deploy to Host** Upload the contents of `site/` to your hosting provider. ::: ``` ::: steps 1. **Build the Project** Generate the production-ready static files. ```bash docmd build ``` 2. **Verify Output** Inspect the `site/` directory to ensure all files were generated. 3. **Deploy to Host** Upload the contents of `site/` to your hosting provider. ::: ## Advanced Usage ### Nesting Containers in Steps You can nest any other component (like a **Callout**) inside a step to provide extra context without breaking the numbering sequence. ```markdown ::: steps 1. **Configure Environment** Create a `.env` file in your root directory. ::: callout tip You can use the template provided in `.env.example`. ::: 2. **Restart Server** Apply the new environment settings. ::: ``` ::: callout tip The `steps` container is a strong signal to LLMs that a specific **Workflow** is being documented. When using `steps`, ensure each list item starts with a **Bolded Title**. This allows AI models to quickly parse the sequence of operations in the `llms-full.txt` context. ::: --- ## [Tabs](https://docs.docmd.io/05/content/containers/tabs/) --- title: "Tabs" description: "Organise alternative or dense information into switchable panes. Perfect for multi-language code snippets." --- Tabs are the best way to present related but mutually exclusive information (like "npm vs yarn" or "Windows vs macOS" instructions) in a compact, interactive format. ## Syntax The `tabs` container uses a special sub-delimiter: `== tab "Label"`. ```markdown ::: tabs == tab "Tab Label 1" Content for the first tab. == tab "Tab Label 2" Content for the second tab. ::: ``` ## Detailed Example: Package Managers ````markdown ::: tabs == tab "NPM" ```bash npm install @docmd/core ``` == tab "Yarn" ```bash yarn add @docmd/core ``` == tab "PNPM" ```bash pnpm add @docmd/core ``` ::: ```` ::: tabs == tab "NPM" ```bash npm install @docmd/core ``` == tab "Yarn" ```bash yarn add @docmd/core ``` == tab "PNPM" ```bash pnpm add @docmd/core ``` ::: ## Advanced Features ### Lazy Rendering `docmd` implements **Conditional Lazy Rendering**. If a tab contains heavy assets like a **Mermaid.js** diagram or large images, they are only initialised once the user clicks that specific tab. This ensures your initial page load remains blazingly fast. ### Sticky Tab State The `docmd` SPA router remembers the active tab's index when navigating between similar pages. This creates a cohesive experience for users switching between pages that share the same tab setup. ## Technical Constraints | Constraint | Note | | :--- | :--- | | **No Tabs-in-Tabs** | To prevent UX loops, tabs cannot be nested inside other tabs. | | **Steps-in-Tabs** | High-conflict syntax: If you need steps inside a tab, use a standard ordered list (`1. Step One`). | | **Max Tabs** | Recommended maximum of 6 tabs for mobile responsiveness. | ::: callout tip When using tabs for code snippets, always include the language in the tab label (e.g., `== tab "JavaScript"`). This allows LLMs to instantly identify the relevant block in the unified `llms-full.txt` stream. ::: --- ## [Frontmatter Reference](https://docs.docmd.io/05/content/frontmatter/) --- title: "Frontmatter Reference" description: "The complete guide to page-level metadata and configuration in docmd." --- Frontmatter allows you to override global settings on a per-page basis. It must be written in YAML format at the very top of your Markdown file. ## Core Metadata | Key | Type | Description | | :--- | :--- | :--- | | `title` | `String` | **Required.** Sets the HTML `<title>` and the primary page header. | | `description` | `String` | Sets the meta description for SEO and search results. | | `keywords` | `Array` | A list of keywords for the `<meta name="keywords">` tag. | ## Visibility & Control (v0.5.1+) | Key | Type | Description | | :--- | :--- | :--- | | `noindex` | `Boolean` | Excludes the page from the search results. | | `llms` | `Boolean` | Set to `false` to exclude this page from the `llms.txt` / `llms-full.txt` files. | | `hideTitle` | `Boolean` | If `true`, the title is hidden from the sticky header (use this if you have a custom H1). | | `bodyClass` | `String` | Adds a custom CSS class to the `<body>` tag of this page. | ## Page Layout & Components | Key | Type | Description | | :--- | :--- | :--- | | `layout` | `String` | Set to `full` to hide the Table of Contents and use the primary width. | | `toc` | `Boolean` | Set to `false` to disable the Table of Contents entirely. | | `noStyle`| `Boolean` | Removes the entire docmd UI (Sidebar, Header, Footer) for custom landing pages. | ### `noStyle` Component Control When `noStyle: true` is enabled, you must explicitly opt-in to components you want to keep: ```yaml --- noStyle: true components: meta: true # Injects SEO tags favicon: true # Injects favicon css: true # Injects docmd-main.css theme: true # Injects theme colours/overrides highlight: true # Injects syntax highlighting scripts: true # Injects docmd-main.js (for SPA/Search) layout: true # Injects the content-area wrapper sidebar: true # Injects the navigation sidebar footer: true # Injects the footer branding: true # Injects the "Built with docmd" badge --- ``` ## Plugin Overrides ### SEO Plugin (`seo`) * `description`: Page-specific social description. * `image`: Social share image URL. * `aiBots`: Set to `false` to block AI crawlers from this specific page. * `canonicalUrl`: Sets a custom canonical link. --- ## [Live Preview & Browser Support](https://docs.docmd.io/05/content/live-preview/) --- title: "Live Preview & Browser Support" description: "Run docmd entirely in the browser without a server using the new Live architecture." --- `docmd` features a modular architecture that separates file system operations from core processing logic. This allows the documentation engine to run **entirely in the browser**, enabling live editors and CMS previews without a server. ::: button "Open Live Editor" https://live.docmd.io ## The Live Editor The built-in Live Editor provides a split-pane interface where you can write Markdown on the left and see the rendered documentation on the right instantly. ### Running Locally Launch the editor on your machine: ```bash docmd live ``` ### Static Deployment Generate a standalone version for hosting (e.g., on Vercel or GitHub Pages): ```bash docmd live --build-only ``` This creates a `dist/` directory containing the `index.html` and `docmd-live.js` engine. ## Embedding docmd in Your Site Use the browser-compatible bundle to add Markdown preview capabilities to your own applications. ### 1. Include Script and Assets ```html <link rel="stylesheet" href="/assets/css/docmd-main.css"> <link rel="stylesheet" href="/assets/css/docmd-theme-sky.css"> <script src="/docmd-live.js"></script> ``` ### 2. Using the API The global `docmd` object exposes the `compile` function. ```javascript const html = docmd.compile(markdown, { siteTitle: 'My Live Doc', theme: { name: 'sky' } }); document.getElementById('preview-frame').srcdoc = html; ``` ::: callout tip "AI Feedback Loops 🤖" By using the Live Editor architecture, you can build **AI-Agent sandboxes**. Instead of the AI saving files to disk, it can "post" its suggested edits to a live-compilation buffer, allowing you to preview AI-suggested documentation changes in real-time before approving the commit. ::: --- ## [docmd : No-Style Page Example](https://docs.docmd.io/05/content/no-style-example/) --- title: "docmd : No-Style Page Example" description: "An example of a page using the no-style feature" noStyle: true components: meta: true favicon: true css: true theme: true scripts: true mainScripts: true copyCode: true customHead: | <style> body { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; margin: 0; padding: 0; line-height: 1.6; } .container { max-width: 800px; margin: 0 auto; padding: 40px 20px; } .header { text-align: centre; margin-bottom: 40px; } .header h1 { font-size: 3rem; margin-bottom: 10px; color: #4a6cf7; } .header p { font-size: 1.2rem; color: #666; } .content { background-color: #f8f9fa; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); } .button { display: inline-block; padding: 12px 24px; background-color: #4a6cf7; color: white; text-decoration: none; border-radius: 4px; font-weight: 600; margin-top: 20px; } .button:hover { background-color: #3a5ce4; } [data-theme="dark"] { color-scheme: dark; } [data-theme="dark"] body { background-color: #121212; color: #e0e0e0; } [data-theme="dark"] .content { background-color: #1e1e1e; box-shadow: 0 2px 10px rgba(0,0,0,0.2); } [data-theme="dark"] .header p { color: #aaa; } </style> bodyClass: "no-style-example" --- <div class="container"> <div class="header"> <h1>No-Style Page Example</h1> <p>This page demonstrates the no-style feature with a custom layout</p> </div> <div class="content"> <h2>What is this page?</h2> <p> This is an example page that uses the <code>noStyle: true</code> frontmatter option to create a completely custom page layout. Unlike regular documentation pages, this page doesn't use the standard docmd layout with sidebar navigation and table of contents. </p> <h2>How does it work?</h2> <p> The <code>noStyle</code> option tells docmd to use a special template that only includes the components you explicitly request via the <code>components</code> object in frontmatter. This gives you complete control over the page structure. </p> <h2>Features enabled on this page:</h2> <ul> <li><strong>meta</strong>: Meta tags, title, and description for SEO</li> <li><strong>favicon</strong>: The site favicon</li> <li><strong>css</strong>: Basic CSS for markdown content</li> <li><strong>theme</strong>: Theme support for light/dark mode</li> <li><strong>scripts</strong>: JavaScript for functionality</li> </ul> <h2>Custom styling</h2> <p> This page includes custom CSS in the <code>customHead</code> frontmatter field. This allows you to define page-specific styles without affecting the rest of your site. </p> <a href="/content/no-style-pages/" class="button">Get Back to No-Style Pages Documentation</a> </div> </div> --- ## [No-Style Pages](https://docs.docmd.io/05/content/no-style-pages/) --- title: "No-Style Pages" description: "Create landing pages and custom layouts by disabling the default docmd theme." --- Sometimes you need a page that looks completely different, like a Marketing Landing Page, a Login screen, or a custom showcase. `docmd` allows you to disable the standard layout (Sidebar, Header, Footer) on a per-page basis using **Frontmatter**. ## Enabling No-Style Add `noStyle: true` to your page's frontmatter. ```yaml --- title: "Welcome" noStyle: true components: meta: true # Keep SEO meta tags favicon: true # Keep site favicon css: true # Injects basic docmd-main.css --- <!-- Write raw HTML or Markdown below --> <div class="hero-section"> <h1>My Product</h1> <p>The future of documentation.</p> </div> ``` ## Controlling Components When `noStyle` is active, you have a blank canvas. Selectively re-enable specific parts of the system: | Component | Description | | :--- | :--- | | `meta` | Injects `<title>`, SEO tags, and OpenGraph data. | | `favicon` | Injects the site favicon. | | `css` | Injects `docmd-main.css` (useful for grid/typography). | | `theme` | Injects the active theme colours/overrides. | | `scripts` | Injects `docmd-main.js` (needed for buttons/SPA). | ## Example: Marketing Landing Page ```yaml --- title: "Home" noStyle: true components: meta: true css: true customHead: | <style> .hero { text-align: centre; padding: 100px 20px; } </style> --- <div class="hero"> <h1>Build Faster.</h1> ::: button "Get Started" /docs/intro color:blue </div> ``` ::: callout tip "AI-Managed Landing Pages 🤖" Because `noStyle` pages can accept raw HTML while still being parsed by `docmd`, they are perfect for **AI-generated layouts**. You can prompt an AI: *"Create a landing page for my project using noStyle: true and provide the raw HTML section."* The AI can perfectly integrate with the rest of your build pipeline. ::: --- ## [Advanced Syntax](https://docs.docmd.io/05/content/syntax/advanced/) --- title: "Advanced Syntax" description: "Master docmd's extended Markdown features: Task lists, custom attributes, footnotes, and more." --- Beyond standard Markdown, `docmd` supports several GitHub Flavored Markdown (GFM) extensions and custom attribute syntaxes to give you total control over your content. ## GFM Extensions ### Task Lists Create interactive or static checklists: ```markdown - [x] Completed task - [ ] Incomplete task ``` - [x] Completed task - [ ] Incomplete task ### Autolinks URL and email addresses are automatically linked without extra syntax: `https://docmd.io` ### Emojis Use standard emoji shortcodes like `:rocket:` or `:smile:`. > I :heart: docmd! :rocket: :smile: ## Custom Attributes (IDs and Classes) You can assign custom IDs and CSS classes directly to headers, images, and links using the `{}` syntax. ### Custom IDs Useful for deep-linking to specific sections. ```markdown ## My Header {#custom-id} ``` ### Custom Classes Assign classes to elements to apply [Custom CSS](/theming/custom-css-js). ```markdown ## Styled Header {.text-centre .text-red} ``` ### Direct Button Links Turn any link into a styled button. ```markdown [Download Now](/download){.docmd-button} ``` ## Footnotes & References Add footnotes for citations or technical deep-dives[^1]. Definitions are automatically moved to the bottom of the page. ```markdown Here is a statement needing a citation[^1]. [^1]: This is the footnote content. ``` ## Abbreviations & Definitions ### Definition Lists ```markdown Term : Definition for the term. ``` Term : Definition for the term. ### Abbreviations Define abbreviations globally within a page. Hovering over the word will show the full name. ```markdown *[HTML]: Hyper Text Markup Language HTML is defined by the W3C. ``` *[HTML]: Hyper Text Markup Language HTML is defined by the W3C. ::: callout tip Using **Definitions** and **Abbreviations** provides high-quality semantic context to AI agents. When an AI processes your `llms-full.txt`, these explicit definitions help it resolve technical acronyms correctly without guessing, leading to more accurate code generation. ::: --- ## [Code Blocks](https://docs.docmd.io/05/content/syntax/code/) --- title: "Code Blocks" description: "Document your code with automatic syntax highlighting, line numbers, and copy buttons." --- `docmd` includes `highlight.js` for automatic syntax highlighting. ## Fenced Code Blocks Wrap your code in triple backticks and specify the language for the best results. ````markdown ```javascript function hello() { console.log("Hello World"); } ``` ```` **Renders as:** ```javascript function hello() { console.log("Hello World"); } ``` ::: callout tip Copy Button If `copyCode: true` is enabled in your config (default), a copy button will automatically appear in the top-right corner of every code block when the user hovers. ::: ## AI Context Strategy When documenting code for LLMs: 1. **Always specify the language**: This helps AI models parse the block correctly in the `llms-full.txt` payload. 2. **Add comments**: Explaining complex logic within the code block helps the AI reason about your implementation during context retrieval. ## Supported Languages `docmd` supports hundreds of languages including: `javascript`, `typescript`, `html`, `css`, `bash`, `json`, `python`, `rust`, `go`, `markdown`, and `yaml`. --- ## [Images & Lightbox](https://docs.docmd.io/05/content/syntax/images/) --- title: "Images & Lightbox" description: "Adding images, styling galleries, and enabling lightbox zoom effects." --- Use standard Markdown syntax. We recommend storing images in your `assets/images/` directory. ```markdown ![Alt Text](/assets/images/screenshot.png "Optional Title") ``` ## Image Styling (v0.5.1+) Add specific classes using the `{ .class }` syntax. ### Sizing ```markdown ![Small](/assets/icon.png){ .size-small } ![Medium](/assets/preview.png){ .size-medium } ![Large](/assets/banner.png){ .size-large } ``` ### Alignment & Effects ```markdown ![Centred](/assets/img.png){ .align-centre } ![Right](/assets/img.png){ .align-right .with-shadow .with-border } ``` ![preview with styling](/assets/images/docmd-preview.png){.with-border .with-shadow .size-medium} ## Captions & Galleries ### Figure Captions Use standard HTML for precise captioning: ```html <figure> <img src="/path/to/image.jpg" alt="Description"> <figcaption>This is the caption</figcaption> </figure> ``` ### Image Galleries Group multiple images into a responsive grid. ```html <div class="image-gallery"> <figure> <img src="/assets/img1.jpg" alt="View 1"> <figcaption>Dashboard</figcaption> </figure> <figure> <img src="/assets/img2.jpg" alt="View 2"> <figcaption>Settings</figcaption> </figure> </div> ``` ## Lightbox (Zoom) If `mainScripts` is enabled (default), any image inside a gallery or any image with the `.lightbox` class will open a full-screen zoom view on click. ```markdown ![Click to Zoom](/assets/diagram.png){ .lightbox } ``` ::: callout tip Always provide descriptive **Alt-Text**. While modern AI agents can "see" images, descriptive text in the markdown source acts as a direct hint for the model's reasoning engine, especially when images contain complex diagrams or architectural flows. ::: --- ## [Markdown Syntax](https://docs.docmd.io/05/content/syntax/) --- title: "Markdown Syntax" description: "Master the basic formatting of docmd: Headings, lists, bold, italic, and more." --- `docmd` uses standard Markdown syntax. This guide covers the essentials for formatting text. ## Text Formatting | Style | Syntax | Example | | :--- | :--- | :--- | | **Bold** | `**text**` | **Bold Text** | | *Italic* | `*text*` | *Italic Text* | | ~~Strikethrough~~ | `~~text~~` | ~~Deleted Text~~ | | `Code` | `` `text` `` | `Inline Code` | ## Technical Elements ### Headings ```markdown # Heading 1 ## Heading 2 ### Heading 3 ``` ::: callout tip AI models (and search engines) rely heavily on a proper heading hierarchy. Always avoid skipping levels (e.g., jumping from `#` to `###`) to ensure the `llms.txt` and search index can accurately map your documentation's context. ::: ### Links ```markdown [Link Text](https://www.example.com) [Relative Link](../section/other-page/) ``` ### Lists * **Unordered:** Use `*` or `-`. * **Ordered:** Use `1.`, `2.`, etc. ### Blocks > This is a blockquote. ## Tables | Header 1 | Header 2 | | :--- | :--- | | Left Align | Centre Align | ## Advanced HTML Because `docmd` is built with `html: true`, you can embed raw HTML directly in your Markdown files for custom styling needs. ```html <div style="color: blue;"> This is a blue div. </div> ``` --- ## [Linking & Referencing](https://docs.docmd.io/05/content/syntax/linking/) --- title: "Linking & Referencing" description: "Master internal cross-linking, external links, and asset referencing." --- To link to another page, use the **relative path** to the `.md` file. ::: callout info "Extension Rewriting" `docmd` automatically converts `.md` extensions to valid HTML links during the build. This ensures links work in your IDE (VS Code) and on the deployed website. ::: | Goal | Syntax | | :--- | :--- | | Same Folder | `[Read Guide](guide.md)` | | Subfolder | `[Read Config](configuration/index.md)` | | Parent Folder | `[Go Back](../index.md)` | ## Anchors (Section Linking) Link to specific headers using the `#slug`. * **Same Page:** `[Jump to Top](#linking--referencing)` * **Cross Page:** `[See Installation](../getting-started/installation.md#global-installation)` ## External & Protocol Links Standard URL syntax works for external sites and protocols. * **HTTPS:** `[Visit Google](https://google.com)` * **Email:** `[Email Support](mailto:help@docmd.io)` * **Phone:** `[Call Us](tel:+123456789)` ## Linking to Assets To allow users to download files, place them in your `assets/` folder. `docmd` will **not** strip the extension for files inside this directory. ```markdown [Download PDF](/assets/manual.pdf) [View Raw Config](/assets/examples/config.js) ``` ::: callout tip "AI Navigation Tip" When cross-linking pages, using descriptive link text (like `[Read about PWA configuration](../plugins/pwa.md)`) instead of `[Click here](../plugins/pwa.md)` helps AI models understand the relationship between different technical topics during contextual analysis. ::: --- ## [Contributing](https://docs.docmd.io/05/contributing/) --- title: "Contributing" description: "Learn how you can contribute to the development, design, and documentation of docmd." --- Thank you for contributing to `docmd`! We appreciate your help in making this tool faster, smarter, and more reliable. ## 🛠️ Development Setup `docmd` is a Monorepo managed with [pnpm](https://pnpm.io/). ### 1. Prerequisites - **Node.js**: v20+ - **pnpm**: v10+ ### 2. Setup Clone the repository and install all workspace dependencies: ```bash git clone https://github.com/docmd-io/docmd.git cd docmd pnpm install ``` ### 3. Running the Dev Server We use workspace filtering to ensure the local CLI is used during development. Start the documentation site and watch for changes in the core engine automatically: ```bash pnpm run dev ``` ### 4. Developer Mode By default, the dev server watches content. To watch internal source code (templates, core engine, plugins), set the environment variable: ```bash # Mac/Linux DOCMD_DEV=true pnpm run dev # Windows (PowerShell) $env:DOCMD_DEV="true"; pnpm run dev ``` ## 🧪 Testing & Quality Before submitting, ensure your changes haven't introduced regressions. 1. **Integration Suite:** Run our universal failsafe to test core engine features, versioning, and redirects: ```bash pnpm test ``` 2. **Conventional Commits:** We follow [Conventional Commits](https://www.conventionalcommits.org/). Use prefixes like `feat:`, `fix:`, or `docs:`. 3. **Copyright Header:** All new files in `packages/` must include the standard project copyright header. Please copy the header from any existing file in the `src/` directory. ## 🚀 Pull Request Workflow 1. **Branch:** Create a branch from `main`. 2. **Code:** Make your changes. 3. **Verify:** Run `pnpm test` and ensure it outputs `✨ ALL SYSTEMS GO`. 4. **Push & Open:** Open a Pull Request against the `main` branch. ### Copyright Header All source files in `packages/` must include the standard copyright header. If you create a new file, please copy the header from an existing file. ```html /*! * -------------------------------------------------------------------- * docmd : the minimalist, zero-config documentation generator. * * @package @docmd/core (and ecosystem) * @website https://docmd.io * @repository https://github.com/docmd-io/docmd * @license MIT * @copyright Copyright (c) 2025-present docmd.io * * [docmd-source] - Please do not remove this header. * -------------------------------------------------------------------- */ ``` ## Code of Conduct Please note that this project operates with a standard Contributor Code of Conduct. By participating in this project you agree to abide by its terms, ensuring a welcoming and respectful environment for everyone. --- ## [Deployment (Deploy Your Website)](https://docs.docmd.io/05/deployment/) --- title: "Deployment (Deploy Your Website)" description: "Learn how to deploy your docmd-generated static site to modern hosting platforms like GitHub Pages, Vercel, and Netlify." --- Because `docmd` generates a pure static site, you can host your documentation literally anywhere that serves HTML. Run the build command and serve the output directory (default: `site/`). ```bash docmd build ``` ::: tabs == tab "GitHub Pages" The most reliable way is using a **GitHub Action**. This ensures your site rebuilds automatically every time you push. **Create `.github/workflows/deploy-docs.yml`** ```yaml name: Deploy docmd on: push: branches: ["main"] permissions: contents: read pages: write id-token: write jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '22', cache: 'npm' } - run: npm install -g @docmd/core - run: docmd build - uses: actions/upload-pages-artifact@v3 with: { path: ./site } - uses: actions/deploy-pages@v4 ``` == tab "Vercel" 1. Connect your GitHub repository. 2. Under Build Settings: * **Build Command:** `npm install -g @docmd/core && docmd build` * **Output Directory:** `site` 3. Click **Deploy**. == tab "Traditional Server" 1. Run `docmd build`. 2. Copy the contents of `site/` to your public directory (e.g., `/var/www/html/docs`). ::: callout tip "SPA Routing" `docmd`'s Single Page Application (SPA) router handles direct URL access gracefully. You **do not** need complex rewrite rules (like `index.html` redirects) on your server. ::: ::: ## Site URL Configuration Always ensure your `siteUrl` is set accurately in `docmd.config.js` if you are using plugins like `sitemap` or `seo` that require absolute URLs. ::: callout tip "AI-Ready Deployments 🤖" When deploying to staging or production, run `docmd build` with the `llms` plugin active. This ensures that even your staging environments provide AI-consumable context via `/llms.txt`, allowing your testing agents to verify your documentation accuracy before going live. ::: --- ## [Basic Usage](https://docs.docmd.io/05/getting-started/basic-usage/) --- title: "Basic Usage" description: "Learn how to initialise a project, organise your markdown files, and build your documentation site." --- Getting started with `docmd` is designed to be instantaneous. This guide explains the core workflow from initialisation to final production build. ## 1. Initialise Your Project To start a new documentation project, create an empty directory and run the `init` command. ```bash mkdir my-guide && cd my-guide docmd init ``` ### The Project Structure After initialisation, your project will follow this clean, intuitive structure: | Folder / File | Purpose | | :--- | :--- | | `docs/` | **Source Folder.** Put all your `.md` files here. | | `assets/` | Static files (images, custom CSS, JS). | | `docmd.config.js` | Your site's brain. Branding, navigation, and plugins. | | `site/` | **Output Folder.** Generated after you run `docmd build`. | ## 2. Launching the Preview You can see your changes in real-time without building the site. Launch the development server: ```bash docmd dev ``` * **URL**: `http://localhost:3000` * **Hot Reload**: Every time you save a `.md` or `.config.js` file, the browser updates instantly. ## 3. Organising Content Every markdown file inside the `docs/` folder becomes a URL. Subfolders are respected automatically. * `docs/index.md` → `/` (Home) * `docs/api.md` → `/api` * `docs/guides/setup.md` → `/guides/setup` > [!TIP] > Use standard Markdown syntax. `docmd` will automatically extract the first `H1` header of your file to use as the page title if not specified in the frontmatter. ## 4. Configuring Navigation `docmd` gives you absolute control over the sidebar. Edit the `navigation` array in `docmd.config.js` to structure your site. ```javascript navigation:[ { title: 'Introduction', path: '/', icon: 'home' }, { title: 'Advanced', icon: 'settings', collapsible: true, // Allow users to collapse this section children:[ { title: 'Configuration', path: '/configuration' }, { title: 'Plugins', path: '/plugins' } ] } ] ``` ## 5. Building for Production When you are ready to deploy, run the build command: ```bash docmd build ``` This generates a highly optimised Single Page Application (SPA) inside the `site/` directory. It is completely static so you can host it on GitHub Pages, Vercel, Netlify, or even a local USB drive. ### Verification Step To verify your production build locally, you can use any static server or run: ```bash docmd dev --preserve ``` ::: callout tip The `--preserve` flag prevents the dev server from overwriting your production `site/` folder with dev-mode assets. ::: --- ## [Installation](https://docs.docmd.io/05/getting-started/installation/) --- title: "Installation" description: "How to install docmd globally or locally using npm, yarn, or pnpm." --- `docmd` is a Node.js package. It requires **Node.js v18.x or higher** installed on your machine. There are several ways you can deploy `docmd` sites. You can run it on-the-fly without installing, or add it permanently to your long term projects. ## Option 1: Zero-Config (Try it instantly) Run `docmd` inside any folder containing markdown files. It will automatically read your files, extract their headers and build a nested navigation sidebar. No configuration or formal setup required. ```bash npx @docmd/core dev -z # Start local dev serve npx @docmd/core build -z # Generate production static site ``` ::: callout warning Zero-Config (`-z`) is currently in `beta`. It is fantastic for quick previews, but for production sites, we recommend initialising a standard configuration file for maximum control. ::: ### Option 2: Project Installation (Recommended) For permanent projects, install `docmd` as dependency to lock your versions. ```bash # 1. Install locally npm install @docmd/core # 2. Initialise your configuration npx @docmd/core init # 3. Start developing npx @docmd/core dev ``` ### Option 3: Global Installation Install once and use the `docmd` command anywhere on your machine. ```bash npm install -g @docmd/core docmd dev # Start the local dev server docmd build # Generate the production static site ``` ## CDN Installation (Browser Only) ::: callout warning Developer Use Only This method is **not** for building documentation sites. It is for developers who want to embed the `docmd` parsing engine inside another web application (like a CMS or Live Preview tool). ::: If you are building a React/Vue/Vanilla JS app and want to render `docmd` syntax on the fly without a backend, use the browser build: ```html <!-- 1. Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- 2. Engine --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` See the [Browser API](/advanced/browser-api) guide for implementation details. ## Setup Troubleshooting ::: callout warning Permission Errors If you see `EACCES` errors on macOS/Linux during global installation, it means you don't have permission to write to global directories. **Fix:** Run `sudo npm install -g @docmd/core`. ::: ::: callout info Windows Powershell If you receive an error about "running scripts is disabled on this system", run this command in PowerShell as Administrator: `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` ::: --- ## [Zero-Config Mode](https://docs.docmd.io/05/getting-started/zero-config/) --- title: "Zero-Config Mode" description: "Run docmd without any configuration file. Perfect for quick previews and rapid prototyping." --- `docmd` features a high-intelligence auto-detection engine. This allows you to generate professional documentation for any project without writing a single line of configuration. ## Usage Simply add the `-z` or `--zero-config` flag to your command. ```bash # Start dev server docmd dev -z # Build static site docmd build -z ``` ## How It Works When running in Zero-Config mode, `docmd` performs the following steps: 1. **Smart Directory Detection**: It scans your project for one of these documentation folders: `docs/`, `src/docs/`, `documentation/`, or `content/`. If none are found, `docmd` will gracefully exit with a helpful message. 2. **Automatic Index Fallback**: If no `index.md` or `README.md` is found in your documentation folder, `docmd` automatically designates the first file it finds as the temporary record for your root domain. No more 404s on fresh projects! 3. **Automatic Titling**: It reads your `package.json`. If found, it automatically sets your site `title` and `description` to match your npm package metadata. 4. **Recursive Routing**: It scans all folders and Markdown files to build a nested navigation sidebar. 5. **Sensible Defaults**: It applies the `default` theme with system-aware light/dark mode and enables the `search` plugin. ## Safety & Performance Zero-Config is engineered for safety and predictability: * **Context Awareness**: By limiting execution to specific folders, `docmd` avoids accidentally indexing your entire project root (which might contain thousands of unrelated files like logs or build artifacts). * **Recursion Limit**: The engine ignores `node_modules` and hidden folders (like `.git`) and restricts depth to prevent infinite loops. * **Bail-out Logic**: If no candidate directory is found, or if the directory contains no Markdown files, `docmd` will immediately stop and provide a clean CLI warning rather than hanging. ::: callout tip Zero-config is excellent for **AI Agents**. Because the structure is predictable and derived from the filesystem, an AI can easily predict where files will be located and update documentation without needing to parse complex configuration schemas. ::: --- ## [docmd: The Minimalist Docs Generator](https://docs.docmd.io/05/) --- title: "docmd: The Minimalist Docs Generator" description: "Generate beautiful, lightweight, and blazing-fast documentation sites directly from your Markdown files. Zero clutter, just content." --- ```text _ _ _| |___ ___ _____ _| | | . | . | _| | . | |___|___|___|_|_|_|___| ``` **Generate beautiful, lightweight documentation sites directly from your Markdown files. Zero clutter, just content.** `docmd` bridges the gap between simple static site generators and heavy, framework-driven applications. It processes standard Markdown into highly optimised static HTML, while delivering a buttery-smooth Single Page Application (SPA) experience for your users. ::: button "Quick Start" /getting-started/installation ::: button "GitHub" external:https://github.com/docmd-io/docmd color:#333 ::: button "Explore Features" /getting-started/basic-usage color:#333 ## Quick Start **Requires [Node.js](https://nodejs.org/) installed on your machine.** Deploy a beautiful, searchable documentation site in seconds. No framework knowledge required. **1. Install `docmd` as dependency in your project to lock your versions.** ```bash npm install @docmd/core # Install locally (Recommended) npx @docmd/core init # Initialise your configuration npx @docmd/core dev # Start developing ``` **2. Install Globally** ```bash npm install -g @docmd/core # Enables docmd to run anywhere on your local machine ``` **3. You can run `docmd` on-the-fly without installing it or setting up any config.** ```bash npx @docmd/core dev -z # Start local dev server instantly ``` Open `http://localhost:3000` in your browser. Any changes you make to the files in the `docs/` folder will instantly update on your screen. ## Why choose docmd? We believe writing documentation should be as frictionless as possible. You shouldn't need to configure complex JavaScript frameworks just to publish text. We also believe that modern tools should be built for **both humans and machines**. That's why `docmd` is arguably the most AI-friendly static documentation generator on the market, ready to be immediately digested by the newest wave of LLMs directly out of the box. <div class="image-gallery" style="grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));"> ::: card AI-Native Optimisation `docmd` transforms your documentation into a structured API for LLMs, allowing them to ingest your entire project context perfectly in single-shot prompts. ::: ::: card Zero Config & Auto-Routing Run `docmd dev -z` in your project. We automatically scan for a expected documentation folders, extract H1 headers as page titles, and build a nested, collapsible navigation tree instantly. No `config.js` needed to start. ::: ::: card SPA Performance We serve static HTML for maximum SEO and speed. Once loaded, `docmd` transitions between pages as a high-performance Single Page Application, no full browser reloads, just instant content swaps. ::: ::: card Smart Offline Search Built-in full-text search with fuzzy matching and section-deep linking. The entire search index runs in-browser, meaning it works 100% offline and in air-gapped environments. ::: ::: card Modern & Responsive Responsive by design. Includes a beautiful default theme with native Light/Dark mode, sticky versioning, and mobile-optimised sidebars out of the box. ::: ::: card Isomorphic Rendering The same engine that builds your static site can run natively in the browser. Embed live documentation previews or interactive editors directly into your own web applications. ::: </div> ## Rich Content Out of the Box `docmd` supports standard Markdown and extends it with intuitive components for professional structure. ::: tabs == tab "Interactive Components" Highlight critical information with Callouts and native Buttons. ::: callout tip Performance Tip Nest containers inside each other to create complex, usable layouts without touching HTML or CSS. ::: ::: button "Read about Containers" /content/containers/callouts == tab "Native Diagrams" Create professional diagrams using **Mermaid.js** syntax directly in your markdown. ```mermaid graph LR MD[Markdown] --> Build[docmd Build] Build --> Static[Static HTML] Build --> LLM[llms-full.txt] ``` == tab "Code Precision" Automatic syntax highlighting with `highlight.js`, including one-click copy buttons and multi-language support. ```javascript // docmd.config.js export default defineConfig({ title: 'My Project', layout: { spa: true } }); ``` ::: Ready to build? [Install docmd](/getting-started/installation) or see [Zero-Config Mode](/getting-started/zero-config) in action. --- ## [Analytics Integration](https://docs.docmd.io/05/plugins/analytics/) --- title: "Analytics Integration" description: "Integrate Google Analytics or other tracking services into your docmd site." --- `docmd` provides a built-in plugin for web analytics. This allows you to understand your audience and track page views with ease. ## Enabling Analytics Add the `analytics` plugin to your `plugins` object in `docmd.config.js`. ```javascript module.exports = { plugins: { analytics: { // For Google Analytics 4 (Recommended) googleV4: { measurementId: 'G-XXXXXXXXXX' }, // For Google Universal Analytics (Legacy) googleUA: { trackingId: 'UA-XXXXXXXXX-Y' } } } }; ``` ## Configuration Options ### Google Analytics 4 (GA4) * **Key**: `googleV4` * **Requirement**: `measurementId` (String). * **Behaviour**: Injects the `gtag.js` snippet into every page. ### Universal Analytics (UA) * **Key**: `googleUA` * **Requirement**: `trackingId` (String). * **Behaviour**: Injects the legacy `analytics.js` script. ## Important Considerations * **SPA Tracking**: The `docmd` analytics plugin is SPA-aware. It automatically sends a "Page View" event on every `docmd:page-mounted` trigger, ensuring your metrics are accurate despite the client-side routing. * **Privacy**: Be mindful of local regulations (GDPR/CCPA). You can use [Custom JS](/advanced/client-side-events) to implement custom consent banners. ::: callout tip "AI Bot Tracking 🤖" While standard analytics track human visitors, `docmd` sites also generate high traffic from AI crawlers. Use server-side logs or advanced privacy-first analytics (like Plausible or Fathom) if you want to distinguish between human readers and AI-agent context retrieval sessions. ::: --- ## [Building Plugins](https://docs.docmd.io/05/plugins/building-plugins/) --- title: "Building Plugins" description: "A guide for developers on how to create and share custom docmd plugins." --- Plugins are the primary way to extend `docmd`. They allow you to hook into the Markdown parser, inject HTML into the layout, and execute logic after builds. ## Anatomy of a Plugin A plugin is a JavaScript object exporting specific hook functions. | Hook | Purpose | | :--- | :--- | | `markdownSetup(md)` | Access the `markdown-it` instance for custom rules. | | `injectHead(config)` | Injects HTML into the `<head>`. | | `injectBody(config)` | Injects HTML at the bottom of the `<body>`. | | `getAssets()` | Returns a list of CSS/JS files to copy/inject. | | `onPostBuild(ctx)` | Executes logic after all HTML is generated. | ## Creating a Local Plugin You can create a plugin file in your project, for example `my-plugin.js`: ```javascript // my-plugin.js module.exports = { // 1. Extend Markdown markdownSetup: (md) => { // Example: Add a custom container or rule // md.use(require('markdown-it-emoji')); }, // 2. Inject Styles/Scripts injectHead: (config) => { return `<meta name="custom-plugin" content="active">`; }, // 3. Post-Build Action onPostBuild: async ({ config, pages, outputDir, log }) => { log('Plugin: Build finished! Processed ' + pages.length + ' pages.'); } }; ``` To use it, require it in your `docmd.config.js`: ```javascript // docmd.config.js module.exports = { // ... plugins: { './my-plugin.js': {} // Key is path, Value is options object } }; ``` ## Plugin API Reference ### `getAssets()` Used to inject client-side scripts or CSS files. ```javascript getAssets: () => { return [ { src: path.join(__dirname, 'client-script.js'), // Source file dest: 'assets/js/plugin.js', // Destination in site/ type: 'js', // 'js' or 'css' location: 'body' // 'head' or 'body' } ]; } ``` ### `onPostBuild({ config, pages, outputDir, log })` * `config`: The full project configuration object. * `pages`: Array of processed page objects `{ outputPath, frontmatter, htmlContent, searchData }`. * `outputDir`: Absolute path to the build output folder. * `log`: Helper function to print messages to the CLI console. ## Publishing a Plugin To share your plugin with the community: 1. Name your package `docmd-plugin-<name>` (recommended). 2. Export the plugin object as the default export. 3. Publish to NPM. Users can then install it via `npm install docmd-plugin-name` and add it to their config: ```javascript plugins: { 'docmd-plugin-name': { /* options */ } } ``` ::: callout tip "AI-Generated Plugins 🤖" The `docmd` plugin API is designed to be **LLM-Optimal**. Because the hooks are simple, stateless, and use standard JavaScript objects, an AI Agent can perfectly generate a complete plugin (e.g., for custom Markdown containers or third-party integrations) from a single prompt with minimal errors. ::: --- ## [Plugin Installer](https://docs.docmd.io/05/plugins/installer/) --- title: "Plugin Installer" description: "How to use the docmd plugin installer to easily add and configure plugins." --- The `docmd` plugin installer is a built-in cross-platform utility that fully automates downloading npm packages and injecting their configurations directly into your `docmd.config.js`. ## Adding Official Plugins To add an official docmd plugin, you can simply run its short name: ```bash docmd add analytics ``` ### What happens under the hood? 1. **Package Manager Detection:** The installer scans your project to detect if you use `npm`, `pnpm`, `yarn`, or `bun`. 2. **Registry Lookup:** It translates `analytics` to `@docmd/plugin-analytics` via the official registry. 3. **Silent Installation:** It silently runs the respective install command (e.g. `pnpm add @docmd/plugin-analytics`) without polluting your terminal. 4. **Configuration Injection:** It surgically parses your `docmd.config.js` and injects `'analytics': {}` into your `plugins` object natively. ## Removing Plugins To safely uninstall a plugin and remove its configuration from your active environment: ```bash docmd remove analytics ``` This will cleanly uninstall the dependency using your active package manager and elegantly strip the active configuration bounds from your `docmd.config.js` without breaking your formatting or code schema. ## Third-Party (Community) Plugins The installer also serves as a generic package installer. If you provide a plugin name that is *not* in the official docmd registry, it elegantly falls back to installing that literal module: ```bash docmd add docmd-custom-theme-plugin ``` 1. The installer downloads `docmd-custom-theme-plugin` natively. 2. It assumes an empty configuration standard and injects `'docmd-custom-theme-plugin': {}` securely into your active configuration file. ## Advanced Usage ### Verbose Logging By default, the installer runs completely silently to keep your terminal perfectly clean. If you are experiencing network issues or want to see the underlying package manager logs, run with the `--verbose` (or `-v`) flag: ```bash docmd add search --verbose ``` This will print the full NPM/Yarn/PNPM/Bun streaming output and detailed Node.js stack traces if an error occurs. --- ## [AI Support (llms.txt)](https://docs.docmd.io/05/plugins/llms/) --- title: "AI Support (llms.txt)" description: "Turn your documentation into a first-class API for Large Language Models using the native llms.txt and llms-full.txt generation." --- `docmd` is built for a world where both humans and machines consume documentation. The `llms` plugin automatically transforms your site into a structured, high-context data stream that allows AI agents and Large Language Models (LLMs) to understand your project with nearly 100% precision. ## Enabling AI Support The plugin is bundled with `@docmd/core` and can be activated with a single line: ```javascript // docmd.config.js module.exports = { url: 'https://docs.myproject.com', // Required for absolute link generation plugins: { llms: {} } }; ``` ## What it Generates When enabled, `docmd` generates two specialized files at the root of your production output: ### 1. `llms.txt` (The Index) A standardised, minimalist Markdown file that map out your site's hierarchy. AI tools like **Cursor**, **ChatGPT Search**, and **Perplexity** can use this to crawl your site's structure efficiently without downloading heavy HTML. ### 2. `llms-full.txt` (The Context Payload) This is a `docmd`-specific innovation. It concatenates the raw, high-fidelity content of your **entire** documentation project into one single massive text file. * **Zero Noise**: Strips CSS, JS, and UI clutter. * **High Context**: Preserves headings, code blocks, and relationships. * **Total Awareness**: Users can upload this single file to ChatGPT or Claude to give the model immediate, deep knowledge of your entire library in one prompt. ## Managing AI Context You can control what parts of your site are visible to AI models using frontmatter. ### Excluding a Page If a page contains sensitive information or internal notes you don't want AI models to learn: ```yaml --- title: "Internal Dev Secrets" llms: false --- ``` ::: callout tip By hosting an `llms-full.txt` file, you are essentially providing an **Open API for AI Models**. This makes your project the preferred choice for developers working with AI assistance, as they can reliably get accurate answers without your docs "hallucinating" or being outdated by the model's training cutoff. ::: --- ## [Mermaid Diagrams](https://docs.docmd.io/05/plugins/mermaid/) --- title: "Mermaid Diagrams" description: "Native support for Mermaid.js. Create flowcharts, sequence diagrams, and pie charts directly in your Markdown files." --- `docmd` includes native, zero-config support for [Mermaid.js](https://mermaid.js.org/). You can create professional diagrams using simple text-based syntax without leaving your Markdown file. ## Why use Mermaid in docmd? * **Zero Scripting**: No need to include external scripts. `docmd` detects the usage and injects the rendering engine automatically. * **Theme Aware**: Diagrams automatically shift colours between **Light** and **Dark** modes to match your site's theme. * **Lazy Loading**: For optimum page speed, diagrams are only initialised once they enter the viewport. ## Examples ### Flowchart Flowcharts are used to represent workflows or processes. They show the steps as boxes of various kinds, and their order by connecting them with arrows. ````markdown ```mermaid graph TD A[Start] --> B{Is it working?} B -->|Yes| C[Great!] B -->|No| D[Debug] D --> E[Fix the issue] E --> B C --> F[Deploy] ``` ```` ```mermaid graph TD A[Start] --> B{Is it working?} B -->|Yes| C[Great!] B -->|No| D[Debug] D --> E[Fix the issue] E --> B C --> F[Deploy] ``` ### Sequence Diagram Sequence diagrams show how processes operate with one another and in what order. They capture the interaction between objects in the context of a collaboration. ````markdown ```mermaid sequenceDiagram participant User participant Browser participant Server participant Database User->>Browser: Enter URL Browser->>Server: HTTP Request Server->>Database: Query Data Database-->>Server: Return Results Server-->>Browser: HTTP Response Browser-->>User: Display Page ``` ```` ```mermaid sequenceDiagram participant User participant Browser participant Server participant Database User->>Browser: Enter URL Browser->>Server: HTTP Request Server->>Database: Query Data Database-->>Server: Return Results Server-->>Browser: HTTP Response Browser-->>User: Display Page ``` ## Pie Chart Pie charts are circular statistical graphics divided into slices to illustrate numerical proportions. ````markdown ```mermaid pie title Browser Usage Statistics "Chrome" : 64.5 "Safari" : 18.2 "Firefox" : 8.5 "Edge" : 4.8 "Other" : 4.0 ``` ```` ```mermaid pie title Browser Usage Statistics "Chrome" : 64.5 "Safari" : 18.2 "Firefox" : 8.5 "Edge" : 4.8 "Other" : 4.0 ``` ## Git Graph Git graphs visualize Git branching and merging operations, making it easier to understand version control workflows. ````markdown ```mermaid gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop commit branch feature checkout feature commit checkout main merge feature commit ``` ```` ```mermaid gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop commit branch feature checkout feature commit checkout main merge feature commit ``` ## XY Chart XY charts display data as a series of points on a coordinate plane, useful for showing correlations and trends. **Code:** ````markdown ```mermaid xychart-beta title "Sales Revenue by Quarter" x-axis [Q1, Q2, Q3, Q4] y-axis "Revenue (in $1000)" 0 --> 100 bar [50, 60, 70, 85] line [45, 55, 75, 80] ``` ```` ```mermaid xychart-beta title "Sales Revenue by Quarter" x-axis [Q1, Q2, Q3, Q4] y-axis "Revenue (in $1000)" 0 --> 100 bar [50, 60, 70, 85] line [45, 55, 75, 80] ``` ::: callout tip Mermaid diagrams are highly readable by LLMs. When an AI model reads your `llms-full.txt`, it can "see" the logic flow of your diagrams as text, making it much better at explaining complex architectural relationships in your project. ::: --- ## [PWA Plugin](https://docs.docmd.io/05/plugins/pwa/) --- title: "PWA Plugin" description: "Turn your documentation into a blazingly fast installable App using the zero-config PWA plugin." --- # PWA Plugin The `@docmd/plugin-pwa` allows you to instantly turn your documentation site into a **Progressive Web App (PWA)** with a single line of configuration. Once enabled, it handles everything: the Web Manifest, PWA meta tag injection, an intelligent Service Worker, and automatic offline caching. ## Installation This plugin ships bundled with `@docmd/core` and does not require a separate install. ## Enabling the Plugin Add `pwa` under the `plugins` object in `docmd.config.js`: ```javascript // docmd.config.js module.exports = { plugins: { pwa: {} // That's it. The plugin is now active! } } ``` ## What it Generates When `docmd build` runs with `pwa` active, three things are automatically generated and injected into your output: | File / Injection | Description | | :--- | :--- | | `manifest.webmanifest` | Declares your site as an installable app with name, theme colours, and icons | | `service-worker.js` | Intercepts network requests, caches assets, and powers offline support | | `<meta>` tag injection | Injects `mobile-web-app-capable`, `apple-mobile-web-app-capable`, and `theme-color` into every page's `<head>` | ## How Caching Works The Service Worker uses a **network-first with cache fallback** strategy: 1. **On page load**, it attempts to fetch from the network first. If the network responds successfully, the freshest version is stored and returned. 2. **On subsequent visits**, if a cached version exists, it is returned instantly from the cache while the network is simultaneously checked in the background and the cache is updated silently. 3. **Offline**: If the network is unreachable and a cached version exists, the cached version is returned easily. ## Automatic Cache Busting Every `docmd build` generates a new Service Worker with a unique `CACHE_NAME` timestamp fingerprint (e.g., `docmd-cache-1741267200000`). When the browser fetches the new worker, it automatically activates it and the old cache is purged immediately via the Service Worker's `activate` lifecycle. > **No manual cache clearing is needed.** Redeploying your site is all it takes. ## Background Auto-Updates The plugin registers a silent polling interval that checks the server for a new Service Worker every **5 minutes** while the user has your site open in their browser tab. If a new Site Worker is found (i.e. you have redeployed), it is staged and installed during activation on the next navigation. ## Disabling or Removing the Plugin ### Temporarily Disable ```javascript pwa: { enabled: false } ``` ### Fully Remove Simply delete the `pwa` block from your `plugins`. The next time you run `docmd build`, a new manifest is not generated. When users visit the site, docmd's client-side bootstrap (`docmd-main.js`) checks for the presence of `<link rel="manifest">`. If it's missing but a Service Worker is registered, it automatically **unregisters all existing ghost workers** and clears the cached shell - requiring no user action. > [!NOTE] > The `manifest.webmanifest` and `service-worker.js` files from a previous build persist on disk until you clear your output directory (`site/` by default) with `docmd build` or `rm -rf site`. This is a filesystem artifact, not an active PWA. ## Configuration Reference All fields are optional. The defaults are designed for zero-config use. ```javascript module.exports = { plugins: { pwa: { // --- Icon Configuration --- // Priority: pwa.logo > config.logo > config.favicon > (no icons) logo: 'assets/images/app-icon.png', // Path relative to your src folder // Or for full manual control: icons: [ { src: '/assets/images/icon-192.png', sizes: '192x192', type: 'image/png' }, { src: '/assets/images/icon-512.png', sizes: '512x512', type: 'image/png' } ], // --- Manifest Colours --- themeColor: '#1e293b', // Browser chrome / top bar accent bgColor: '#ffffff', // Splash screen background during install // --- Disable the plugin entirely --- enabled: false } } } ``` ### Icon Resolution Priority docmd resolves your PWA icon from the following cascade: 1. `pwa.icons` - Manual array, used as-is 2. `pwa.logo` - Single image path, used for both 192x192 and 512x512 entries 3. `config.logo` - Your global site logo 4. `config.favicon` - Your global favicon 5. *(No icons declared in manifest)* - If none of the above are set ## Testing Locally Browsers restrict Service Workers to `https://` or `localhost`. Use: ```bash docmd dev ``` Open Chrome DevTools → **Application** → **Manifest** and **Service Workers** to view the activated registration in real-time. Safari → **Develop** → **Service Workers** panel works equally well. --- ## [Search Plugin](https://docs.docmd.io/05/plugins/search/) --- title: "Search Plugin" description: "Configure docmd's zero-config, privacy-focused offline search engine with section-deep linking." --- Every `docmd` project includes a powerful, full-text search engine built-in. Unlike traditional search tools that require external indexing services or server-side databases, `docmd` search runs **entirely in the user's browser**. ## How it Works 1. **Build Phase**: `docmd` analyses your markdown and generates a compressed `search-index.json`. 2. **Section Awareness**: We don't just index pages; we index **headers**. If a keyword appears in a specific `###` section, the search result will link the user directly to that section using its permalink. 3. **Local Execution**: When a user types, the matching happens instantly in memory using `MiniSearch`. It works perfectly in air-gapped environments or on slow connections. ## Configuration The search plugin is **active by default**. You can customise its presence via the `layout` object. ```javascript // docmd.config.js module.exports = { layout: { optionsMenu: { components: { search: true // Set to false to remove the search button } } } } ``` ## Advanced Usage ### Excluding Content To prevent a specific page from being indexed (e.g., utility pages), add `noindex` to the frontmatter: ```yaml --- title: "Private Info" noindex: true --- ``` ### Keyboard Shortcuts We've optimised the search experience with native feeling shortcuts: * `Cmd + K` (Mac) or `Ctrl + K` (Windows) to open. * `ESC` to close. * `Arrow Keys` and `Enter` to navigate. ## Privacy First Because the search happens entirely on the client, no data - not even keystrokes - is ever sent to a server. This makes `docmd` the Gold Standard for documentation search in privacy-sensitive industries (Healthcare, Finance, Security). ## Comparison Many documentation generators (like Docusaurus) rely on **Algolia DocSearch**. While Algolia is powerful, it introduces friction: | Feature | docmd Search | Algolia / External | | :--- | :--- | :--- | | **Setup** | **Zero Config** (Automatic) | Complex (API Keys, CI/CD crawling) | | **Privacy** | **100% Private** (Client-side) | Data sent to 3rd party servers | | **Offline** | **Yes** | No | | **Cost** | **Free** | Free tier limits or Paid | | **Speed** | **Instant** (In-memory) | Fast (Network latency dependent) | --- ## [SEO & Meta Tags](https://docs.docmd.io/05/plugins/seo/) --- title: "SEO & Meta Tags" description: "Automatic SEO optimisation, Open Graph integration, and AI Scraper control for your docmd site." --- The `seo` plugin ensures your documentation is discoverable by search engines and looks professional when shared on social media. It handles technical meta-tag injection automatically. ## Quick Setup ```javascript // docmd.config.js module.exports = { plugins: { seo: { defaultDescription: 'The official documentation for Project X.', openGraph: { defaultImage: '/assets/og-hero.jpg' // Shown on Twitter/LinkedIn }, aiBots: { block: true // Automatically block common AI scrapers (GPTBot, etc) } } } } ``` ## Automatic Features ### 1. Smart Excerpts If you forget to provide a `description` in your file's frontmatter, the SEO plugin automatically constructs a **150-character fallback description** from the beginning of your content. This ensures you never have "empty" snippets in Google search results. ### 2. AI Scraper Control With `aiBots.block: true`, `docmd` injects `noindex` tags targetting 12+ major AI crawler agents (including `GPTBot`, `ClaudeBot`, and `Google-Extended`). This is the easiest way to keep your documentation out of bulk training datasets while remaining visible to humans. ## Per-Page Overrides For maximum SEO precision, use the `seo` object in your Markdown frontmatter. ```yaml --- title: "Advanced Setup Guide" seo: description: "Learn how to configure our enterprise-grade security clusters in minutes." image: "/assets/guides/setup-social.png" noindex: false keywords: ["security", "cluster", "enterprise"] --- ``` ## Structured Data (LD+JSON) `docmd` can automatically generate [Article Schema](https://developers.google.com/search/docs/appearance/structured-data/article) to help Search Engines display rich snippets. ```yaml --- title: "How to Build a docmd Plugin" seo: ldJson: true --- ``` ::: callout tip A well-configured SEO plugin helps AI-powered search engines (like SearchGPT or Perplexity) summarize your site accurately. By providing clear descriptions and blocked bots, you control exactly how AI models perceive and source your content online. ::: --- ## [Sitemap Plugin](https://docs.docmd.io/05/plugins/sitemap/) --- title: "Sitemap Plugin" description: "Automatically generate sitemap.xml to improve search engine discoverability." --- The `sitemap` plugin generates a standard `sitemap.xml` file during the build process. This ensures your content is indexed correctly by Google and other crawlers. ## Enabling the Plugin ```javascript // docmd.config.js module.exports = { siteUrl: 'https://mydocs.com', // Required for absolute URLs plugins: { sitemap: { defaultChangefreq: 'weekly', // Default: weekly defaultPriority: 0.8 // Default: 0.8 } } }; ``` ## Frontmatter Overrides You can control sitemap behaviour on a per-page basis. * **Exclude Page:** `sitemap: false` * **Custom Settings**: ```yaml --- sitemap: changefreq: 'daily' priority: 1.0 --- ``` ## How It Works 1. **Scanning**: The plugin scans every HTML file generated during the build. 2. **Absolute Mapping**: It uses your `siteUrl` to generate the final URLs. Ensure this is defined without a trailing slash. 3. **Generation**: It writes `sitemap.xml` to the root of your output directory. ::: callout tip "AI Discoverability 🤖" While traditional search engines use sitemaps, **AI Agents** and **Knowledge Crawlers** use them to prioritise which pages to ingest into their training or RAG sets first. A well-configured sitemap ensures your most important sections (like "Guides") are processed before minor utility pages. ::: --- ## [Using Plugins](https://docs.docmd.io/05/plugins/usage/) --- title: "Using Plugins" description: "How to enable and configure docmd's powerful plugin ecosystem." --- `docmd` features a modular architecture. While the core engine handles Markdown conversion and routing, specialized features are implemented via plugins. ## Enabling Core Plugins Most official plugins ship bundled with `@docmd/core` and simply need to be enabled in your `docmd.config.js`. ```javascript // docmd.config.js module.exports = { plugins: { // 1. Search (Built-in offline search) search: {}, // 2. SEO (Meta tags & canonical URLs) seo: { aiBots: false }, // 3. PWA (Mobile App support) pwa: { themeColor: '#0097ff' }, // 4. LLM (AI Context generation) llms: { fullContext: true }, // 5. Mermaid (Native Diagrams) mermaid: {} } } ``` ## Plugin Lifecycle Plugins hook into different stages of the build process: * **`onPreBuild`**: Modifies the file list or adds files before compilation. * **`onPostBuild`**: Generates secondary artifacts (like `sitemap.xml` or `service-worker.js`). * **`generateMetaTags`**: Injects custom HTML into the `<head>` of every page. * **`generateScripts`**: Injects JavaScript before the closing `</body>` tag. ## External Plugins To use a plugin from npm, install it and require it in your config. ```bash npm install @docmd/plugin-analytics ``` ```javascript // docmd.config.js const Analytics = require('@docmd/plugin-analytics'); module.exports = { plugins: { analytics: { googleV4: { measurementId: 'G-XXXX' } } } } ``` ::: callout tip Our plugin architecture is designed to be **transparent**. Every meta-tag and script injected by a plugin is clearly defined and traceable. This allows AI models to understand exactly how your site's functionality is being extended without guessing. ::: --- ## [Recipe: Optimising for AI Agents](https://docs.docmd.io/05/recipes/ai-optimisation/) --- title: "Recipe: Optimising for AI Agents" description: "How to structure your docmd site to be perfectly ingestible by LLMs and AI Agents." --- `docmd` is uniquely positioned as an "AI-Ready" documentation engine. By following these best practices, you ensure that AI models (like ChatGPT, Claude, and GitHub Copilot) can understand and support your project with high accuracy. ## 1. Enable the LLM Plugin The first step is enabling the native LLM plugin. This generates structured context files that AI agents crave. ```javascript // docmd.config.js module.exports = { plugins: { llms: { fullContext: true // Generates llms-full.txt (highly recommended) } } } ``` ## 2. Semantic Heading Hierarchy AI models use headings to build a mental map of your documentation. * **Don't skip levels**: Always go H1 → H2 → H3. * **Be Descriptive**: Instead of "Setup," use "Installing CLI via NPM." * **One H1 Per Page**: Ensure your frontmatter `title` is descriptive, as `docmd` uses it as the primary H1. ## 3. Code Block Metadata When providing code examples, always specify the language. This helps the LLM parser apply the correct syntax rules during context retrieval. ````markdown ```typescript // Good: Language is specified const docmd = new Engine(); ``` ```` ## 4. Using the `llms-full.txt` Pipeline The `llms-full.txt` file is a concatenated version of your entire documentation. * **Prompting Tip**: Tell your AI: *"Use the structure in /llms.txt and the full content in /llms-full.txt to answer my questions about this project."* * **Customisation**: Use `llms: false` in frontmatter to exclude private or internal-only pages from this public AI context file. ## 5. Descriptive Image Alt-Text While AI is getting better at vision, text is still the most reliable way to provide context. descriptive `alt` text in your images ensures that even if the AI doesn't "see" the image, it understands its purpose in the build. --- ## [Recipe: Adding Custom Fonts](https://docs.docmd.io/05/recipes/custom-fonts/) --- title: "Recipe: Adding Custom Fonts" description: "Personalize your documentation by importing Google Fonts." --- `docmd` uses CSS variables to manage typography. Changing your site's font is as easy as creating a custom stylesheet. ## 1. Create a CSS File Create a file in your project (e.g., `assets/css/fonts.css`). Go to [Google Fonts](https://fonts.google.com), find the font you want (like *Inter* or *Fira Code*), and use the `@import` method. Then, assign that font to the docmd root variables. ```css /* assets/css/fonts.css */ /* Import the fonts */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Fira+Code&display=swap'); :root { /* Override the default sans-serif font */ --font-family-sans: "Inter", -apple-system, BlinkMacSystemFont, sans-serif; /* Override the monospace (code block) font */ --font-family-mono: "Fira Code", monospace; } ``` ## 2. Register the Stylesheet Open your `docmd.config.js` and add the path to your new CSS file in the `theme.customCss` array. ```javascript module.exports = { // ... theme: { name: 'sky', appearance: 'light', customCss:[ '/assets/css/fonts.css' // Path is relative to the generated site/ root ] } } ``` Restart your `docmd dev` server. Your entire site will now use your custom typography! --- ## [Recipe: Adding a Custom Favicon](https://docs.docmd.io/05/recipes/favicon/) --- title: "Recipe: Adding a Custom Favicon" description: "How to add a custom favicon to your documentation site." --- A favicon is the small icon that appears in the browser tab next to your page title. `docmd` makes it easy to add your own. ## 1. Prepare your image You can use `.ico`, `.png`, or `.svg` files. For the best compatibility, an `.ico` file is recommended. ## 2. Add to Assets Place your image file in your project's assets directory. ```bash # Example structure my-project/ ├── assets/ │ └── my-icon.ico <-- Your file here ├── docs/ └── docmd.config.js ``` ## 3. Update Configuration Open `docmd.config.js` and update the `favicon` property with the path relative to the output root. ```javascript module.exports = { // ... // Points to site/assets/my-icon.ico favicon: '/assets/my-icon.ico', // ... }; ``` ## 4. Build Run `docmd build` (or `docmd dev`). `docmd` will automatically copy your asset file to the site build and link it in the `<head>` of every page. --- ## [Recipe: Creating a Landing Page](https://docs.docmd.io/05/recipes/landing-page/) --- title: "Recipe: Creating a Landing Page" description: "How to build a custom landing page using noStyle." --- Sometimes you want your `index.html` (the home page) to look completely different from your documentation - like a product marketing page. `docmd` makes this easy with **No-Style Pages**. ## The Concept By adding `noStyle: true` to your frontmatter, `docmd` strips away the sidebar, header, and default CSS, giving you a blank canvas while still keeping helpful meta tags. ## Implementation Create or edit `docs/index.md`: ```html --- title: "My Product" description: " The best product ever." noStyle: true components: meta: true # Keep SEO tags favicon: true # Keep favicon scripts: false # Disable default docmd scripts customHead: | <style> body { font-family: sans-serif; margin: 0; } .hero { background: #111; color: #fff; padding: 100px 20px; text-align: centre; } .btn { background: #3b82f6; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; } </style> --- <div class="hero"> <h1>Welcome to My Product</h1> <p>The ultimate solution for X, Y, and Z.</p> <br> <a href="/getting-started/" class="btn">Read the Docs →</a> </div> <div class="features"> <!-- Your custom HTML features grid here --> </div> ``` This page will be built as `index.html` but will look exactly like your custom HTML, serving as a perfect entry point to your documentation. --- ## [Recipe: Documentation Writing Guide](https://docs.docmd.io/05/recipes/writing-guide/) --- title: "Recipe: Documentation Writing Guide" description: "Best practices for writing clear, scannable, and effective documentation with docmd." --- Great documentation isn't just about correct information; it's about how that information is structured. This guide covers the best practices for using `docmd` features to help your readers. ## Scannability is Everything Users rarely read documentation line-by-line. They scan for answers. * **Use Descriptive Headings:** Instead of "Setup," use "Installing the CLI via NPM." * **Keep Paragraphs Short:** Break up large walls of text into 2-3 sentence chunks. * **Use Bold Text:** Highlight key terms, file paths, or commands so they pop while scanning. ## Choosing the Right Container `docmd` provides several containers. Using them correctly improves the user's mental model. ### Callouts vs. Cards * **Use Callouts** for "interruptions." Use `tip` for helpful shortcuts, `warning` for things that might break, and `danger` for critical errors. * **Use Cards** for "grouping." Cards are great for feature lists on a homepage or summarizing a large section. ### Steps for Tutorials Whenever you have more than two actions the user must perform in order, use the `::: steps` container. It provides a visual timeline that feels much more encouraging than a plain numbered list. ## Linking Best Practices Since `docmd` generates a Single Page Application, navigating between pages is instant. * **Use Relative Paths:** Always link using `./file.md` or `../folder/file.md`. This ensures your links work in your code editor (VS Code), on your web server, and even in offline mode. * **Self-Describing Links:** Avoid "Click here." Instead, use "[Read the Installation Guide](/getting-started/installation)." ## Organising Code Blocks * **Specify Languages:** Always add the language tag (e.g., ` ```javascript `) to enable syntax highlighting. * **Copy Buttons:** Remember that `docmd` automatically adds a copy button to every code block, so you don't need to ask users to "copy and paste" manually. --- ## [Release Note for docmd 0.5.0](https://docs.docmd.io/05/release-notes/0-5-0/) --- title: "Release Note for docmd 0.5.0" description: "PWA & AI First docmd 0.5.0 Release Notes" --- v0.5.0 marks a massive evolution for docmd. We are introducing **Enterprise-Grade Versioning**, a magical **Zero-Config Mode**, and a modernized configuration schema, all while maintaining our promise of zero bloat. This release transforms docmd from a simple documentation generator into a reliable platform capable of handling complex, multi-versioned projects with ease. ## ✨ Highlights ### 1. Documentation Versioning Support You asked, we delivered. You can now maintain multiple versions of your documentation (e.g., `v1.0`, `v2.0`) simultaneously. docmd handles the routing, asset separation, and UI automatically. * **Sticky Switching:** Changing versions keeps you on the same page (e.g., switching v1 -> v2 while on `/installation` takes you to `/v2/installation`). * **Smart Navigation:** The sidebar automatically filters out links that don't exist in older versions. * **Per-Version Navigation:** You can completely override the menu for specific versions. ```javascript versions: { current: 'v2', // Builds to root (/) for optimal SEO all:[ { id: 'v2', dir: 'docs', label: 'v2.x (Latest)' }, { id: 'v1', dir: 'docs-v1', label: 'v1.x', // version specific navigation: not required (optional) // docmd is smart enough to auto-generate custom nav for your specific version based on available docs navigation: [ { title: 'Legacy Guide', path: '/legacy-intro' } ] } ] } ``` ### 2. Zero-Config Mode (`--zero-config`) Want to document a project instantly? You no longer need a config file. Run **`docmd dev -z`** for dev server and `docmd build -z` for production in any folder. Our new **Auto-Router** will: * Scan your directory structure recursively. * Extract `H1` titles from every Markdown file. * Build a deeply nested, collapsible sidebar. * Launch the dev server instantly. * **Note:** Zero-Config is still in `beta` and does not support versioning yet. ### 3. V3 Configuration Schema (Simpler Labels) We have streamlined the configuration labels to align with modern standards (like Vite/VitePress). It is cleaner, shorter, and more intuitive. *Legacy `v0.4` labels are still 100% supported, so no breaking changes!* | Legacy | Modern (v0.5) | Description | | :--- | :--- | :--- | | `siteTitle` | `title` | The name of your website. | | `siteUrl` | `url` | Production URL (Critical for SEO). | | `srcDir` | `src` | Your markdown source folder. | | `outputDir` | `out` | Build output folder. | ### 4. Native 404s & SEO Redirects docmd now behaves like a mature Static Site Generator (SSG) regarding SEO traffic. * **Custom 404:** We generate a native `404.html` that inherits your theme, sidebar, and layout. * **Redirects:** Define old paths in your config, and we generate static HTML redirects to preserve your SEO ranking. ```javascript module.exports = defineConfig({ redirects: { '/old-guide': '/new-guide' }, notFound: { title: 'Page Not Found', content: 'Oops! This page has moved.' } }); ``` ### 5. Whitelabeling (Hide Branding) For professional use cases, you can now easily toggle off the "Built with docmd" footer signature. ```javascript footer: { style: 'minimal', branding: false // you can hide docmd signature now } ``` ## 📝 Complete Changelog ### ✨ Features & Enhancements * **Core:** Implemented **Multi-Version Build Engine**. It loops through configured versions and builds them into isolated sub-directories (`/v1/`, `/v2/`). * **Core:** Added **Auto-Router** for Zero-Config mode. It performs AST-free scanning of headers to build navigation trees dynamically. * **Core:** Introduced `defineConfig` helper for IDE autocomplete support. * **Config:** Added V3 Schema (`title`, `src`, `out`, `url`) with internal normalization for backward compatibility. * **UI:** Added **Version Dropdown** component with "Sticky Path" logic (preserves relative path when switching versions). * **UI:** Major sidebar CSS overhaul. The navigation list now scrolls independently of the header/footer (Flexbox layout), eliminating double scrollbars. * **UI:** Sidebar dropdowns now intelligently open *upwards* when placed at the bottom of the sidebar. * **Dev Server:** Now serves the custom `404.html` instead of a raw text error when a route is missing. ### 🐛 Bug Fixes * **Search:** Fixed search index 404s in versioned subfolders by implementing `DOCMD_SITE_ROOT` logic. * **Core:** Fixed `ReferenceError: options is not defined` in config loader when using specific flags. * **UI:** Fixed SPA Router duplicating relative paths (e.g., `/v1/v1/page`) by hard-reloading on version context switches. * **Live Editor:** Fixed crash caused by missing `isOfflineMode` flag in the browser-side rendering engine. * **Build:** Fixed `EJS Render Error` for 404 pages by passing correct template context. * **Failsafe:** Upgraded test suite to brute-test Versioning, Zero-Config, and Redirect generation before every release. ## 📥 Upgrade ```bash npm install -g @docmd/core ``` **Full Changelog**: https://github.com/docmd-io/docmd/compare/0.4.11...0.5.0 --- ## [Release Note for docmd 0.5.1](https://docs.docmd.io/05/release-notes/0-5-1/) --- title: "Release Note for docmd 0.5.1" description: "PWA & AI First docmd 0.5.1 Release Notes" --- This release focuses on refining the developer experience, enhancing our AI-First approach, and introducing powerful new plugins for the ecosystem. ## 🚀 New Features ### 1. Progressive Web App (PWA) Plugin 📱 You can now instantly turn your documentation site into an installable application with a reliable Service Worker for offline availability! The `@docmd/plugin-pwa` is shipped natively. - **Zero Config**: Add `pwa: {}` to your config plugins and it automatically generates `manifest.webmanifest`, `service-worker.js`, and injects all meta tags. - **Customizable**: Allows overriding the `<meta>` theme colours, backgrounds, and explicit `pwa.logo` paths. - **Offline First**: Instantly caches requests using a network-first strategy, allowing your users to browse documentation easily on airplanes or trains. ### 2. AI First Full Context Generation 🤖 `docmd` 0.5.1 is officially the easiest static site generator for LLMs to consume natively. - **`llms-full.txt` Generation**: Beyond the structural `llms.txt`, the LLM Plugin now concatenates the raw, unmodified markdown content of your entire documentation repository into a single unified `llms-full.txt` file. Give it directly to ChatGPT or Claude to immediately inject your entire codebase context in one shot. ### 3. Deep Section Linking in Search 🔍 - The Search Plugin has been overhauled to provide hyper-granular results. Instead of just taking users to matching pages, search results are now broken down by **Header sections** (`<h3>`, `<h4>` etc) and easily deeply link users straight to the exact paragraph the keyword originates from. ## 🛠️ Improvements & Fixes ### ✨ Zero-Config Hardening - **Smarter Path Resolving**: Zero-Config mode now automatically detects `docs`, `src/docs`, and `content` base folders natively. - **Metadata Fallbacks**: Zero-Config will automatically try to ingest the root `package.json` to assign the proper `name` and `description` to the documentation site natively. - **Failsafe Executions**: Dev Loops are completely eradicated. If you run `docmd dev` in a folder that has zero Markdown files anywhere to be found, it now cleanly aborts with a useful error message instead of spamming watcher loops indefinitely. ### 🐛 Bug Fixes - **SPA Query Selector**: Fixed a crash in `docmd-main.js` which caused navigation loops when users manually clicked Anchor tags with IDs starting with numeric values. - **SEO AI Bot Blacklist**: Added native `seo.aiBots` configuration support which automatically blankets your meta headers with `<meta name="GPTBot" content="noindex">` tags across 12 prominent model scrapers for projects that need privacy. - **Meta Description**: If you omit a frontmatter description from a Markdown file, the SEO plugin automatically constructs a rich excerpt fallback from the first 150 characters of the content securely. ## 📥 Upgrade ```bash npm install -g @docmd/core ``` **Full Changelog**: https://github.com/docmd-io/docmd/compare/0.5.0...0.5.1 --- ## [Release Note for docmd 0.5.2](https://docs.docmd.io/05/release-notes/0-5-2/) --- title: "Release Note for docmd 0.5.2" description: "Menubar & Dev-UX docmd 0.5.2 Release Notes" --- This release introduces the much-anticipated **Menubar** component, significantly hardens the **Zero-Config** engine, and transforms the developer experience with a reliable dev server and a built-in playground. ## 🚀 New Features ### 1. Global Menubar The focus of this release is the new Menubar, providing a top-level navigation layer for your documentation. - **Versatile Positioning**: Can be placed at the very top of the viewport (`fixed`) or inside the header slot (`sticky`). - **Rich Components**: Supports branding (logo + title), link items, and nested dropdowns for complex navigation needs. - **Responsive Design**: Automatically collapses on mobile devices to maintain a clean reading experience. ### 2. Built-in `_playground` We've added a dedicated `_playground` package within the repository. Developers can now test core engine changes, UI components, and parser rules in real-time without leaving the codebase. ### 3. Smarter Options Menu Positioning The Options Menu (Search, Theme Toggle, Sponsor) is now more flexible than ever. - **Menubar Integration**: A new `menubar` position allows the options menu to sit perfectly on the right side of your navigation bar. - **Intelligent Fallbacks**: If you configure the options menu to a position that is currently disabled (like `header` or `menubar`), docmd now automatically falls back to `sidebar-top` to ensure your users never lose access to essential utilities. ## 🛠️ Improvements & Fixes ### ✨ Dev-UX & Dev Server Hardening - **Auto Port Selection**: `docmd dev` now automatically finds and binds to the next available port if `3000` is in use, eliminating interactive prompts and speeding up launch times. - **Log Refinement**: We've eliminated repeating build logs and improved visual highlights, providing clearer details about the build process and PWA asset generation. - **Reliable Rebuilds**: Fixed issues where `pnpm dev` would fail during active development. The internal watcher is now smarter about tracking core utility changes. ### 📦 Zero-Config Evolution - **Selective Activation**: Zero-Config is now more surgical about where it activates, implementing "silent kills" to avoid triggering in invalid or non-project directories. - **Stability**: Multiple edge cases in directory analysis have been resolved, making the zero-config start much more reliable across different OS environments. ### 🍱 Container Improvements - **Indentation Fixes**: Resolved long-standing indentation issues in container syntax parsing. - **Nested Design**: Improved the visual and structural handling of nested containers (e.g., Tabs inside Callouts). ### 🐛 Bug Fixes - **Container Heading Logic**: Fixed a design flaw where headings inside containers (Tabs, Cards, etc.) were receiving permalinks and appearing in the Table of Contents. They are now correctly excluded to keep your TOC focused on main page sections. - **Sidebar-Top Fallback**: Fixed an issue where the Options Menu would remain invisible if its primary target container was disabled. ## 📥 Upgrade ```bash npm install -g @docmd/core ``` **Full Changelog**: https://github.com/docmd-io/docmd/compare/0.5.1...0.5.2 --- ## [v0.5.4](https://docs.docmd.io/05/release-notes/0-5-3/) --- title: "v0.5.4" description: "Theme improvements, developer control, and internal architecture improvements." --- This release focuses on **theme improvements, developer control, and internal architecture improvements**. It introduces a new CLI command for managing running servers, finalises the transition to the new **appearance** theme system, and performs a large refactor across the UI and theme layers to make docmd easier to maintain long-term. <img width="720" alt="image" src="https://github.com/user-attachments/assets/a150abc3-21a0-44f1-9dc5-22c2fc367139" /> ## ✨ Highlights ### Major UI and Theme Refactor A substantial cleanup was performed across UI templates, CSS, and theme logic. The goal was simple: **reduce legacy complexity and standardise styling across themes**. Key improvements include: * **Container polishing**: Containers look much better and consistent now, especially callouts. * **Expanded design tokens**: Colours, spacing, typography, radii, and shadows are now more consistently defined. * **Improved layout structure**: Better handling of content areas, sidebars, menubars, and responsive behaviour. * **Cleaner navigation system**: Navigation templates were refactored for simpler active/parent logic and improved accessibility. * **Better theme toggling**: Highlight stylesheets and theme switching logic were corrected and simplified. * **Lighter themes**: Themes are lighter now, a lot of transitional animations are removed, making UX faster and snappier than before. Overall this significantly reduces duplicated styling while making themes easier to extend and maintain. ### New `docmd stop` Command Managing running dev servers is now simpler. A new CLI command allows you to stop active docmd servers directly from the terminal. This is particularly useful when multiple dev instances are running or when a previous process did not exit cleanly. * **Quick shutdown**: Stop running servers without hunting for processes. * **CLI integration**: Fully wired into the main `docmd` binary. * **Cleaner dev workflow**: Prevents port conflicts and lingering background processes. ### Theme System Migration (`appearance`) The theme configuration system has been modernised. The previous `defaultMode` option has been replaced with **`appearance`**, providing clearer semantics and aligning theme handling across the UI. * **Cleaner configuration**: A single consistent appearance model. * **Backward compatible**: Existing configs using `defaultMode` continue to work automatically. * **Earlier theme initialisation**: Pages now initialise appearance earlier to prevent flashing during load. ## 📝 Complete Changelog ### ✨ CLI & Dev Server * Added a new `docmd stop` command to terminate running docmd servers. * Improved dev server shutdown handling for more graceful process termination. * CLI wiring added for the new stop command. ### 🎨 Theme & UI System Refactor * Large cleanup and refactor of theme CSS architecture. * Expanded design tokens for colour, typography, spacing, borders, and shadows. * Improved responsive layout across content areas, header, menubar, and sidebar. * Updated code blocks, tables, cards, and callouts for visual consistency. * Reworked navigation template logic with better active state detection and collapsible groups. * Introduced additional structural classes for layout organisation. * Improved accessibility attributes and navigation semantics. * Adjusted scroll offsets, anchors, buttons, hover states, and general UI polish. **Sky** <img width="720" alt="image" src="https://github.com/user-attachments/assets/a150abc3-21a0-44f1-9dc5-22c2fc367139" /> * Minor variable cleanups and alignment with the new shared layout structure. * Adjusted background, link, border, and muted text variables. **Ruby** <img width="720" alt="image" src="https://github.com/user-attachments/assets/7808ac2c-552a-4db3-9fe4-31454259485b" /> * Consolidated root variables and simplified theme overrides. * Removed unnecessary shadows and layout rules. * Standardised font and code variable usage. **Retro** <img width="720" alt="image" src="https://github.com/user-attachments/assets/068febea-2ae0-4b2e-8a50-05d121307355" /> * Full redesign into a cleaner *Classic Computing* style. * Added Google font imports and rebuilt light/dark variables. * Removed legacy CRT effects, scanlines, and glow animations. * Simplified layout and improved accessibility contrast. ### ⚙️ Configuration & Zero-Config Improvements * Migrated theme configuration from `defaultMode` to `appearance`. * Maintained backward compatibility by mapping `defaultMode` → `appearance`. * Refined zero-config navigation logic so an explicitly empty navigation is now respected. * Prevent default plugins from being injected when plugins are explicitly defined. --- ## [v0.5.4](https://docs.docmd.io/05/release-notes/0-5-4/) --- title: "v0.5.4" description: "Plugin Installer architecture, resilient config migrations, and rendering fixes." --- This release introduces a fully automated plugin installation engine and hardens our configuration schemas for a much smoother developer experience. ### 🚀 The Plugin Installer (`docmd add`) Gone are the days of manually tweaking configuration files to add new features! `docmd` now ships with an absolute zero-touch plugin installer. * `docmd add <plugin>`: Instantly download and inject official docmd plugins into your environment. Need search? Just run `docmd add search`. Need analytics? `docmd add analytics`. * **Automatic Config Injection:** The CLI parses your existing `docmd.config.js` and securely injects the exact plugin block natively without breaking your code structure. * **Intelligent Package Detection:** Handles `--no-save` proxies for bare repositories easily. * **Clean Uninstalls (`docmd remove`):** Automatically wipes plugin traces safely from your configuration file. ### 🛡️ Universal Config Migrator If you built your docmd site back on our V1 architecture (`siteTitle`, `srcDir`, `defaultMode`), upgrading is now bulletproof. * Running `docmd migrate` now detects **all** legacy schemas and actively translates them into the modern V3 standard (`title`, `src`, `appearance`). * It protects custom layouts while intelligently mapping everything forward and automatically saving an exact backup of your legacy config for peace of mind. ### 🐛 Bug Fixes & Refinements * **Fixed Scroll Clipping (Sky & Retro Themes):** Addressed a critical CSS bug causing the main `.content-theme-cover` layout to improperly clip and hide deeply nested page contents when using the Sky or Retro themes. Scrolling through massive documents now behaves fluidly without trapping content behind fixed bounds. * **Improved Failsafe Mechanics:** Expanded our internal CI/CD script (`failsafe.js`) to rigorously spawn dummy packages and assert all Installer regex behaviours on the fly so feature-regressions are impossible. --- ## [Assets Management](https://docs.docmd.io/05/theming/assets-management/) --- title: "Assets Management" description: "How docmd handles CSS, JavaScript, and Image assets during the build process." --- `docmd` takes a "Mirror & Map" approach to assets. This ensures that your local development paths stay consistent with your production build. ## Directory Structure By default, `docmd` looks for an `assets/` folder in your project root. ```bash my-docs/ ├── assets/ # Source Assets │ ├── css/ │ ├── js/ │ └── images/ ├── docs/ # Content ├── docmd.config.js └── site/ # Build Output (Automatically mirrored) ``` ## Automatic Copying (v0.5.1+) When you run `docmd build` or `docmd dev`: 1. **The Mirroring Logic**: The entire contents of your `assets/` folder are recursively copied to `site/assets/`. 2. **Stability**: We use a hardened copy engine with automatic retries to prevent "File Busy" or "ENOENT" errors on macOS and modern SSDs. 3. **Referencing**: You should always reference assets from your Markdown or Config using the **root-relative** path: ```markdown ![Logo](/assets/images/logo.png) ``` ## Custom CSS & JS Integration To link your assets to every page, add them to your theme configuration: ```javascript // docmd.config.js module.exports = { theme: { customCss: ['/assets/css/branding.css'] }, customJs: ['/assets/js/utils.js'] } ``` ## AI Recognition Strategy When adding assets: * **Organise by type**: Keep `/css`, `/js`, and `/images` separate. This helps AI agents locate relevant styles or scripts instantly when you ask them to "edit the header colour". * **Use Descriptive Filenames**: Naming an image `authentication-flow-diagram.png` provides much more context to the `llms.txt` crawler than `img_01.png`. --- ## [Available Themes](https://docs.docmd.io/05/theming/available-themes/) --- title: "Available Themes" description: "Explore docmd's built-in themes including Sky, Ruby, and Retro. Learn how to switch themes with a single config line." --- `docmd` provides a set of professionally designed, light/dark responsive themes. You can switch your entire site's aesthetic by changing a single key in `docmd.config.js`. ## How to Switch Themes ```javascript // docmd.config.js module.exports = { theme: { name: 'sky', appearance: 'system', // Options: 'light', 'dark', 'system' } } ``` ## Built-in Theme Gallery | Theme | Best For | Vibes | | :--- | :--- | :--- | | `default` | Low-profile docs | Minimal, lightweight, clean | | `sky` | Product Docs | Modern, premium, standard-issue | | `ruby` | Brand Identity | Sophisticated, serif headers, vibrant | | `retro` | Dev Tools | 80s Terminals, monospace, neon accents | <div class="theme-picker" style="display: flex; gap: 10px; margin: 20px 0;"> <button onclick="switchDocTheme('default')" class="docmd-button" style="color:#fff;background: #2e2e2e;">Default</button> <button onclick="switchDocTheme('sky')" class="docmd-button" style="color:#fff;background: #0097ff;">Sky</button> <button onclick="switchDocTheme('ruby')" class="docmd-button" style="color:#fff;background: #960b0b;">Ruby</button> <button onclick="switchDocTheme('retro')" class="docmd-button" style="color:#fff;background: #a95308; border: 1px solid #0ec80e;">Retro</button> </div> ### 1. `sky` (Default) The gold standard for modern documentation. It features crisp typography, subtle transitions, and high-contrast light/dark modes that match modern SaaS platforms. ### 2. `ruby` A high-elegance theme using serif typography for headers and a deep, jewel-toned colour palette. Perfect for documentation that needs to feel authoritative and premium. ### 3. `retro` A nostalgia-fueled theme inspired by vintage computing. Features include phosphor-green text on black backgrounds (in dark mode), scanline effects, and monospace fonts like Fira Code by default. ### 4. `default` A total "Blank Slate" theme. Use this if you plan on adding extensive custom CSS and don't want any built-in design layers interfering with your branding. ## Theming Architecture 1. **CSS Layering**: Themes are additive. Choosing `sky` actually loads the base `default` styles and then overlays the `sky` aesthetic on top. 2. **Native dark-mode**: Every theme includes a first-class dark mode implementation. 3. **No Refresh**: When users switch themes via the UI, the SPA engine updates the `--docmd-primary` variables instantly without a page reload. ::: callout tip When describing your documentation layout to an AI developer tool, mentioning your theme (e.g., "I'm using the `retro` theme") helps the model suggest custom CSS overrides that align with that specific theme's variable schema. ::: --- ## [Custom Styles & Scripts](https://docs.docmd.io/05/theming/custom-css-js/) --- title: "Custom Styles & Scripts" description: "Inject your own CSS and JS files to extend docmd's functionality and branding." --- While `docmd` themes are highly flexible, you may want to inject your own stylesheets or interactive scripts. This is done via the `theme.customCss` and `customJs` arrays in your configuration. ## Custom CSS Use `theme.customCss` to override existing styles or add new ones. ```javascript // docmd.config.js module.exports = { theme: { customCss: [ '/assets/css/branding.css' // Path relative to site root ] } } ``` ### How it Works 1. Place your CSS file inside your project’s assets folder (e.g., `docs/assets/css/branding.css`). 2. `docmd` will automatically copy it to the build folder and inject a `<link>` tag into every page. 3. Custom CSS is loaded **after** the theme styles, ensuring your overrides take priority. ## Custom JavaScript Use the top-level `customJs` array for scripts that add behaviour or integrate 3rd-party services. ```javascript // docmd.config.js module.exports = { customJs: [ '/assets/js/feedback-widget.js' ] } ``` ### Life-cycle Awareness Scripts are injected at the bottom of the `<body>` tag. Since `docmd` is a **Single Page Application (SPA)**, remember that: * The page does not fully reload when navigating between links. * You may need to listen for the `docmd:navigated` event to re-initialise your scripts on new pages. ```javascript // Example: Re-init on page change document.addEventListener('docmd:page-mounted', () => { console.log('New page loaded via SPA router'); initMyCustomWidget(); }); ``` ::: callout tip Adding custom CSS and JS allows AI models (like ChatGPT) to suggest much more tailored UI improvements. If you mention "I have a custom `branding.css` file", the model can provide specific selectors that won't conflict with the core `docmd` engine. ::: --- ## [Customisation & Variables](https://docs.docmd.io/05/theming/customisation/) --- title: "Customisation & Variables" description: "A complete reference of docmd's CSS variables and component classes for advanced styling." --- `docmd` is built using a CSS variable-first architecture. This means you can restyle your entire site by simply overriding a few keys in a `:root` block without writing complex CSS selectors. ## Global Variable Reference | Variable | Default (Light) | Default (Dark) | Description | | :--- | :--- | :--- | :--- | | `--bg-color` | `#ffffff` | `#09090b` | Main page background. | | `--text-color` | `#3f3f46` | `#a1a1aa` | Standard body text. | | `--text-heading` | `#09090b` | `#fafafa` | Title and Header colours. | | `--link-color` | `#068ad5` | `#068ad5` | Primary accent / links. | | `--border-color` | `#e4e4e7` | `#27272a` | Dividers and borders. | | `--sidebar-bg` | `#fafafa` | `#09090b` | Navigation background. | | `--ui-border-radius` | `6px` | `6px` | Rounding for all UI items. | | `--sidebar-width` | `260px` | `260px` | Sidebar column width. | ## Example Override To change your site's primary accent colour, add this to your `customCss`: ```css :root { --link-color: #f43f5e; /* Rose 500 */ } body[data-theme="dark"] { --link-color: #fb7185; /* Rose 400 */ } ``` ## Component Targeting If you need to style specific components, use these top-level classes: * `.main-content`: The wrapper for all Markdown content. * `.sidebar-nav`: The internal navigation list. * `.page-header`: The top navigation bar. * `.docmd-search-modal`: The search overlay. * `.docmd-tabs`: Tab container components. * `.callout`: The alert/note boxes. ## Troubleshooting specificity Most `docmd` styles use low specificity. If your overrides aren't applying, ensure your `customCss` is registered correctly and check if adding a `body` prefix (e.g., `body .main-content`) helps. ::: callout tip Because `docmd` uses standard CSS variables, you can ask an AI: *"Give me a professional colour palette using --link-color and --bg-color for docmd"*. The model will be able to provide ready-to-paste CSS that integrates perfectly with the built-in themes. ::: --- ## [Icons](https://docs.docmd.io/05/theming/icons/) --- title: "Icons" description: "How to use and customise Lucide icons in your documentation." --- `docmd` comes with built-in support for the [Lucide](https://lucide.dev/) icon library. Icons can be used in your navigation sidebar, buttons, and custom components to provide visual cues and improve scannability. ## Navigation Icons Assign an icon to any navigation item in your `docmd.config.js`. Use the kebab-case name of any icon found on the Lucide website. ```javascript navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Setup', path: '/setup', icon: 'settings' } ] ``` ## Button Icons You can also use icons inside your button labels by including the raw HTML or using standard Lucide naming if supported by your theme. ```markdown ::: button "Download" /download icon:download ``` ## CSS Styling All icons are rendered as inline SVGs with the class `.lucide-icon`. You can globally change their size or stroke weight in your `customCss`: ```css .lucide-icon { stroke-width: 1.5px; /* Thinner icons for a modern look */ width: 1.2rem; height: 1.2rem; } /* Target a specific icon */ .icon-rocket { color: #ff5733; } ``` ## Icon Reference We support the entire Lucide library. You can browse the thousands of available icons here: ::: button "Browse Lucide Icons" external:https://lucide.dev/icons --- ## [Light & Dark Mode](https://docs.docmd.io/05/theming/light-dark-mode/) --- title: "Light & Dark Mode" description: "How to configure the default viewing mode and manage the theme switcher for the best user experience." --- `docmd` provides built-in support for light and dark colour schemes. It detects user system preferences automatically and allows manual overrides via a UI toggle. ## Default Viewing Mode You specify the starting state of your documentation in `docmd.config.js`. ```javascript // docmd.config.js module.exports = { theme: { name: 'sky', appearance: 'system' // Options: 'light', 'dark', 'system' (default) } } ``` * **`system`**: Matches the user's OS preference (Recommended). * **`light`**: Force light mode on initial load. * **`dark`**: Force dark mode on initial load. ## Configuring the Toggle Button The theme switcher is part of the **Options Menu**. You can control its visibility and position within the `layout` object. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom' components: { themeSwitch: true // Show or hide the Sun/Moon toggle } } } ``` ## How it works (Technical) The theme engine applies a `data-theme` attribute to the `<body>` tag: * `<body data-theme="light">` * `<body data-theme="dark">` If you are using a themed design like `sky`, the attribute will be `sky-light` or `sky-dark`. ### CSS Variables `docmd` themes use CSS variables for all colours. You can override these variables in your own CSS to customise the look of either mode. ```css /* Custom CSS override */ :root { --docmd-primary: #4f46e5; /* Primary accent for light mode */ } body[data-theme="dark"] { --docmd-primary: #818cf8; /* Primary accent for dark mode */ } ``` ## User Persistence When a user manually toggles the mode, their preference is stored in `localStorage`. `docmd` instantly reads this value on every page load to prevent "theme flickering" (FOUC). ::: callout tip When generating content, LLMs prefer high-contrast structures. `docmd` ensures that code snippets and callouts remain accessible in both modes, ensuring that `llms-full.txt` payloads are correctly understood as semantic blocks regardless of which mode was active during the build. ::: --- ## [Developer Guide](https://docs.docmd.io/06/advanced/developer-guide/) --- title: "Developer Guide" description: "Professional automated onboarding, verification, and maintenance workflows for docmd contributors." --- If you are a contributor who has forked the `docmd` monorepo, we provide a suite of **Dev Environment Tools** to ensure your workspace remains clean and consistent. While `contributing.md` outlines the basic setup, this guide details the professional automated workflows available for project maintenance. ## Automated Workflows We provide high-level scripts to handle environmental health and project scaffolding across the monorepo. ### Project Scaffolding: `pnpm onboard` Run this command after forking the repository or pulling major changes. It performs a full environment synchronisation. ```bash pnpm onboard ``` ### Environment Synchronisation: `pnpm onboard --link` This extended command prepares the environment and makes the local `docmd` binary available globally for system-wide testing. ```bash pnpm onboard --link-docmd ``` **Actions performed:** - Executes a recursive `pnpm install` across all packages. - Performs a full `pnpm build` for the core engine, UI templates, and plugins. - **(Optional)**: Symlinks the `@docmd/core` binary to your system PATH via `npm link`. ### System Reset: `pnpm reset` If your environment becomes unstable or you require a completely fresh start, use the reset command. ```bash pnpm reset ``` **Actions performed:** 1. **Process Cleanup**: Stops all active `docmd dev` or `docmd live` background servers. 2. **Global Unlinking**: Recursively removes all `docmd` and `docmd-live` global symlinks. 3. **Deep Clean**: Deletes all `node_modules`, `dist/`, `public/`, `site/`, and TypeScript build caches across the monorepo. ## Granular Maintenance Commands The following commands can be executed from the monorepo root for specific maintenance tasks: | Command | Description | | :--- | :--- | | `pnpm build` | Compiles all TypeScript packages and bundles the Live Editor. | | `pnpm stop` | Scans and terminates orphaned `docmd` processes. | | `pnpm clean` | Safely removes build artifacts and caches. | | `pnpm lint` | Executes ESLint and Prettier across the entire workspace. | | `pnpm unlink:global` | Explicitly removes all global binary symlinks. | ## Merge Preparation Pipeline (`pnpm prep`) Before merging code, the central automated pipeline ensures complete integrity: ```bash pnpm prep ``` **Testing Methodology:** - **Zero-Trust Reset**: Executes `pnpm reset` to wipe caches, builds, global instances, and node_modules. - **Deep Clean Linking**: Uses fresh dependency installations to block cache poisoning. - **Strict Lint Validation**: Enforces code style adherence via `pnpm lint`. If linting fails, the release aborts. - **Verification Suite (`pnpm verify`)**: Runs the aggressive `failsafe.js` integration testing system designed to verify engine integrity: - **Dynamic Scaffolding**: Creates a temporary, isolated directory and generates a raw documentation project. - **Cross-Schema Validation**: Builds the test project using both Legacy and Modern configuration schemas. - **Feature E2E**: Generates HTML and performs explicit assertions on structural elements, versioning, and link resolution. - **Installer Resilience**: Simulates `docmd add` and `docmd remove` operations to ensure configuration injection logic is stable. ### Alternative: Fast Verification (`pnpm verify`) While `pnpm prep` is mandatory for pull requests to guarantee absolute safety, maintaining a clean state means tearing down active caches and re-installing Node modules from scratch every time. For **isolated, high-speed testing** during active development, you can natively invoke: ```bash pnpm verify ``` **Limitations & Use Cases:** - *Use Case*: Validating a quick core-engine patch before committing. - *Limitation*: Because it relies on the pre-existing state of your local `node_modules` and compiled files, it does not guarantee your branch will successfully replicate on a pristine machine or in CI. It strictly protects against regressions in code logic, lacking the cache-poisoning defence of a full `prep`. ## The Playground Environment To test core engine changes or UI template tweaks in real-time, use the dedicated `_playground` package. ```bash pnpm run dev ``` This starts a development server bound to `packages/_playground`. Any modifications to the core engine, UI assets, or plugins will trigger an instant Hot Module Replacement (HMR) in the playground's browser tab. ## Local CLI Testing When developing CLI features, avoid polluting the root project. Use the proxied playground commands to test logic in isolation: ```bash pnpm run playground:add <plugin> pnpm run playground:remove <plugin> ``` **Advantages:** - Executes your local, uncompiled code from `packages/core/bin/docmd.js`. - Confines all filesystem side-effects to the isolated `_playground` directory. - Prevents accidental `package.json` modifications in the git tree. ## Arbitrary Playground Commands If you need to execute a custom CLI command within the playground context from the root, use the pnpm filter bridge: ```bash pnpm --filter @docmd/playground exec docmd [command] ``` --- ## [Browser API (Client-Side)](https://docs.docmd.io/06/api/browser-api/) --- title: "Browser API (Client-Side)" description: "Interact with docmd from the browser - live compilation and dev-mode plugin communication." --- `docmd` provides two browser APIs: the **isomorphic compile engine** for rendering markdown in the browser, and the **dev-mode plugin API** for real-time communication with the dev server. ## Isomorphic Compile Engine The same engine that generates static sites in Node.js can run entirely within a web browser. This is ideal for building CMS previews, interactive playgrounds, or embedding documentation into existing web applications. ### Installation via CDN ```html <!-- Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- The Isomorphic Engine --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` ### `docmd.compile(markdown, config)` Compiles raw Markdown into a full HTML document string using the default `docmd` layout. **Parameters:** - `markdown` (String): The raw Markdown content. - `config` (Object): Configuration overrides (same schema as `docmd.config.js`). **Returns:** `Promise<String>`: The complete HTML document. ### Example: Live Preview To ensure style isolation, it is recommended to render the output inside an `<iframe>` using the `srcdoc` attribute. ```javascript const editor = document.getElementById('editor'); const preview = document.getElementById('preview'); async function updatePreview() { const html = await docmd.compile(editor.value, { title: 'Preview', theme: { appearance: 'light' } }); preview.srcdoc = html; } editor.addEventListener('input', updatePreview); ``` ## Dev-Mode Plugin API During `docmd dev`, a `window.docmd` global is automatically injected into every page. This API enables real-time communication between browser-side plugin code and server-side action handlers via WebSocket RPC. ::: callout info "Dev Mode Only" The plugin API methods below are only available during `docmd dev`. They are not included in production builds. ::: ### `docmd.call(action, payload)` Call a server-side action handler registered by a plugin. Returns a promise that resolves with the handler's return value. ```javascript // Call a plugin action and get a result const threads = await docmd.call('threads:get-threads', { file: 'docs/getting-started.md' }); console.log(threads); // Array of thread objects ``` If the action modifies source files, the page automatically reloads after the promise resolves. ### `docmd.send(name, data)` Send a fire-and-forget event to the server. No response is returned. ```javascript // Notify the server of a page view (no response expected) docmd.send('analytics:page-view', { path: window.location.pathname }); ``` ### `docmd.on(name, callback)` Subscribe to server-pushed events. Returns an unsubscribe function. ```javascript // Listen for server-broadcast events const unsub = docmd.on('threads:updated', (data) => { console.log('Threads updated:', data); }); // Later: unsubscribe unsub(); ``` ### `docmd.afterReload(name, callback)` Declare a handler that runs after a page reload. If context was stashed with `scheduleReload`, the callback receives it. ```javascript // Restore scroll position after a live-reload docmd.afterReload('scroll-restore', (ctx) => { window.scrollTo(0, ctx.scrollY); }); ``` ### `docmd.scheduleReload(name, context)` Stash context into `sessionStorage` for a named `afterReload` handler. The matching handler fires with this context after the next page reload. ```javascript // Before a file edit triggers a reload, save state docmd.scheduleReload('scroll-restore', { scrollY: window.scrollY }); ``` ## Considerations - **No File System**: The browser engine cannot scan folders. You must provide the `navigation` array explicitly in the config object if you need a sidebar. - **Node-Only Plugins**: Plugins that rely on Node.js APIs (like Sitemap or LLM text generation) are disabled in the browser environment. - **WebSocket Connection**: The dev-mode API requires an active WebSocket connection to the dev server. It will auto-reconnect with exponential backoff if the connection drops. --- ## [Client-Side Events](https://docs.docmd.io/06/api/client-side-events/) --- title: "Client-Side Events" description: "Hook into the docmd SPA lifecycle to add interactive features." --- `docmd` utilizes a lightweight Single Page Application (SPA) router to provide instant page transitions. Because the browser does not perform a full reload during navigation, scripts relying on `DOMContentLoaded` will not re-execute. To handle this, `docmd` dispatches custom lifecycle events that you can listen for in your `customJs` files. ## `docmd:page-mounted` This event is dispatched whenever a new page has been successfully fetched and injected into the DOM. ### Usage Add a listener to the `document` object to re-initialise third-party libraries or trigger custom animations. ```javascript document.addEventListener('docmd:page-mounted', (event) => { const { url } = event.detail; console.log(`Navigated to: ${url}`); // Re-initialise components // Example: Prism.highlightAll(); }); ``` ### Event Details (`event.detail`) | Property | Type | Description | | :--- | :--- | :--- | | `url` | `String` | The absolute URL of the page that was just mounted. | ## Best Practices 1. **Idempotency**: Ensure your initialisation logic can be safely called multiple times on the same page or cleaned up before the next navigation. 2. **Global Scope**: Scripts added via `customJs` are executed in the global scope. Use an IIFE (Immediately Invoked Function Expression) to avoid polluting the `window` object. 3. **Cleanup**: If your script adds global event listeners (e.g., `window.onresize`), consider tracking the current path to remove them when the user navigates away. --- ## [Live Editor](https://docs.docmd.io/06/api/live-api/) --- title: "Live Editor" description: "Understanding the docmd Live Editor and its browser-based authoring workflow." --- The `docmd` Live Editor is a dedicated environment for real-time documentation authoring. It uses the isomorphic core of `docmd` to provide an instant, side-by-side preview of your Markdown content without requiring a backend build process. ## Launching the Editor Start the local Live Editor by running: ```bash docmd live ``` The editor will typically be available at `http://localhost:3000`. ## Architecture Unlike the standard `dev` server which rebuilds files on the disk, the Live Editor runs the `docmd` engine directly in your browser. This enables: 1. **Instant Feedback**: Content is re-rendered as you type. 2. **Portable Playgrounds**: The editor can be bundled into a static site for hosting on platforms like GitHub Pages. 3. **Cross-Platform Consistency**: The preview uses the exact same rendering logic as the production build. ## Static Deployment Generate a shareable, standalone version of the editor: ```bash docmd live --build-only ``` This creates a `dist/` directory containing the editor's HTML and the bundled isomorphic engine. --- ## [Node.js API](https://docs.docmd.io/06/api/node-api/) --- title: "Node.js API" description: "Integrate docmd's build engine into your custom Node.js scripts and automation pipelines." --- For advanced workflows, you can import and use the `docmd` build engine directly within your own Node.js applications. This is ideal for custom CI/CD pipelines, automated documentation generation, or extending `docmd` for specialized environments. ## Installation Ensure `@docmd/core` is installed in your project: ```bash npm install @docmd/core ``` ## Core Functions ### `buildSite(configPath, options)` The primary build function. It handles configuration loading, Markdown parsing, and asset generation. ```javascript import { buildSite } from '@docmd/core'; async function runBuild() { await buildSite('./docmd.config.js', { isDev: false, // Set to true for watch mode logic offline: false, // Set to true to optimise for file:// access zeroConfig: false // Set to true to bypass config file detection }); } ``` ### `buildLive(options)` Generates the browser-based **Live Editor** bundle. ```javascript import { buildLive } from '@docmd/core'; async function generateEditor() { await buildLive({ serve: false, // true starts a local server; false generates static files port: 3000 // Custom port if serve is true }); } ``` ## Example: Custom Pipeline You can wrap `docmd` to create complex documentation workflows. ```javascript import { buildSite } from '@docmd/core'; import fs from 'fs-extra'; async function deploy() { // 1. Generate dynamic content await fs.writeFile('./docs/dynamic.md', '# Generated Content'); // 2. Execute docmd build await buildSite('./docmd.config.js'); // 3. Move output await fs.move('./site', './public/docs'); } ``` ::: callout tip The programmatic API is highly compatible with **AI-Driven Documentation**. Agents can trigger builds after content updates to verify integrity and manage deployments autonomously. ::: ## Plugin API Exports `@docmd/core` also exports utilities for building advanced plugins with server-side action handling. ### `createActionDispatcher(hooks, options)` Creates a dispatcher that routes WebSocket RPC messages to plugin action/event handlers. ```javascript import { createActionDispatcher } from '@docmd/core'; const dispatcher = createActionDispatcher( { actions: myPlugin.actions, events: myPlugin.events }, { projectRoot: '/path/to/project', config, broadcast } ); const { result, reload } = await dispatcher.handleCall('my-action', payload); ``` ### `createSourceTools({ projectRoot })` Creates source editing utilities for markdown file manipulation. ```javascript import { createSourceTools } from '@docmd/core'; const source = createSourceTools({ projectRoot: '/path/to/project' }); // Get block information at a specific line range const block = await source.getBlockAt('docs/page.md', [10, 12]); // Wrap text with syntax markers await source.wrapText('docs/page.md', [10, 12], 'important', 0, '**', '**'); ``` ### Type Exports For TypeScript plugin authors, the following types are available: ```typescript import type { PluginModule, // Full plugin contract interface ActionContext, // Context passed to action/event handlers ActionHandler, // Signature for action handlers EventHandler, // Signature for event handlers SourceTools, // Source editing tools interface BlockInfo, // Block information returned by getBlockAt TextLocation, // Text location returned by findText } from '@docmd/core'; ``` --- ## [CLI Commands](https://docs.docmd.io/06/cli-commands/) --- title: "CLI Commands" description: "The complete command-line interface reference for docmd." --- The `docmd` CLI provides a set of high-performance commands to manage your documentation lifecycle, from initial scaffolding to production deployment. ## `docmd init` Scaffolds a new documentation project in the current directory. ```bash docmd init ``` ### Actions - Creates a `docs/` directory with a boilerplate `index.md`. - Generates a `docmd.config.js` file with recommended defaults. - Updates your `package.json` with recommended build scripts. ## `docmd dev` Starts a high-speed development server with **Instant Hot Reloading**. ```bash docmd dev [options] ``` ### Options - `-p, --port <number>`: Specify a custom port (Default: `3000`). - `-z, --zero-config`: Run in auto-detect mode without a configuration file. - `-c, --config <path>`: Use a non-standard configuration file path. ## `docmd build` Generates a production-ready static website in the `site/` folder. ```bash docmd build [options] ``` ### Options - `--offline`: **File Protocol Friendly**. Rewrites links to end in `.html`, allowing for direct browsing from the local filesystem (e.g., `file://`). - `-z, --zero-config`: Build using auto-detection logic. - `-c, --config <path>`: Path to the configuration file (Default: `docmd.config.js`). ## `docmd live` Launches the browser-based **Live Editor** environment. ```bash docmd live [options] ``` ### Options - `--build-only`: Generates the static editor bundle in `dist/` without starting a server. ## `docmd stop` Gracefully terminates all background documentation servers. ```bash docmd stop [options] ``` ### Options - `-p, --port <number>`: Stop a specific instance running on a given port. ## `docmd add <plugin>` Installs an official or community plugin and auto-configures your project. ```bash docmd add analytics ``` ### Actions - Uses your preferred package manager (`npm`, `pnpm`, `yarn`, or `bun`). - Injects the plugin and its recommended default settings into `docmd.config.js`. ## `docmd remove <plugin>` Safely uninstalls a plugin and cleans up your configuration. ```bash docmd remove analytics ``` ## `docmd migrate` Upgrades legacy `docmd` configurations to the modern V2 schema. ```bash docmd migrate ``` It re-maps deprecated keys (e.g., `siteTitle` to `title`) and restructures the configuration object to support the new layout and navigation frameworks. ::: callout tip "Agent-Compatible Logging" `docmd` implements structured terminal logging. If you are using an AI agent for development, this allows for precise error detection and automated project maintenance. ::: --- ## [Comparing Documentation Tools](https://docs.docmd.io/06/comparison/) --- title: "Comparing Documentation Tools" description: "A professional comparison between docmd and other popular documentation generators like Docusaurus, MkDocs, and Mintlify." --- `docmd` was engineered to occupy the space between simple Markdown parsers and heavy-weight framework applications (like Docusaurus). It provides the speed and SEO of a static site with the interactive feel of a modern Single Page Application (SPA). ## Feature Matrix | Feature | docmd | Docusaurus | MkDocs | Mintlify | | :--- | :--- | :--- | :--- | :--- | | **Ecosystem** | **Node.js** | React.js | Python | SaaS | | **Navigation** | **Instant SPA** | React SPA | Full Reloads | Hosted SPA | | **Base Payload** | **< 20kb** | > 200kb | Minimal | Medium | | **Versioning** | **Native** | Complex FS | Plugin-based | Native | | **i18n Support** | **Coming Soon** | Native | Plugin-based | Native | | **Search** | **Built-in (Offline)** | Algolia (Cloud) | Built-in | Cloud-based | | **PWA** | **Built-in (Plugin)** | Plugin | None | Hosted | | **AI Optimisation** | **Built-in (llms.txt)** | Manual | None | Proprietary | | **Setup** | **Instant (-z)** | ~15 mins | ~10 mins | ~5 mins | ## The docmd Advantage ### 1. AI-First Architecture Unlike traditional generators, `docmd` recognises that AI agents are now primary consumers of technical documentation. Our built-in **LLM Plugin** automatically generates `llms.txt` and `llms-full.txt` files, providing structured context for LLM-driven development tools. ### 2. Zero-Config PWA Transform your documentation into a high-performance, installable mobile and desktop application with a single plugin. `docmd` handles the service worker logic, manifest generation, and offline caching automatically. ### 3. Balanced Performance By generating pure, semantic HTML and subsequent navigations via a micro-SPA router, `docmd` ensures peak SEO performance without sacrificing the fluidity of a modern web application. ## Choosing the Right Tool - **Use Docusaurus if**: You require high-complexity React components within your Markdown (MDX) or have urgent multi-language needs today. - **Use MkDocs if**: Your environment is strictly Python-based and you prefer the legacy static page-reloading model. - **Use docmd if**: You value speed, developer experience (DX), a modern SPA feel, and want your documentation to be easily digestible by both humans and AI agents. --- ## [General Configuration](https://docs.docmd.io/06/configuration/general/) --- title: "General Configuration" description: "Master the docmd.config.js schema. Configure branding, layout architecture, and core engine features." --- The `docmd.config.js` file serves as the definitive configuration for your documentation project. It controls site structure, branding, UI behaviour, and engine-level processing rules. ## The Configuration File We recommend using the `defineConfig` helper provided by `@docmd/core`. This provides full IDE autocomplete and type-checking, enabling effortless discovery of available settings. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ title: 'My Project', url: 'https://docs.myproject.com', // ... configuration settings }); ``` ## Core Settings `docmd` utilizes a streamlined configuration schema. Below are the primary top-level settings: | Key | Description | Default | | :--- | :--- | :--- | | `title` | The name of your documentation site. Used in the header and browser titles. | `Documentation` | | `url` | Your production base URL. **Critical for SEO, Sitemaps, and OpenGraph.** | `null` | | `src` | The relative path to the directory containing your Markdown files. | `docs` | | `out` | The relative path for the generated static site output. | `site` | | `base` | The base path if hosting in a subfolder (e.g., `/docs/`). | `/` | ## Branding & Identity Configure how your brand is represented in the navigation header and browser tabs. ```javascript logo: { light: 'assets/images/logo-dark.png', // Logo shown in Light Mode dark: 'assets/images/logo-light.png', // Logo shown in Dark Mode href: '/', // Link destination when clicking the logo alt: 'Company Logo', // Alternative text for accessibility height: '32px' // Optional: Explicit height for the logo }, favicon: 'assets/favicon.ico', // Path to your site's favicon ``` ## Layout Architecture `docmd` features a modular layout system. You can toggle UI components and configure navigation behaviour via the `layout` object. | Section | Key | Default | Description | | :--- | :--- | :--- | :--- | | **Global** | `spa` | `true` | Enables seamless Single Page Application navigation without browser reloads. | | **Header** | `header` | `{ enabled: true }` | Toggles the top navigation bar. | | **Sidebar**| `sidebar`| `{ enabled: true, collapsible: true }` | Controls the sidebar navigation tree and its behaviour. | | **Footer** | `footer` | `{ style: 'minimal' }` | Supports `'minimal'` or `'complete'` footer styles. | ### Utility Menu (Options Menu) The Options Menu consolidates utility components suchs as **Global Search**, **Theme Switching**, and **Sponsorship links**. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom', 'menubar' components: { search: true, // Enable built-in full-text search themeSwitch: true, // Enable Light/Dark mode toggle sponsor: 'https://github.com/sponsors/your-profile' // Optional URL for a heart icon/link } } } ``` ::: callout info If `optionsMenu.position` is set to `header` or `menubar` but those containers are disabled, the menu will automatically fall back to `sidebar-top`. ::: ## Core Engine Features Fine-tune how `docmd` processes and renders your documentation content. ```javascript minify: true, // Minifies production assets (CSS/JS) for better performance autoTitleFromH1: true, // Uses the first H1 heading as the page title if frontmatter 'title' is missing copyCode: true, // Adds a 'Copy' button to all code blocks automatically pageNavigation: true, // Adds 'Previous' and 'Next' navigation links at the bottom of pages ``` ## Legacy Support If you are upgrading from an older version of `docmd`, the following keys are automatically mapped to the modern schema for backward compatibility: * `siteTitle` → `title` * `siteUrl` / `baseUrl` → `url` * `srcDir` / `source` → `src` * `outDir` / `outputDir` → `out` ::: callout tip Execute `docmd migrate` to automatically upgrade your configuration file to the latest schema while preserving a backup of your original settings. ::: --- ## [Layout & UI Zones](https://docs.docmd.io/06/configuration/layout-slots/) --- title: "Layout & UI Zones" description: "Control the interface structure by managing headers, sidebars, and functional UI slots." --- A standard `docmd` page is divided into six primary functional zones: 1. **Menubar**: A full-width top navigation bar for global site links. 2. **Header**: The persistent secondary bar containing the page title and utility buttons. 3. **Sidebar**: The primary navigation tree (usually on the left). 4. **Content Area**: The central Markdown rendering zone, including **Breadcrumbs**. 5. **Table of Contents (TOC)**: Right-hand heading navigation for the current page. 6. **Footer**: Bottom area for copyright, branding, and site-wide links. ## Global Components Most UI zones are configured within the `layout` section of your `docmd.config.js`. ### Menubar The menubar provides a high-level navigation layer above your documentation. ```javascript layout: { menubar: { enabled: true, position: 'top', // 'top' (fixed) or 'header' (within content flow) left: [ { type: 'title', text: 'Brand', url: '/', icon: 'home' }, { text: 'Features', url: '/features' } ], right: [ { text: 'GitHub', url: 'https://github.com/docmd-io/docmd', icon: 'github' } ] } } ``` ### The Page Header The header is enabled by default. You can disable it site-wide or hide specific elements via page-level frontmatter. ```javascript // docmd.config.js layout: { header: { enabled: true // Set to false to hide the entire top header site-wide }, breadcrumbs: true // Set to false to hide the breadcrumb trail site-wide } ``` **Page-level override (Frontmatter):** ```yaml --- title: "Special Page" hideTitle: true # Hides the title from the sticky header for this specific page --- ``` ## Utility Menus (Options Menu) The `optionsMenu` consolidates core utilities like **Search**, **Theme Toggle**, and **Sponsorship**. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom', 'menubar' components: { search: true, // Enable full-text search themeSwitch: true, // Enable Light/Dark mode toggle sponsor: 'https://github.com/sponsors/your-profile' } } } ``` ::: callout info "Container Fallback" If the chosen position targets a container that is disabled, `docmd` will automatically render the options menu in the `sidebar-top` slot to ensure core utilities remain accessible. ::: ## Sidebar & Footer Controls ### Sidebar Behaviour ```javascript layout: { sidebar: { enabled: true, collapsible: true, // Enables the expand/collapse animation defaultCollapsed: false, // Sets the initial sidebar state position: 'left' } } ``` ### Footer Branding `docmd` provides both **minimal** and **complete** layouts for your site footer. ```javascript layout: { footer: { style: 'complete', description: 'Minimalist documentation for modern projects.', branding: true, // Controls the "Built with docmd" badge columns: [ { title: 'Community', links: [{ text: 'GitHub', url: '...' }] } ] } } ``` ::: callout tip "AI-Optimised Interface" When designing custom layouts, ensure the **Search** component is prominent in your `optionsMenu`. AI agents frequently utilize search as a primary anchor when exploring your documentation to locate specific technical context. ::: --- ## [Menubar](https://docs.docmd.io/06/configuration/menubar/) --- title: "Menubar" description: "Structure and position your menubar, manage navigation links, and configure drop-down menus." --- The `menubar` is a premium navigation layer that provides global context across your documentation site. It can be positioned as a fixed bar at the top of the viewport or as a relative component above the page header. ## Configuration The menubar is configured within the `layout` section of your `docmd.config.js`. ```javascript export default defineConfig({ layout: { menubar: { enabled: true, position: 'top', // 'top' (fixed) or 'header' (inline) left: [ { type: 'title', text: 'Brand', url: '/', icon: 'home' }, { text: 'Documentation', url: '/docs' }, { type: 'dropdown', text: 'Ecosystem', items: [ { text: 'GitHub', url: 'https://github.com/docmd-io/docmd', external: true }, { text: 'Live Editor', url: 'https://live.docmd.io' } ] } ], right: [ { text: 'Support', url: '/support', icon: 'help-circle' } ] } } }); ``` ### Options | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `Boolean` | `false` | Toggles the visibility of the menubar. | | `position` | `String` | `'top'` | `'top'` (fixed at absolute top) or `'header'` (positioned above the page title). | | `left` | `Array` | `[]` | Navigation items aligned to the left section. | | `right` | `Array` | `[]` | Navigation items aligned to the right section. | ## Item Types The `left` and `right` arrays support various item types to structure your navigation effectively: ### 1. Standard Link The most common item type. - `text`: Display label. - `url`: Path or external URL. - `icon`: Optional Lucide icon name. - `external`: Set to `true` to open in a new tab. ### 2. Title (Brand) Set `type: 'title'` to apply branding styles (usually bold or with a specific font weight) to the link. ### 3. Dropdown Menu Set `type: 'dropdown'` and provide an `items` array to create a nested menu. ## Utility Integration You can host the global search and theme toggle within the menubar by setting the `optionsMenu.position` to `'menubar'`. ```javascript layout: { optionsMenu: { position: 'menubar' } } ``` When integrated, the options menu will automatically align to the **right region** of the menubar, appearing after any links defined in the `right` array. ::: callout info If the `menubar` is disabled, any utility components assigned to it will automatically fall back to the `sidebar-top` position. ::: ## Custom Styling You can fine-tune the menubar's appearance using CSS variables in your `customCss` files: ```css :root { --menubar-height: 56px; --menubar-bg: var(--docmd-bg-secondary); --menubar-border: var(--docmd-border-color); --menubar-text: var(--docmd-text-primary); } ``` --- ## [Navigation Configuration](https://docs.docmd.io/06/configuration/navigation/) --- title: "Navigation Configuration" description: "Structure your sidebar, categorize links, and assign icons for both human readers and AI models." --- `docmd` provides explicit control over your site's structure. By defining your `navigation` in `docmd.config.js`, you create a logical hierarchy that optimises the Single Page Application (SPA) experience and provides a clear context map for AI models and search engines. ## The Navigation Array Each object in the array defines a **Link** or a **Category Group**. ```javascript export default defineConfig({ navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Installation', path: '/getting-started/installation', icon: 'download' } ] }); ``` ## Available Properties | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | | **`title`** | `String` | Yes | The display text for the link or category. | | **`path`** | `String` | No | Destination URL. Must start with `/` for local paths. | | **`icon`** | `String` | No | Name of a [Lucide Icon](https://lucide.dev/icons) (e.g., `rocket`). | | **`children`** | `Array` | No | Nested items used to create a submenu or group. | | **`collapsible`**| `Boolean` | No | If `true`, the group can be expanded/collapsed by the user. | | **`external`** | `Boolean` | No | If `true`, the link opens in a new browser tab. | ## Organising Groups You can nest navigation items to create deep hierarchies. There are two primary ways to organise groups: ### 1. Clickable Group (Directory with Index) If the parent has a `path`, clicking the label navigates to that page and automatically expands the children in the sidebar. ```javascript { title: 'Cloud Setup', path: '/cloud/overview', children: [ { title: 'AWS', path: '/cloud/aws' }, { title: 'GCP', path: '/cloud/gcp' } ] } ``` ### 2. Static Label (Category Header) If you **omit the `path`**, the item becomes a static category header. This is the recommended approach for grouping related technical sections that don't share a common landing page. ```javascript { title: 'Content & Formatting', icon: 'layout', children: [ { title: 'Syntax Guide', path: '/content/syntax' }, { title: 'Containers', path: '/content/containers' } ] } ``` ## Automated Breadcrumbs `docmd` automatically generates breadcrumbs for every page based on your navigation hierarchy. These crumbs are rendered above the main page title to improve orientation and navigation speed. ### Behaviour * **Auto-Resolution**: The engine traces the path through your `navigation` tree to identify the current page's ancestors. * **Active State**: The current page is listed as the final, non-linked crumb. * **Mobile Support**: Breadcrumbs are intelligently adjusted or hidden on smaller screens to preserve header space. ### Disabling Breadcrumbs Breadcrumbs are enabled by default. To disable them site-wide, update your `docmd.config.js`: ```javascript layout: { breadcrumbs: false } ``` ## External Versioned Navigation When maintaining multiple versions of your documentation (e.g., `v1`, `v2`), managing a massive central configuration can become cumbersome. `docmd` supports **Navigation V2**, allowing you to place a `navigation.json` file at the root of your versioned directory (e.g., `docs-v1/navigation.json`). The JSON file must follow the standard array structure: ```json [ { "title": "Home", "path": "/" }, { "title": "Release Notes", "path": "/release-notes" } ] ``` **Resolution Priority:** When rendering a versioned page, the sidebar is resolved in this order: 1. **`navigation.json`**: Checked first within the specific version source folder. 2. **`versions.navigation`**: Checked within the version definition in `docmd.config.js`. 3. **Default Navigation**: Falls back to the main site navigation. ## Icons Integration `docmd` comes pre-bundled with the entire **Lucide** icon library. Simply use the icon name in kebab-case (e.g., `brain-circuit`, `terminal`, `settings`). ::: callout tip Use descriptive `title` keys even if the page content starts with a header. Clear, consistent navigation titles allow AI agents (using `llms-full.txt`) to build an accurate mental map of your project structure effortlessly. ::: --- ## [Redirects & 404](https://docs.docmd.io/06/configuration/redirects/) --- title: "Redirects & 404" description: "Configure metadata-based redirects and custom branded 404 error pages for static deployments." --- In a static hosting environment, there is no server-side logic (such as Nginx rules or `.htaccess` files) to handle dynamic routing. `docmd` addresses this by generating native HTML failsafes that handle redirection and error states automatically. ## Server-less Redirects You can forward traffic from legacy URLs to new destinations by defining a mapping in the `redirects` object. ```javascript export default defineConfig({ redirects: { '/setup': '/getting-started/installation', // Short URL to deep link '/v1/api': '/api-reference' // Legacy version to modern path } }); ``` ### Technical Implementation When a redirect is defined, `docmd` creates an `index.html` file at the legacy path containing a `<meta http-equiv="refresh">` tag. This strategy ensures: 1. **Seamless Redirection**: Users are forwarded to the new destination instantly after the page loads. 2. **SEO Preservation**: Search engines recognise the redirection, helping to maintain link equity. 3. **Analytics Tracking**: Page views are captured before the redirect occurs, preserving your traffic data. ## Branded 404 Pages When a user attempts to access a non-existent URL, most static hosting providers (Netlify, Vercel, GitHub Pages) automatically look for a `404.html` file in the root directory. `docmd` generates this file by default, ensuring it inherits your site's theme, sidebar, and SPA functionality. ### Customising Error Content You can personalize the 404 error message within your configuration: ```javascript export default defineConfig({ notFound: { title: '404: Page Not Found', content: "We couldn't find the page you're looking for. Use the sidebar to find your way back." } }); ``` ::: callout tip "Local Development" The `docmd dev` server automatically serves your custom 404 page whenever a requested file is missing, allowing you to test the error experience locally. ::: --- ## [Versioning](https://docs.docmd.io/06/configuration/versioning/) --- title: "Versioning" description: "Enable multi-version documentation with seamless switching, sticky path preservation, and isolated build directories." --- `docmd` features a native Versioning Engine that allows you to manage and serve multiple versions of your project simultaneously (e.g., `v1.x`, `v2.x`). The engine automatically handles URL routing, sidebar updates, and switching logic. ## Directory Organisation To enable versioning, organise your documentation into versioned source folders. A common pattern is keeping the active version in `docs/` and archived versions in directories prefixed with `docs-`. ```text my-project/ ├── docs/ # Latest Version (Main) ├── docs-v1/ # Legacy Version ├── docmd.config.js ``` ## Configuration Define your versions within the `versions` object: ```javascript export default defineConfig({ versions: { current: 'v2', // The version ID built to the root (/) position: 'sidebar-top', // Switcher location: 'sidebar-top' or 'sidebar-bottom' all: [ { id: 'v2', dir: 'docs', label: 'v2.x (Latest)' }, { id: 'v1', dir: 'docs-v1', label: 'v1.x' } ] } }); ``` ## Core Features ### 1. Root SEO (The "Current" Version) The version designated as `current` is generated directly at your output root (e.g., `mysite.com/`). This ensures your primary search traffic always lands on your most up-to-date documentation. ### 2. Isolated Sub-directories Non-current versions are automatically built into subfolders matching their `id`. * `v2 (Current)` → `mysite.com/` * `v1` → `mysite.com/v1/` ### 3. Sticky Switching (Path Preservation) `docmd` preserves the relative path when a user switches versions. If a user is reading `mysite.com/getting-started` and switches to **v1**, they are automatically redirected to `mysite.com/v1/getting-started` (if the page exists) rather than being returned to the home page. ### 4. Asset Isolation Each version inherits your global `assets/` directory, but `docmd` ensures they are isolated during the build process to prevent style leakage or version conflicts. ## Best Practices 1. **Semantic IDs**: Use concise, URL-friendly IDs like `v1`, `v2`, or `beta`. 2. **Navigation Parity**: Maintain consistent folder structures across versions to maximise the effectiveness of "Sticky Switching." 3. **Unified Configuration**: You do not need separate config files for each version; `docmd` processes all versions in a single pass. --- ## [Buttons](https://docs.docmd.io/06/content/containers/buttons/) --- title: "Buttons" description: "Inject call-to-action buttons for internal routing or external resources with a minimalist syntax." --- Buttons are high-impact UI elements used for prominent navigation. Unlike block containers, the `button` is **self-closing** - it is defined on a single line and does not require a closing `:::` tag. ## Syntax ```markdown ::: button "Label" Path [Options] ``` ### Options Reference | Property | Format | Description | | :--- | :--- | :--- | | **Path** | `/path/` | Relative project URL (resolves automatically for SPA navigation). | | **External** | `external:URL`| Opens the target URL in a new browser tab (`target="_blank"`). | | **Colour** | `color:VALUE` | Applies a background colour (supports CSS names or Hex codes). | ## Usage Examples ### 1. Internal Navigation Use relative paths to ensure seamless, zero-reload transitions within the `docmd` SPA. ```markdown ::: button "Install docmd" /getting-started/installation ``` ::: button "Install docmd" /getting-started/installation ### 2. External Resource Link Prepend `external:` to the URL to secure safe external linking. ```markdown ::: button "View GitHub Repository" external:https://github.com/docmd-io/docmd ``` ::: button "View GitHub Repository" external:https://github.com/docmd-io/docmd ### 3. Semantic & Brand Styling Match buttons to your brand identity or semantic priority using colour overrides. ```markdown ::: button "Danger Action" /delete color:crimson ::: button "Success Confirmation" /success color:#228B22 ``` ::: button "Danger Action" ./#delete color:crimson ::: button "Success Confirmation" ./#success color:#228B22 ## Critical Note: Self-Closing Logic Because buttons are self-closing, adding a terminal `:::` line will terminate the **parent container** (e.g., a Card or Tab) that the button resides in, potentially breaking your layout. **Incorrect Sequence:** ```markdown ::: card "Setup" ::: button "Begin" /setup ::: <-- Error: This closes the Card prematurely. ::: ``` **Correct Sequence:** ```markdown ::: card "Setup" ::: button "Begin" /setup ::: <-- Correct: This closes the Card. ``` --- ## [Callouts](https://docs.docmd.io/06/content/containers/callouts/) --- title: "Callouts" description: "Highlight critical warnings, pro-tips, and background context using semantic visual blocks." --- Callouts are used to isolate information that requires the reader's immediate attention. `docmd` provides five semantic types, each featuring distinct visual styling and themed iconography. ## Syntax Reference ```markdown ::: callout type "Optional Title" The technical content or warning goes here. ::: ``` ### Supported Semantic Types | Type | Intent | Visual Signal | | :--- | :--- | :--- | | `info` | **General Data** | Contextual background or helpful non-critical info. | | `tip` | **Optimisation** | Performance shortcuts or "Pro-tips". | | `warning`| **Cautionary** | Potential issues or deprecated features to monitor. | | `danger` | **Critical** | Risk of data loss, breaking changes, or system failure. | | `success`| **Verification** | Confirmation of successful configuration or build. | ## Implementation Gallery ### 1. Minimalist Informational Note ```markdown ::: callout info Legacy configuration schemas remain supported but are no longer recommended. ::: ``` ::: callout info Legacy configuration schemas remain supported but are no longer recommended. ::: ### 2. High-Priority Alert with Custom Title ```markdown ::: callout warning "Breaking Change Target" As of `v0.7.0`, the internal WebSocket RPC system will be officially deprecated. ::: ``` ::: callout warning "Breaking Change Target" As of `v0.7.0`, the internal WebSocket RPC system will be officially deprecated. ::: ### 3. Rich Content Composition Callouts support the full spectrum of Markdown, allowing you to embed buttons and code blocks within the alert. ````markdown ::: callout tip "Optimised Local Testing" Use the preserve flag to maintain build files during dev sessions: ```bash docmd dev --preserve ``` ::: button "CLI Flag Reference" /cli-commands ::: ```` ::: callout tip "Optimised Local Testing" Use the preserve flag to maintain build files during dev sessions: ```bash docmd dev --preserve ``` ::: button "CLI Flag Reference" ./#cli-commands ::: ::: callout tip "Prioritised Logic for AI" For LLMs, callouts act as **High-Priority Anchors**. By utilizing `::: callout danger` to document breaking changes or system constraints, you provide a clear signal that the AI model must prioritise this information above surrounding text during its reasoning and generation process. ::: --- ## [Cards](https://docs.docmd.io/06/content/containers/cards/) --- title: "Cards" description: "Organise information into framed, visually distinct containers. Perfect for feature grids and landing pages." --- Cards are the primary structural building blocks in `docmd`. They encapsulate related content into a distinct, bordered frame with optional headers, providing a clear visual hierarchy for your documentation. ## Syntax Reference ```markdown ::: card "Optional Header Title" This is the primary content area of the card. ::: ``` ## Practical Implementation Examples ### 1. Feature Showcasing Use cards to highlight key technical advantages or module capabilities. ```markdown ::: card "Asynchronous Generation" The `docmd` core engine utilizes a non-blocking I/O pipeline, enabling the generation of thousands of pages in milliseconds. ::: ``` ::: card "Asynchronous Generation" The `docmd` core engine utilizes a non-blocking I/O pipeline, enabling the generation of thousands of pages in milliseconds. ::: ### 2. Multi-Component Integration Cards can house any standard Markdown elements, including syntax-highlighted code and call-to-action buttons. ````markdown ::: card "Instant Localisation" Prepare your documentation for a global audience using our built-in i18n support. ```bash docmd add i18n ``` ::: button "L10n Strategy Guide" /configuration/localisation ::: ```` ::: card "Instant Localisation" Prepare your documentation for a global audience using our built-in i18n support. ```bash docmd add i18n ``` ::: button "L10n Strategy Guide" ./#localisation ::: ## Multi-Column Layouts (Grids) You can use the native `grids` container to organise your cards into clean, responsive multi-column layouts without ever touching HTML. ```markdown ::: grids ::: grid ::: card "Primary Node" Configuration for the master instance. ::: ::: ::: grid ::: card "Secondary Node" Configuration for redundant slave instances. ::: ::: ::: ``` ::: callout tip "Semantic Clustering for AI" In the `llms-full.txt` stream, content wrapped in a `card` is treated by AI agents as a **Cohesive Topic Cluster**. Utilizing cards to segment unrelated technical concepts on the same page prevents context leakage and ensures that LLM-generated summaries remain logically isolated and accurate. ::: --- ## [Changelogs](https://docs.docmd.io/06/content/containers/changelogs/) --- title: "Changelogs" description: "Generate structured, timeline-based version history and release notes." --- The `changelog` container provides a specialized layout for documenting project evolution. It automatically parses date or version headers into a vertical timeline, ensuring historical updates are easily scannable. ## Syntax Utilize the specialized `==` delimiter to define entries. The text on the `==` line is rendered as a timeline badge on the left, while the following content populates the adjacent chronological slot. ```markdown ::: changelog == v2.0.0 Description of the major feature release. == v1.5.0 Description of maintenance updates and security patches. ::: ``` ## Detailed Example: Release History Changelogs support rich Markdown within each entry, including lists, callouts, and code blocks. ```markdown ::: changelog == v2.0.0 (2026-03-15) ### Major System Overhaul The core engine has been rearchitected for isomorphic execution. * Implemented **SPA Router** for zero-reload navigation. * Introduced the **Isomorphic Plugin** system. ::: callout success This release offers a 40% improvement in initial build speed. ::: == v1.5.1 (2025-12-10) ### Security Patch * Resolved high-severity vulnerability in the internal parser. * Updated dependency `flatted` to `v3.3.2`. == v1.0.0 (2024-05-01) Initial public release. ::: ``` ::: changelog == v2.0.0 (2026-03-15) ### Major System Overhaul The core engine has been rearchitected for isomorphic execution. * Implemented **SPA Router** for zero-reload navigation. * Introduced the **Isomorphic Plugin** system. ::: callout success This release offers a 40% improvement in initial build speed. ::: == v1.5.1 (2025-12-10) ### Security Patch * Resolved high-severity vulnerability in the internal parser. * Updated dependency `flatted` to `v3.3.2`. == v1.0.0 (2024-05-01) Initial public release. ::: ::: callout tip "Historical Context for AI" Changelogs provide a temporal map for AI agents. When an LLM parses the `llms-full.txt` context, the `::: changelog` structure allows it to accurately identify when specific features, breaking changes, or security fixes were introduced, leading to higher accuracy in its development recommendations. ::: --- ## [Collapsible Sections](https://docs.docmd.io/06/content/containers/collapsible/) --- title: "Collapsible Sections" description: "Embed interactive accordion-style toggles for FAQs, deep-dive content, and spoilers." --- The `collapsible` container creates an interactive, toggleable section (accordion). This pattern is ideal for FAQs, detailed technical configuration, or any secondary information that should be accessible without cluttering the primary documentation flow. ## Syntax ```markdown ::: collapsible [open] "Title Text" Main content goes here. ::: ``` ### Options Reference - **`open`**: (Optional) If specified, the section initialises in an expanded state. - **`"Title"`**: The text rendered on the interactive toggle bar. Defaults to "Click to expand" if omitted. ## Detailed Implementation Examples ### Standard Usage (Initial State: Closed) Primarily used for FAQs or reducing the visual density of technical pages. ```markdown ::: collapsible "How do I upgrade docmd?" Run `npm update -g @docmd/core` to fetch the latest stable engine. ::: ``` ::: collapsible "How do I upgrade docmd?" Run `npm update -g @docmd/core` to fetch the latest stable engine. ::: ### Opt-In Visibility (Initial State: Open) Ideal for sections that should be visible by default but allow the user to minimise them for a cleaner view. ```markdown ::: collapsible open "Environment Prerequisites" 1. Node.js v18+ (LTS recommended) 2. PNPM package manager ::: ``` ::: collapsible open "Environment Prerequisites" 1. Node.js v18+ (LTS recommended) 2. PNPM package manager ::: ### Nested Technical Data Collapsibles can contain complex Markdown elements, including syntax-highlighted code blocks. ````markdown ::: collapsible "Analyse Sample JSON Response" ```json { "status": "success", "data": { "version": "0.6.2" } } ``` ::: ```` ::: collapsible "Analyse Sample JSON Response" ```json { "status": "success", "data": { "version": "0.6.2" } } ``` ::: ::: callout tip While content inside a `collapsible` may be hidden from the human user, it remains fully visible to the `docmd` search index and is included in the unified `llms-full.txt` stream. This ensures AI agents can provide comprehensive answers based on hidden technical details while the human-facing interface remains clean and prioritised. ::: --- ## [URL Embeds](https://docs.docmd.io/06/content/containers/embed/) --- title: URL Embeds description: How to safely embed dynamic components, videos, and social media directly into your documents. --- `docmd` ships natively with the highly-optimised `embed-lite` parser ecosystem. This allows you to aggressively map raw external URLs strictly onto the page, transforming them beautifully into completely secure, zero-latency UI components instantly! ## Supported Platforms The integrated engine natively exposes structured formatters targeting the following networks identically: * **Video Ecosystem:** YouTube (including native 9:16 Shorts support), Vimeo, Dailymotion, TikTok * **Social Connections:** X (Twitter), Reddit, Instagram, Facebook, LinkedIn * **Code & Prototyping:** GitHub Gists, CodePen, Figma, Google Maps * **Music Services:** Spotify, SoundCloud ## Usage Syntax You simply use the `::: embed` container followed by any destination URL. All three enclosing formats are equivalent: ```md ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ``` ### Standard Result Example The rendering engine strictly parses that URL in the background, checking the validation matrix, and structurally injects native HTML nodes directly onto your page output gracefully: ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ## Fallback Safety Don't worry about generating broken screens. If the internal parser scans an unverified or strictly unavailable domain configuration mapping, `docmd` gracefully falls back to generating a simple, solid `<a>` hyperlink button mapping explicitly out to the target: ```md ::: embed "https://unsupported-example.com/status/123" ``` *(Proceeds to generate exactly what you would see below)* ::: embed "https://unsupported-example.com/status/123" --- ## [Grids](https://docs.docmd.io/06/content/containers/grids/) --- title: "Grids" description: "Organise layout easily with auto-adjusting responsive columns using native markdown containers." --- Grids provide a native, markdown-driven layout system in `docmd`. Instead of writing manual HTML wrappers, you can use the `grids` container to structure elements side-by-side. Columns automatically adjust their widths to fill available space and logically stack into vertical rows on smaller screens (mobile devices). ## Syntax Reference ```markdown ::: grids ::: grid #### Component A Content for the left side. ::: ::: grid #### Component B Content for the right side. ::: ::: ``` ## Practical Implementation Examples ### 1. Feature Showcasing Side-by-Side Use grids to highlight key capabilities next to each other, like combining structural cards with informational blocks. ```markdown ::: grids ::: grid ::: card "Speed :rocket:" Built on a non-blocking I/O pipeline for maximum performance. ::: ::: ::: grid ::: card "Scalability :zap:" Designed for massive monorepos and extensive project structures. ::: ::: ::: ``` ::: grids ::: grid ::: card "Speed :rocket:" Built on a non-blocking I/O pipeline for maximum performance. ::: ::: ::: grid ::: card "Scalability :zap:" Designed for massive monorepos and extensive project structures. ::: ::: ::: ### 2. Layout Balancing Grids will automatically calculate the optimal width per column (up to 4 items per row on ultra-wide screens) based on the content available and easily group rows on narrow viewports. ::: callout tip "Semantic Layouts" Using the `grids` container keeps your documentation structure purely written in Markdown, resulting in cleaner source files and ensuring LLMs interpret your structural relationships flawlessly! ::: --- ## [Hero Sections](https://docs.docmd.io/06/content/containers/hero/) --- title: "Hero Sections" description: "Build high-impact landing page headers and marketing highlights purely in Markdown." --- The `hero` container is designed for creates professional, visually-striking "landing page" headers. It handles complex CSS requirements like **Split Layouts**, **Glow Effects**, and **Sliders** while maintaining a minimalist authoring experience. ## Basic Syntax By default, the `hero` centres its content, making it perfect for banners and simple headlines. ```markdown ::: hero # Build Faster. The minimalist, zero-config documentation generator. ::: button "Get Started" /intro color:blue ::: ``` ## Advanced Layouts The `hero` container supports specialized flags to control its structural behaviour. | Flag | Effect | | :--- | :--- | | `layout:split` | Divides the hero into a Text area (left) and a Media area (right). Stacks vertically on mobile. | | `layout:slider` | Transforms the hero into a horizontal slider with scroll-snap behaviour. | | `glow:true` | Injects a subtle, radial gradient glow in the background. | ### The Split Layout (`== side`) Use the `== side` separator to define what content goes in the primary text area and what goes in the secondary "side" area (typically an image or a video embed). ```markdown ::: hero layout:split glow:true # docmd 2.0 Isomorphic execution. AI-optimised. ::: button "Quickstart" /getting-started/basic-usage color:blue == side ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ::: ``` ::: hero layout:split glow:true # docmd 2.0 Isomorphic execution. AI-optimised. ::: button "Quickstart" /getting-started/basic-usage color:blue == side ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ::: ### The Slider Layout (`== slide`) Create an interactive hero slider by using the `== slide` separator between different content nodes. ```markdown ::: hero layout:slider == slide # Isomorphic Core The engine renders everywhere. == slide # AI Optimisation Built for the LLM era. ::: ``` ::: hero layout:slider == slide # Isomorphic Core The engine renders everywhere. == slide # AI Optimisation Built for the LLM era. ::: ## Responsive Behaviour The `hero` container is fully responsive by default: - On **Desktop**, `layout:split` displays side-by-side. - On **Mobile**, it automatically transitions to a centred, vertical stack to ensure optimal readability. ## Best Practices 1. **Glow Effects**: Use `glow:true` sparingly on dark mode sites for a premium "neon" feel. 2. **Media Types**: The "side" content of a split layout is perfect for the `::: embed` component, high-quality PNGs, or raw `<video>` tags. 3. **CTA Placement**: Always place `::: button` elements within the primary "Hero Copy" section (before the `== side` separator) to ensure they are the first thing users see on mobile. --- ## [Custom Interactive Containers](https://docs.docmd.io/06/content/containers/) --- title: "Custom Interactive Containers" description: "A comprehensive directory of the interactive UI building blocks available in docmd." --- Standard Markdown excels at basic text formatting, but professional technical documentation requires rich structural components to effectively communicate complex logic. `docmd` extends Markdown with a suite of **isomorphic containers** that render into responsive, high-fidelity UI elements. ## Block Syntax Reference All containers utilize a consistent block syntax, ensuring a predictable authoring experience across your entire project. ```markdown ::: type "Optional Header Title" This is the primary content area. It supports **Markdown**, imagery, and deep component nesting. ::: ``` | Component | Keyword | Primary Use Case | | :--- | :--- | :--- | | **[Callouts](./callouts)** | `callout` | Semantic highlights for tips, warnings, and alerts. | | **[Cards](./cards)** | `card` | Framed structural blocks for feature grids and layout control. | | **[Grids](./grids)** | `grids` | Auto-adjusting multi-column structural groups. | | **[Tabs](./tabs)** | `tabs` | Interactive switchable panes for alternative platform instructions. | | **[Steps](./steps)** | `steps` | Visual numbered timelines for "How-to" guides and tutorials. | | **[Buttons](./buttons)** | `button` | Self-closing, prominent call-to-action navigation links. | | **[Collapsibles](./collapsible)**| `collapsible`| Interactive accordion toggles for FAQs and deep-dive technical data. | | **[Changelogs](./changelogs)** | `changelog` | Structured, timeline-based version history and release notes. | | **[Hero](./hero)** | `hero` | High-impact landing page sections with layout and slider support. | ## The Strategic Importance of Containers Containers facilitate more than visual polish; they provide high-fidelity **Semantic Signals** to the `docmd` engine and downstream AI agents: 1. **AI Context Mapping**: Marking a block as a `callout warning` explicitly tells LLMs to prioritise that information during its reasoning and generation phases. 2. **Structural Integrity**: Combining `cards` with standard CSS allows for the creation of sophisticated landing pages without ever leaving the Markdown environment. 3. **Source Maintainability**: Eliminates "HTML Bloat" in your documentation source, keeping your `.md` files clean and machine-readable. ## Recursive Composition `docmd` supports **Infinite Nesting Depth**. You can compose any container within another to build complex, interactive documentation nodes purely with minimalist Markdown syntax. ```markdown ::: card "Architecture Overview" ::: callout info This module utilizes an asynchronous I/O pipeline. ::: ::: button "Deep Explore Core Engine" /advanced/developer-guide ::: ``` [Master the Nesting Guide →](./nested-containers) --- ## [Nested Containers](https://docs.docmd.io/06/content/containers/nested-containers/) --- title: "Nested Containers" description: "Use docmd's recursive parser to combine cards, tabs, and callouts into high-fidelity page layouts." --- One of `docmd`’s most powerful technical capabilities is its **Recursive Parsing Engine**. You can nest components within each other infinitely to synthesize complex, interactive documentation blocks that would otherwise require deep HTML knowledge or custom templates. ## The Architectural Rule While nesting is mathematically infinite, always adhere to the **Self-Closing Component Rule**: ::: callout warning "Self-Closing Buttons" Because the `::: button` component is self-closing (single line), never add a terminal `:::` line after it. Doing so will inadvertently close the **parent container** housing the button, resulting in a fractured layout. ::: ## Technical Composition Examples ### 1. Interactive Resource Block Combine a **Card** for structural framing, **Tabs** for environment-specific instructions, and **Callouts** for highlighting critical information. ````markdown ::: card "Monorepo Quickstart" Choose your preferred initialisation path: ::: tabs == tab "Automated" ```bash pnpm onboard ``` ::: callout success This script handles all package installation and build tasks automatically. ::: == tab "Manual" Manually fetch and link the core engine. ::: button "Go to Developer Guide" /advanced/developer-guide ::: ::: ```` ### 2. Multi-Platform Tutorials Nesting **Tabs** inside **Steps** is a professional pattern for providing platform-specific instructions within a standard tutorial sequence. ```markdown ::: steps 1. **Environment Setup** Configure your local operating system. ::: tabs == tab "macOS" Ensure Homebrew is installed and up-to-date. == tab "Linux" Verify the Presence of `curl` and `bash`. ::: 2. **Core Verification** Execute the version check to confirm connectivity. ::: ``` ::: steps 1. **Environment Setup** Configure your local operating system. ::: tabs == tab "macOS" Ensure Homebrew is installed and up-to-date. == tab "Linux" Verify the Presence of `curl` and `bash`. ::: 2. **Core Verification** Execute the version check to confirm connectivity. ::: ## Design Constraints To maintain both performance and mobile responsiveness, observe the following constraints: * **Recursive Tabs**: Nesting tabs within other tabs is technically supported but strongly discouraged. It creates navigation "loops" that are visually confusing on smaller viewports. * **Sequential Conflict**: If you require numbered steps within a tab, utilize a standard ordered list (`1. Step Content`) rather than the `::: steps` container to avoid layout conflicts. * **Legibility**: While `docmd` does not strictly require indentation for nested blocks, using a 2 or 4-space indentation significantly improves the human-readability of the Markdown source. ::: callout tip "Knowledge Segmentation for AI" Nesting provides clear **Semantic Boundaries**. When an AI agent parses the `llms-full.txt` stream, a `callout` nested within a `card` explicitly tells the model that the tip is scoped to that card's specific topic, preventing context leakage and improving technical accuracy in generated responses. ::: --- ## [Steps](https://docs.docmd.io/06/content/containers/steps/) --- title: "Steps" description: "Convert standard ordered lists into high-impact visual timelines and tutorials." --- The `steps` container is designed specifically for "How-to" guides and technical tutorials. It transforms a standard Markdown ordered list into a polished, numbered vertical timeline with automatic spacing and visual emphasis. ## Syntax Wrap any standard ordered list in a `::: steps` block. ```markdown ::: steps 1. **Initialise Project** Run the `docmd init` command to scaffold your directory. 2. **Author Content** Write your documentation using standard Markdown files. 3. **Build & Deploy** Generate static assets using `docmd build`. ::: ``` ## Detailed Implementation The `steps` component supports rich Markdown content within each item, including code blocks, images, and nested containers. ```markdown ::: steps 1. **Generate Production Build** Execute the build command to generate a highly optimised static site. ```bash docmd build ``` 2. **Verify Asset Integrity** Inspect the `site/` directory to ensure all assets were correctly compiled. 3. **Deploy to Infrastructure** Synchronise the `site/` directory with your primary hosting provider (e.g., S3, Cloudflare Pages, or Vercel). ::: ``` ::: steps 1. **Generate Production Build** Execute the build command to generate a highly optimised static site. ```bash docmd build ``` 2. **Verify Asset Integrity** Inspect the `site/` directory to ensure all assets were correctly compiled. 3. **Deploy to Infrastructure** Synchronise the `site/` directory with your primary hosting provider (e.g., S3, Cloudflare Pages, or Vercel). ::: ## Advanced Nesting You can nest other documentation components (such as **Callouts** or **Buttons**) inside a step without interrupting the chronological flow of the sequence. ```markdown ::: steps 1. **Configure Environment** Define your project-specific variables in `docmd.config.js`. ::: callout tip Use `defineConfig` to enable IDE autocompletion for configuration keys. ::: 2. **Validate Schema** Run `docmd verify` to ensure your configuration is structurally sound. ::: ``` ::: callout tip "Workflow Optimisation" Modern AI models interpret the `steps` container as a high-fidelity signal for **Sequential Workflows**. To maximise AI accuracy in the `llms-full.txt` context, always start your list items with a **Bolded Title**. This allows agents to reliably parse the objective of each step before processing the implementation details. ::: --- ## [Tabs](https://docs.docmd.io/06/content/containers/tabs/) --- title: "Tabs" description: "Organise dense, alternative, or multi-language information into switchable interactive panes." --- Tabs are the optimal UI pattern for presenting mutually exclusive or related data sets (e.g., "Install via NPM vs. Yarn" or "macOS vs. Windows" instructions) within a compact, interactive format. ## Syntax Reference The `tabs` container utilizes the specialized sub-delimiter `== tab "Label"`. Each label defines a distinct pane that users can toggle between. ```markdown ::: tabs == tab "Label 1" Content for the first tab. == tab "Label 2" Content for the second tab. ::: ``` ## Implementation Gallery ### 1. Package Management Tabs are most commonly used to show installation instructions for different package managers in a single view. ::: tabs == tab "pnpm" ```bash pnpm add @docmd/core ``` == tab "npm" ```bash npm install @docmd/core ``` == tab "yarn" ```bash yarn add @docmd/core ``` ::: ### 2. Multi-Language Code Snippets Keep your logic clean by separating different programming languages or environments. ::: tabs == tab "TypeScript" ```typescript import { build } from '@docmd/core'; await build('./docmd.config.js'); ``` == tab "JavaScript" ```javascript const { build } = require('@docmd/core'); build('./docmd.config.js'); ``` ::: ## Core Capabilities ### Isomorphic Lazy Rendering `docmd` implements **Conditional Resource Laziness**. If a tab contains computationally expensive elements (e.g., **Mermaid.js** diagrams or high-resolution images), these assets are only initialised and rendered once the user activates that specific tab. This ensures rapid initial page loads. ### State Persistence The default SPA router tracks the active tab's index across similar documentation pages. If a user selects "pnpm" on one page and navigates to another page with a matching tab structure, the "pnpm" tab will remain active automatically. ## Technical Constraints | Constraint | Note | | :--- | :--- | | **Nesting Depth** | To preserve layout integrity, tabs cannot be nested inside other tab components. | | **Interactive Conflict**| High-conflict syntax: To nest Steps inside a Tab, use a standard ordered list (`1. Step One`) instead of the `::: steps` container. | | **Responsive Limit** | It is recommended to limit tab counts to 6 per block to ensure mobile device compatibility. | ::: callout tip "AI Context Mapping" When utilizing tabs for code snippets, always include the target language directly in the tab label (e.g., `== tab "TypeScript"`). This allows LLMs to instantly identify and extract the technically relevant section from the `llms-full.txt` context stream. ::: --- ## [Frontmatter Reference](https://docs.docmd.io/06/content/frontmatter/) --- title: "Frontmatter Reference" description: "The complete guide to page-level metadata and configuration in docmd." --- Frontmatter allows you to override global settings on a per-page basis. It must be written in YAML format at the very top of your Markdown file. ## Core Metadata | Key | Type | Description | | :--- | :--- | :--- | | `title` | `String` | **Required.** Sets the HTML `<title>` and the primary section header. | | `description` | `String` | Sets the meta description for SEO and search results. | | `keywords` | `Array` | A list of keywords for the `<meta name="keywords">` tag. | ## Visibility & Indexing | Key | Type | Description | | :--- | :--- | :--- | | `noindex` | `Boolean` | Excludes the page from the internal search index. | | `llms` | `Boolean` | Set to `false` to exclude this page from the AI context files (`llms.txt`). | | `hideTitle` | `Boolean` | Hides the title from the sticky header (useful if using a custom H1). | | `bodyClass` | `String` | Adds a custom CSS class to the `<body>` tag of this page. | ## Layout Control | Key | Type | Description | | :--- | :--- | :--- | | `layout` | `String` | Set to `full` to use the primary content width and hide the TOC sidebar. | | `toc` | `Boolean` | Set to `false` to disable the Table of Contents entirely. | | `noStyle` | `Boolean` | Disables the entire `docmd` UI (Sidebar, Header, Footer) for custom pages. | ### `noStyle` Component Control When `noStyle: true` is active, you must explicitly opt-in to the components you wish to retain: ```yaml --- noStyle: true components: meta: true # Injects SEO metadata favicon: true # Injects site favicon css: true # Injects docmd-main.css theme: true # Injects theme-specific styling highlight: true # Injects syntax highlighting scripts: true # Injects the SPA router logic sidebar: true # Injects the navigation sidebar footer: true # Injects the site footer --- ``` ## Plugin Overrides ### SEO (`seo`) * `image`: Custom social share image URL for the page. * `aiBots`: Set to `false` to block specifically AI crawlers from this page. * `canonicalUrl`: Sets a custom canonical link for SEO. --- ## [Live Preview](https://docs.docmd.io/06/content/live-preview/) --- title: "Live Preview" description: "Run docmd entirely in the browser without a backend server using the Live architecture." --- `docmd` features a modular architecture that separates filesystem operations from core processing logic. This enables the documentation engine to run **entirely within the browser**, facilitating live editors and CMS previews without the need for a Node.js backend. ::: button "Open Live Editor" https://live.docmd.io ## The Live Editor The built-in Live Editor provides a high-performance, split-pane interface. Author your Markdown in the left pane and observe the rendered output navigate and synchronise in real-time on the right. ### Local Execution To launch the Live Editor locally within your project: ```bash docmd live ``` ### Static Distribution Generate a standalone, static version of the editor for hosting on platforms like Vercel or GitHub Pages: ```bash docmd live --build-only ``` This generates a `dist/` directory containing the `index.html` entry point and the bundled `docmd-live.js` isomorphic engine. ## Embedding docmd You can integrate the browser-compatible bundle into your own applications to provide internal Markdown rendering or preview capabilities. ### 1. Resource Integration Include the required CSS and JavaScript bundles from your assets or a CDN: ```html <link rel="stylesheet" href="/assets/css/docmd-main.css"> <script src="/docmd-live.js"></script> ``` ### 2. Isomorphic API The global `docmd` object provides the `compile` method for instantaneous rendering. ```javascript const html = await docmd.compile(markdown, { siteTitle: 'Dynamic Preview', theme: { appearance: 'dark' } }); // Inject into an iframe for style isolation document.getElementById('preview-frame').srcdoc = html; ``` ::: callout tip "AI Feedback Loops" The Live architecture is ideal for building **AI-Agent Sandboxes**. Instead of providing an agent with filesystem write access, you can pipe its suggested documentation changes to a live-compilation buffer. This allows you to visually verify AI suggestions in a "ghost" environment before committing changes to your repository. ::: --- ## [docmd : Bespoke No-Style Page Demo](https://docs.docmd.io/06/content/no-style-example/) --- title: "docmd : Bespoke No-Style Page Demo" description: "A functional demonstration of the noStyle architectural feature." noStyle: true components: meta: true favicon: true css: true theme: true scripts: true mainScripts: true copyCode: true customHead: | <style> body { font-family: 'Inter', -apple-system, system-ui, sans-serif; margin: 0; padding: 0; line-height: 1.6; background: var(--bg-primary); color: var(--text-primary); } .demo-container { max-width: 900px; margin: 0 auto; padding: 80px 20px; } .demo-hero { text-align: centre; margin-bottom: 60px; } .demo-hero h1 { font-size: 3.5rem; margin-bottom: 20px; color: var(--brand-primary, #4a6cf7); } .demo-hero p { font-size: 1.25rem; color: var(--text-secondary); } .demo-card { background: var(--bg-secondary, #f8f9fa); padding: 40px; border-radius: 16px; border: 1px solid var(--border-color); box-shadow: 0 4px 20px rgba(0,0,0,0.05); } .demo-button { display: inline-block; padding: 14px 28px; background-color: var(--brand-primary, #4a6cf7); color: white; text-decoration: none; border-radius: 8px; font-weight: 600; margin-top: 30px; transition: filter 0.2s ease; } .demo-button:hover { filter: brightness(1.1); } </style> --- <div class="demo-container"> <div class="demo-hero"> <h1>Bespoke Page Architecture</h1> <p>Demonstrating the absolute layout control enabled via <code>noStyle: true</code>.</p> </div> <div class="demo-card"> <h2>Logical Foundation</h2> <p> This demonstration utilizes the <code>noStyle: true</code> frontmatter directive to bypass the global documentation layout (Sidebar, Header, and TOC). This provides a "Zero-Friction" canvas for creating marketing landing pages or custom product dashboards. </p> <h3>Enabled System Components</h3> <p>When in No-Style mode, you explicitly opt-in to the documentation engine's core features:</p> <ul> <li><strong>SEO Meta Engine</strong>: Structured tags and social graph data are retained.</li> <li><strong>Project Branding</strong>: Global favicon injection remains active.</li> <li><strong>Foundational Typography</strong>: The processed <code>docmd-main.css</code> provides base styling.</li> <li><strong>Theme Synchronisation</strong>: Light/Dark mode state is fully preserved.</li> <li><strong>Interactive Capabilities</strong>: The SPA router and component logic remain available.</li> </ul> <h3>Technical Implementation</h3> <p> The layout for this page is authored using standard HTML wrappers and scoped CSS defined within the <code>customHead</code> frontmatter field. This ensures zero CSS leakage to the rest of the documentation site. </p> <a href="/content/no-style-pages/" class="demo-button">Analyse the Implementation Guide →</a> </div> </div> --- ## [No-Style Pages](https://docs.docmd.io/06/content/no-style-pages/) --- title: "No-Style Pages" description: "Create custom landing pages and unique layouts by disabling the default docmd theme." --- `docmd` allows you to bypass the standard documentation layout (Sidebar, Header, and Footer) on a per-page basis. This is ideal for creating product landing pages, custom dashboards, or marketing splash screens while maintaining access to the documentation engine's components. ## Enabling No-Style Mode To disable the global UI, add `noStyle: true` to the page's frontmatter. ```yaml --- title: "Product Showcase" noStyle: true components: meta: true # Retain SEO and OpenGraph tags favicon: true # Retain site favicon css: true # Inject docmd-main.css for typography --- <!-- Raw HTML or specialized Markdown goes here --> <div class="hero"> <h1>Next-Gen Documentation</h1> <p>Minimalist. Isomorphic. AI-Ready.</p> </div> ::: callout info "Infinite Nesting Support" Even with `noStyle: true`, all standard `docmd` containers like `::: card`, `::: tabs`, and `::: hero` are fully supported and can be nested at any depth. ::: ``` ## Component Opt-In When `noStyle` is active, you start with a blank canvas. Selectively re-enable core system components as needed: | Component | Description | | :--- | :--- | | `meta` | Injects `<title>`, SEO meta tags, and structured OpenGraph data. | | `favicon` | Injects the project-wide favicon. | | `css` | Injects `docmd-main.css`. Highly recommended for foundational grid and typography. | | `menubar` | Injects the site's top menubar. | | `theme` | Injects the active theme's CSS variables and appearance overrides. | | `scripts` | Injects interactive component logic (requires `mainScripts: true`). | | `spa` | Enables the single-page application router (requires `scripts: true`). | ## Composable Landing Pages The primary power of `noStyle` is that it allows you to use the entire suite of `docmd` components as high-fidelity "widgets" on a blank canvas. You aren't limited to raw HTML; you can build complex, structural designs purely in Markdown. ### Building a Modern Entry Point ```yaml --- title: "Welcome" noStyle: true components: meta: true css: true menubar: true # Use the site's top navigation scripts: true # Enable interactive components mainScripts: true --- ::: hero layout:split glow:true # Build Documentation that Wows. The zero-config engine for modern engineering teams. ::: button "Get Started" /introduction color:blue ::: button "GitHub" github:docmd-io/docmd color:gray == side ::: embed [https://www.youtube.com/watch?v=dQw4w9WgXcQ] ::: ::: ::: grids ::: card "Zero Configuration" Just write markdown. No complex React logic or build scripts. ::: ::: card "AI Optimised" Structure-aware parsing for the LLM era. ::: ::: card "Blazing Fast" Static generation with isomorphic SPA navigation. ::: ::: ``` ::: callout tip "AI-Generated Layouts" Because `noStyle` pages support raw HTML alongside `docmd` containers, they are perfectly suited for **AI-driven UI design**. You can prompt an AI: *"Design a modern hero section using Tailwind-like utility classes and docmd buttons, wrapped in a noStyle: true container."* The AI can iterate on the design within your static site pipeline with zero additional configuration. ::: --- ## [Advanced Markdown Syntax](https://docs.docmd.io/06/content/syntax/advanced/) --- title: "Advanced Markdown Syntax" description: "Use docmd's extended feature set: Custom attributes, GFM extensions, and semantic definitions." --- Beyond standard Markdown, `docmd` supports several high-fidelity extensions derived from GitHub Flavored Markdown (GFM) and custom attribute plugins. These tools provide total control over your document's structure and styling. ## GFM Extensions ### Task Lists Create interactive or read-only checklists for roadmap tracking. ```markdown - [x] Engine Optimisation Complete - [ ] Plugin API Finalization ``` - [x] Engine Optimisation Complete - [ ] Plugin API Finalization ### Automatic Link Resolution Standard URLs and email addresses are automatically identified and linked without additional markup: `https://docmd.io` ### Shortcode Emojis `docmd` supports standard shortcodes to inject visual personality into your documentation. > We :heart: high-performance documentation! :rocket: :smile: ## Custom Element Attributes Assign unique IDs and CSS classes directly to headers, images, and links using the curly-brace `{}` syntax. This is the primary method for applying [Custom CSS Styles](/theming/custom-css-js). ### Unique Semantic IDs Useful for deep-linking directly to technical subsections. ```markdown ## Performance Benchmarks {#benchmarks-2026} ``` ### Functional CSS Classes Apply styling utilities to specific elements. ```markdown ## Center-Aligned Section {.text-centre .text-blue} ``` ### Actionable Button Links Transform any standard markdown link into a styled call-to-action button. ```markdown [Download Latest Release](/download){.docmd-button} ``` ## Citations & Definitions ### Footnote References Add citations or technical deep-dives[^1] that are automatically collected and rendered at the bottom of the page. ```markdown Architectural decisions are documented in the RFC[^1]. [^1]: RFC-42: Isomorphic Rendering Pipeline. ``` ### Definition Lists Perfect for API parameter descriptions and glossaries. ```markdown PropName : The unique identifier for the configuration key. ``` PropName : The unique identifier for the configuration key. ### Technical Abbreviations Define abbreviations globally within a page. Hovering over the term reveals its full definition. ```markdown *[SPA]: Single Page Application The docmd router enables a seamless SPA experience. ``` *[SPA]: Single Page Application The docmd router enables a seamless SPA experience. ::: callout tip "Contextual Precision for AI" Utilizing **Definitions** and **Abbreviations** provides high-quality technical signals to AI agents. When an AI processes your `llms-full.txt` context, these explicit definitions prevent lexical ambiguity, ensuring the model generates logically correct explanations for your project's specific terminology. ::: --- ## [Code Blocks](https://docs.docmd.io/06/content/syntax/code/) --- title: "Code Blocks" description: "Document technical implementations with high-fidelity syntax highlighting and interactive copy buttons." --- `docmd` utilizes the ultra-fast `lite-hl` engine to provide automatic, context-aware syntax highlighting across hundreds of programming languages and configuration formats. ## Syntax Highlighting Author your technical examples using standard Markdown fenced code blocks. Always specify the language identifier to ensure the highlight engine applies the correct lexical rules. ````markdown ```javascript function initialise() { console.log("docmd engine active."); } ``` ```` **Rendered Result:** ```javascript function initialise() { console.log("docmd engine active."); } ``` ::: callout tip "One-Click Portability" When `copyCode: true` is enabled in your configuration (default), a subtle copy button automatically appears in the top-right corner of every code block on hover, allowing users to instantly transfer snippets to their IDE. ::: ## Strategy for AI Context When documenting code for consumption by LLMs and AI Agents, adhere to these technical best practices: 1. **Strict Language Labeling**: Explicitly labeling blocks as `typescript`, `bash`, or `json` ensures the AI parser accurately interprets the block's grammar within the `llms-full.txt` stream. 2. **Embedded Intent**: Use inline comments within your code blocks to explain the *why* behind complex logic. This provides the AI with critical reasoning context that simple text outside the block might lack. ## Language Support Reference `docmd` provides out-of-the-box support for the most common technical ecosystems, including: * **Logic**: `javascript`, `typescript`, `python`, `rust`, `go`, `ruby`, `csharp`. * **Web**: `html`, `css`, `markdown`. * **Data & Shell**: `json`, `yaml`, `bash`, `powershell`, `dockerfile`. * **Documentation**: `mermaid`, `changelog`. --- ## [Images & Visual Media](https://docs.docmd.io/06/content/syntax/images/) --- title: "Images & Visual Media" description: "Master media management: Responsive images, styling attributes, and automated Lightbox effects." --- `docmd` utilizes standard Markdown syntax for media integration. We recommend centralizing your media assets in the `assets/images/` directory within your project source. ```markdown ![Technical Diagram](/assets/images/architecture.png "Optional Tooltip Title") ``` ## Technical Styling Reference Assign specialized CSS classes and attributes directly to your images using the `{ .class }` attribute syntax. ### Dynamic Resizing ```markdown ![Small Scale](/assets/icon.png){ .size-small } ![Standard View](/assets/preview.png){ .size-medium } ![Full Scale](/assets/banner.png){ .size-large } ``` ### Alignment & Layout ```markdown ![Centred Focus](/assets/img.png){ .align-centre } ![Floating Right](/assets/img.png){ .align-right .with-shadow .with-border } ``` ![Advanced Styling Example](/assets/images/docmd-preview.png){.with-border .with-shadow .size-medium .align-centre} ## Structured Media Elements ### Figure Captions For precise, accessible media captioning, use standard HTML5 `<figure>` elements. ```html <figure> <img src="/assets/diagram.png" alt="Cloud Infrastructure Diagram"> <figcaption>Figure 1.1: Core System Infrastructure Architecture.</figcaption> </figure> ``` ### Image Galleries Organise multiple assets into a responsive, balanced grid using the `image-gallery` class. ```html <div class="image-gallery"> <figure> <img src="/assets/screen1.jpg" alt="User Dashboard View"> <figcaption>Live Performance Monitor</figcaption> </figure> <figure> <img src="/assets/screen2.jpg" alt="Configuration Panel View"> <figcaption>Project Global Settings</figcaption> </figure> </div> ``` ## Interactive Lightbox Zoom If the `mainScripts` component is active (default), `docmd` automatically applies a full-screen zoom effect to any image contained within a gallery or any image tagged with the `.lightbox` class. ```markdown ![Deep Texture Analysis](/assets/sample.png){ .lightbox } ``` ::: callout tip "AI Context & Accessibility" Always provide comprehensive **Alt-Text** for visual media. While advanced AI models possess vision capabilities, descriptive text within the Markdown source provides a direct, high-fidelity signal for the model's reasoning engine - enhancing architectural analysis and feature comprehension in the `llms-full.txt` stream. ::: --- ## [Markdown Syntax Foundation](https://docs.docmd.io/06/content/syntax/) --- title: "Markdown Syntax Foundation" description: "Master the fundamental formatting rules of docmd: Headings, typographic styles, and technical blocks." --- `docmd` adheres to standard **GitHub Flavored Markdown (GFM)** specifications. This guide establishes the baseline standards for authoring core content across your documentation site. ## Typographic Styling | Attribute | Markdown Syntax | Visual Outcome | | :--- | :--- | :--- | | **Emphasis** | `**Text**` | **Bold technical terms** | | **Italic** | `*Text*` | *Stylized variables* | | **Strikethrough** | `~~Text~~` | ~~Deprecated logic~~ | | **Inline Logic** | `` `code` `` | `engine.initialise()` | ## Structural Elements ### Semantic Header Hierarchy ```markdown # Level 1 (Automatic via Frontmatter) ## Level 2 (Major Section) ### Level 3 (Feature Detail) ``` ::: callout tip "Logical Integrity for AI" Advanced AI models and search internalizers rely on a strict heading hierarchy to build an accurate mental model of your project. By avoiding "Heading Skipping" (e.g., jumping from H2 directly to H4), you ensure the `llms-full.txt` context stream remains chronologically and logically sound. ::: ### Navigation & Reference Utilize standard link syntax for both internal documentation nodes and global resources. ```markdown [Global Resource](https://docmd.io) [Internal Module](../api/node-api.md) ``` ### Enumeration & Listing * **Unordered Segments**: Utilize `*` or `-` for scannable bullet points. * **Sequential Logic**: Utilize `1.`, `2.`, etc., for ordered instructions. (For tutorials, consider the high-impact **[Steps Container](../containers/steps)**). ## Technical Block Elements ### Blockquotes The standard `>` syntax is ideal for highlighting outside quotes or background context. > The docmd engine redefines the boundaries between static site generation and dynamic application delivery. ### Data Schemas (Tables) | Attribute | Data Type | Default | | :--- | :--- | :--- | | `name` | `string` | `undefined` | | `active` | `boolean` | `true` | ## Embedded HTML Support As `docmd` is built with raw HTML parsing enabled, you can inject complex layouts or unique styling directly within your Markdown files for specialized UI requirements. ```html <div style="padding: 2rem; border: 1px solid var(--border-color); border-radius: 12px; text-align: centre;"> Bespoke UI elements live here. </div> ``` --- ## [Linking & Referencing](https://docs.docmd.io/06/content/syntax/linking/) --- title: "Linking & Referencing" description: "Master internal cross-linking, external resources, and reliable asset referencing." --- `docmd` provides a reliable, filesystem-aware linking system. By using relative paths to your source `.md` files, you ensure that links remain functional within your IDE (e.g., VS Code) and are automatically rewritten for production deployment. ::: callout info "Extension Neutrality" During the build process, the engine automatically resolves `.md` extensions to their relative HTML counterparts. This guarantees that internal documentation links never break, regardless of whether you are browsing local source or the compiled production site. ::: ## Internal Link Resolution | Targeting Strategy | Markdown Syntax | | :--- | :--- | | **Sibling Page** | `[System Overview](overview.md)` | | **Subdirectory** | `[API Reference](api/node-api.md)` | | **Parent Directory**| `[Back to Home](../index.md)` | ## Section Anchors (Deep Linking) Navigate directly to specific headings using standard URL slugs. * **Intra-page Anchor**: `[Jump to Roadmap](#project-roadmap)` * **Cross-page Anchor**: `[Review CLI Flags](../cli-commands.md#available-flags)` ## Protocols & External Resources The engine respects standard browser protocols for global resources. * **Global HTTPS**: `[docmd Homepage](https://docmd.io)` * **Mail Protocol**: `[Support Channel](mailto:help@docmd.io)` * **Asset Protocol**: `[Download CLI Binary](/assets/bin/docmd-mac.zip)` ## Static Asset Referencing To provide downloads or reference raw source files, place them within the `assets/` directory of your project. The `docmd` builder ensures these files are moved to the production root without path modifications. ```markdown [Download Documentation PDF](/assets/pdf/handbook.pdf) [View Raw Global Config](/assets/config/docmd.config.js) ``` ::: callout tip "Semantic Linkage for AI" When cross-linking technical modules, prioritise **Descriptive Anchors** (e.g., `[Optimise PWA caching](../plugins/pwa.md)`) over generic text (e.g., `[Read more](../plugins/pwa.md)`). Detailed link labels provide AI agents with a high-fidelity map of the semantic relationships between different documentation nodes in the `llms-full.txt` context. ::: --- ## [Contributing](https://docs.docmd.io/06/contributing/) --- title: "Contributing" description: "Guidelines and setup instructions for contributing to docmd." --- Thank you for your interest in contributing to `docmd`! We appreciate all contributions, from bug fixes and documentation improvements to new features and design suggestions. ## Development Environment `docmd` is a monorepo managed with [pnpm](https://pnpm.io/). ### Prerequisites - **Node.js**: v22.x or later (LTS recommended) - **pnpm**: v10.x or later ### Project Setup Clone the repository and run the automated onboarding tool to install dependencies and perform an initial build: ```bash git clone https://github.com/docmd-io/docmd.git cd docmd pnpm onboard ``` To link the local `docmd` command globally for testing in other projects: ```bash pnpm onboard --link ``` ### Local Development Run the documentation site while watching for changes in the core engine: ```bash pnpm run dev ``` To watch internal source files (engine, templates, and plugins), set the `DOCMD_DEV` environment variable: ```bash DOCMD_DEV=true pnpm run dev ``` ## Quality Standards Ensure your code complies with the native codebase style guides enforced by our ESLint settings. For minor formatting issues, you can automatically fix them utilizing: ```bash pnpm lint:fix ``` Before submitting a Pull Request, please verify your entire branch compiles flawlessly against the continuous integration Gauntlet by preparing the final release image: ```bash pnpm prep ``` *(This rigorously chains `pnpm reset`, dependency installation, lint checks, E2E tests, and deep security audits in a fresh slate.)* ### Commit Guidelines We use [Conventional Commits](https://www.conventionalcommits.org/). Please prefix your commit messages with: - `feat:` (New features) - `fix:` (Bug fixes) - `docs:` (Documentation changes) - `refactor:` (Code changes that neither fix bugs nor add features) ### Source Headers All new files within the `packages/` directory MUST include the standard project copyright header to maintain consistency and compliance. ```javascript /** * -------------------------------------------------------------------- * docmd : the minimalist, zero-config documentation generator. * * @package @docmd/core (and ecosystem) * @website https://docmd.io * @repository https://github.com/docmd-io/docmd * @license MIT * @copyright Copyright (c) 2025-present docmd.io * * [docmd-source] - Please do not remove this header. * -------------------------------------------------------------------- */ ``` ## GitHub Workflow 1. **Fork and Branch**: Create a feature branch from the latest `main`. 2. **Verify**: Ensure `pnpm verify` returns `🛡️ docmd is ready for production!`. 3. **Pull Request**: Open a PR with a clear description of the problem solved or the feature added. --- ## [Deployment](https://docs.docmd.io/06/deployment/) --- title: "Deployment" description: "Host your docmd documentation on platforms like GitHub Pages, Vercel, Netlify, and Cloudflare Pages." --- Because `docmd` generates a high-performance static website, it can be hosted on any environment that serves HTML. Simply run the build command and deploy the output directory (Default: `site/`). ```bash docmd build ``` ## Hosting Providers ::: tabs == tab "GitHub Pages" The recommended method is using **GitHub Actions** to automate your deployments on every push. **Create `.github/workflows/deploy.yml`:** ```yaml name: Deploy docmd on: push: branches: ["main"] permissions: contents: read pages: write id-token: write jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '22' } - run: npx @docmd/core build - uses: actions/upload-pages-artifact@v3 with: { path: ./site } - uses: actions/deploy-pages@v4 ``` == tab "Vercel" 1. Connect your repository to Vercel. 2. In the project **Build Settings**: - **Framework Preset**: `Other` - **Build Command**: `npx @docmd/core build` - **Output Directory**: `site` 3. Deploy. Vercel automatically detects the static output and serves it globally. == tab "Netlify" 1. Import your project from GitHub/GitLab/Bitbucket. 2. Configure your build settings: - **Build command**: `npx @docmd/core build` - **Publish directory**: `site` 3. Click **Deploy site**. Netlify's CDN will handle the routing and asset delivery. == tab "Cloudflare Pages" 1. Create a new project in the Cloudflare Dashboard under **Pages**. 2. Connect your git provider and select your repository. 3. Configure the build settings: - **Framework preset**: `None` - **Build command**: `npx @docmd/core build` - **Build output directory**: `site` 4. Save and Deploy. == tab "Firebase" 1. Install the Firebase CLI: `npm install -g firebase-tools`. 2. Build your site: `npx @docmd/core build`. 3. Run `firebase init hosting` and select your project. 4. Set the public directory to `site`. 5. Configure as a single-page app: `Yes` (this handles the 404 behaviour). 6. Deploy using `firebase deploy`. == tab "Static Server" For traditional web servers (NGINX, Apache, IIS): 1. Generate the site: `npx @docmd/core build`. 2. Upload the contents of the `site/` folder to your server via SFTP, SCP, or your preferred CI/CD tool. 3. Ensure your server is configured to serve `index.html` for directories (the default for most). == tab "Docker" For self-hosting within a containerized environment, you can use a simple Nginx-based Dockerfile: ```dockerfile # Build Stage FROM node:22-alpine AS builder WORKDIR /app COPY . . RUN npx @docmd/core build # Serve Stage FROM nginx:alpine COPY --from=builder /app/site /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ::: ## SPA Routing Considerations `docmd` implements a micro-SPA router that handles internal navigation smoothly. Unlike React-based SPAs, every page in `docmd` is generated as its own `index.html` file on the filesystem. This means: - **No Rewrite Rules**: You don't need to configure `index.html` rewrites on your server for most platforms. - **Deep Linking**: Direct access to URLs like `/guide/setup` works out of the box because the server finds `/guide/setup/index.html`. ## Production Checklist 1. **Site URL**: Ensure the `url` property is set in your `docmd.config.js`. This is critical for generating correct canonical tags, sitemaps, and social preview images. 2. **Redirects**: If you are migrating from another tool, use the `redirects` config to maintain your SEO rankings. 3. **Analytics**: Enable the `analytics` plugin to track user engagement and search queries. 4. **AI Ingress**: Enable the `llms` plugin to generate `llms.txt`. This allows AI agents to ingest your documentation more efficiently, providing better answers to your users. ::: callout tip "Custom 404 Pages" `docmd` automatically generates a `404.html` in your output directory. Most hosting providers (GitHub Pages, Netlify, Vercel) will automatically use this file when a user hits a missing route. ::: --- ## [Basic Usage](https://docs.docmd.io/06/getting-started/basic-usage/) --- title: "Basic Usage" description: "Learn how to initialise a project, organise your Markdown files, and build your documentation site." --- Getting started with `docmd` is designed to be instantaneous. This guide walks you through the core workflow, from initial setup to the final production build. ## 1. Project Initialisation To start a new documentation project, create a directory and execute the `init` command. ```bash mkdir my-docs && cd my-docs npx @docmd/core init ``` ### Project Structure After initialisation, your project will follow a clean and predictable structure: | File / Directory | Description | | :--- | :--- | | `docs/` | **Source Directory.** Place all your `.md` files here. | | `assets/` | Static assets (images, custom CSS, or client-side JavaScript). | | `docmd.config.js` | **Configuration File.** Define branding, navigation, and plugins. | | `site/` | **Output Directory.** Contains the generated static site after running `build`. | ## 2. Real-Time Development You can preview your changes instantly without manual rebuilding. Start the development server with: ```bash npx @docmd/core dev ``` * **Access**: `http://localhost:3000` * **Live Reload**: Changes to `.md` files or `docmd.config.js` are reflected instantly in the browser via Hot Module Replacement. ## 3. Content Organisation `docmd` maps the file structure of your `docs/` folder directly to URLs. Subdirectories are handled automatically. * `docs/index.md` → `/` (Home) * `docs/api.md` → `/api` * `docs/guides/setup.md` → `/guides/setup` ::: callout tip "Use standard Markdown" Use standard Markdown. If a page title is not defined in the frontmatter, `docmd` will automatically extract the first `H1` header as the title. ::: ## 4. Customising Navigation The sidebar navigation is controlled via the `navigation` array in `docmd.config.js`. This allows you to define a logical hierarchy for your content. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ navigation: [ { title: 'Introduction', path: '/', icon: 'home' }, { title: 'Advanced', icon: 'settings', collapsible: true, children: [ { title: 'Configuration', path: '/configuration' }, { title: 'Plugins', path: '/plugins' } ] } ] }); ``` ## 5. Production Build When you are ready to deploy, generate a production-ready static site: ```bash npx @docmd/core build ``` This command produces a highly optimised Single Page Application (SPA) in the `site/` directory. The output is entirely static and can be hosted on platforms like GitHub Pages, Vercel, Netlify, or even served from a local file system. ### Verification To verify your production build locally, you can use any static file server (e.g., `npx serve site`) to ensure all links and assets are functioning correctly before deployment. --- ## [Installation](https://docs.docmd.io/06/getting-started/installation/) --- title: "Installation" description: "Instructions for installing docmd globally, locally, or using it on-the-fly with npx." --- `docmd` is a Node.js-based documentation generator. It requires **Node.js (v18.x or higher)** to be installed on your system. There are several ways to deploy and use `docmd`. You can execute it instantly without installation, or integrate it permanently into your development workflow. ## Option 1: Instant Execution (Zero-Config) You can run `docmd` inside any directory containing Markdown files. It automatically scans your files, extracts headings for page titles, and generates a nested navigation structure. No configuration or formal setup is required. ```bash # Start a local development server on http://localhost:3000 npx @docmd/core dev -z # Generate a production-ready static site in the /site directory npx @docmd/core build -z ``` ::: callout warning "Beta Feature" Zero-Config mode (`-z`) is currently in beta. While it is excellent for rapid prototyping and internal documentation, we recommend initialising a project configuration (`docmd.config.js`) for production-grade sites to ensure maximum stability and control. ::: ## Option 2: Local Project Installation (Recommended) For long-term projects, we recommend installing `docmd` as a development dependency. This ensures version consistency across your team and CI/CD environments. ```bash # 1. Install docmd as a development dependency npm install -D @docmd/core # 2. Initialise your project configuration npx @docmd/core init # 3. Start the development server npx @docmd/core dev ``` ## Option 3: Global Installation If you prefer to have the `docmd` CLI available globally across your system: ```bash # Install globally npm install -g @docmd/core # Use the 'docmd' command anywhere docmd dev # Start development server docmd build # Build static site ``` ## Developer Integration (Browser-Only) ::: callout info "Library Use Only" This method is intended for developers who wish to embed the `docmd` parsing and rendering engine inside another web application, such as a CMS, a Live Preview tool, or a custom dashboard. It is **not** the standard way to build standalone documentation sites. ::: To render `docmd` syntax dynamically in a web application without a Node.js backend, include the following assets: ```html <!-- 1. Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- 2. Processing Engine --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` Refer to the [Browser API](../api/browser-api.md) guide for integration details. ## Troubleshooting ::: callout warning "Permission Denied (EACCES)" If you encounter `EACCES` errors on macOS or Linux during global installation, it indicates insufficient permissions for global directories. **Resolution:** Use `sudo npm install -g @docmd/core` or, preferably, use a Node version manager like `nvm` to manage global packages without root access. ::: ::: callout info "PowerShell Script Execution" On Windows, if you receive an error stating that "running scripts is disabled on this system," execute the following command in PowerShell as an Administrator: `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` ::: --- ## [Zero-Config Mode](https://docs.docmd.io/06/getting-started/zero-config/) --- title: "Zero-Config Mode" description: "Execute docmd without a configuration file. Ideal for rapid prototyping and instant documentation previews." --- `docmd` features an intelligent auto-detection engine that allows you to generate professional documentation for any project without writing a single line of configuration. This "Zero-Config" mode derives structure and metadata directly from your filesystem and project files. ## Usage To activate Zero-Config mode, simply append the `-z` or `--zero-config` flag to your command. ```bash # Start the development server instantly npx @docmd/core dev -z # Generate a production-ready static site npx @docmd/core build -z ``` ## How It Works When executing in Zero-Config mode, `docmd` performs the following automated steps: 1. **Directory Detection**: The engine scans your project root for common documentation folders, including: `docs/`, `src/docs/`, `documentation/`, and `content/`. If multiple candidates exist, it prioritises them in that order. 2. **Smart Indexing**: If no `index.md` or `README.md` is found at the root of the source directory, `docmd` automatically designates the first discovered Markdown file as the home page. 3. **Metadata Extraction**: If a `package.json` exists in your project, `docmd` extracts the `name` and `description` to automatically set the site title and branding. 4. **Automatic Routing**: The engine recursively scans all subdirectories and Markdown files to build a nested, collapsible navigation sidebar instantly. 5. **Optimised Defaults**: It applies the premium `default` theme with system-aware Light/Dark mode and enables core features like built-in search. ## Safety & Performance Zero-Config mode is engineered for speed and predictability: * **Scoped Execution**: By targeting specific directories, `docmd` avoids unnecessary indexing of unrelated project files, build artifacts, or large logs. * **Intelligent Exclusion**: The engine automatically ignores `node_modules`, hidden system folders (e.g., `.git`), and typical output directories (`dist/`, `build/`, `site/`). * **Bail-out Protection**: If no valid documentation directory or content is found, `docmd` will provide a clear warning and exit gracefully rather than hanging or generating empty files. ::: callout tip "AI-Friendly Architecture" Zero-Config mode is highly recommended for **AI-driven development**. Because the documentation structure is strictly derived from the filesystem, AI agents can easily predict file locations and update content without needing to manage complex configuration schemas. ::: --- ## [Documentation for docmd: The Minimalist Docs Generator](https://docs.docmd.io/06/) --- title: "Documentation for docmd: The Minimalist Docs Generator" description: "Generate beautiful, lightweight, and blazing-fast documentation sites directly from your Markdown files. Zero clutter, just content." --- ```text _ _ _| |___ ___ _____ _| | | . | . | _| | . | |___|___|___|_|_|_|___| ``` **Generate professional, high-performance documentation sites directly from Markdown. Zero clutter, just content.** `docmd` bridges the gap between simple static site generators and heavy, framework-driven documentation tools. It transforms standard Markdown into highly optimised static HTML while delivering a seamless Single Page Application (SPA) experience. ::: button "Get Started" /getting-started/installation ::: button "GitHub" external:https://github.com/docmd-io/docmd color:#333 ::: button "Explore Features" /getting-started/basic-usage color:#333 ## Quick Start **Requires [Node.js](https://nodejs.org/) (v18 or higher) installed.** Deploy a beautiful, searchable documentation site in seconds. No framework knowledge or complex setup required. **1. Install `docmd` as a development dependency** ```bash npm install -D @docmd/core # Recommended: Install locally npx @docmd/core init # Initialise your project configuration npx @docmd/core dev # Start the development server ``` **2. Global Installation (Optional)** ```bash npm install -g @docmd/core # Run docmd from anywhere on your system ``` **3. Instant Zero-Config Execution** ```bash # Start a dev server instantly without any local configuration npx @docmd/core dev -z ``` Once running, open `http://localhost:3000` in your browser. Changes to your files in the `docs/` folder will reflect instantly via Hot Module Replacement (HMR). ## Why choose docmd? Writing documentation should be frictionless. You shouldn't have to manage complex JavaScript frameworks or deep configuration trees just to publish technical text. `docmd` is built for **both humans and AI**, serving as the most LLM-friendly static site generator available. <div class="image-gallery" style="grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));"> ::: card "AI-Native Optimisation" `docmd` generates a structured context for LLMs (`llms.txt` and `llms-full.txt`), allowing AI models to ingest your entire project context perfectly in a single request. ::: ::: card "Zero Config & Auto-Routing" Executing `docmd dev -z` automatically scans for documentation directories, extracts headings as page titles, and builds a nested, collapsible navigation tree instantly. ::: ::: card "SPA Performance" We serve pre-rendered HTML for maximum SEO and initial load speed. Once loaded, `docmd` transitions between pages as a high-performance SPA, ensuring instant content swaps without full browser reloads. ::: ::: card "Smart Offline Search" Features built-in full-text search with fuzzy matching and deep linking. The search index runs entirely in-browser, making it fully functional in offline or air-gapped environments. ::: ::: card "Modern & Responsive" Designed for all devices. Includes premium themes with native Light/Dark appearance modes, sticky versioning, and mobile-optimised sidebars out of the box. ::: ::: card "Isomorphic Rendering" The same engine used for static builds can run natively in the browser. Embed live documentation previews or interactive editors directly into your own web applications. ::: </div> ## Rich Content Out of the Box `docmd` extends standard Markdown with intuitive components designed for professional documentation structures. ::: tabs == tab "Interactive Components" Highlight critical information with Callouts and native Buttons. ::: callout tip Performance Tip Nest containers inside each other to create complex layouts without touching HTML or CSS. ::: ::: button "Read about Containers" /content/containers/callouts == tab "Native Diagrams" Create professional architectural diagrams using **Mermaid.js** syntax directly in your Markdown files. ```mermaid graph LR MD[Markdown] --> Build[docmd Build] Build --> Static[Static HTML] Build --> LLM[llms-full.txt] ``` == tab "Code Precision" Automatic syntax highlighting via our custom `lite-hl` engine, including one-click copy buttons and multi-language support. ```javascript // docmd.config.js import { defineConfig } from '@docmd/core'; export default defineConfig({ title: 'My Project', layout: { spa: true } }); ``` ::: Ready to build? [Install docmd](./getting-started/installation.md) or see [Zero-Config Mode](./getting-started/zero-config.md) in action. --- ## [Analytics Plugin](https://docs.docmd.io/06/plugins/analytics/) --- title: "Analytics Plugin" description: "Integrate Google Analytics 4 or Legacy Universal Analytics and track user interactions automatically." --- The `@docmd/plugin-analytics` plugin allows you to easily integrate Google Analytics into your documentation. It supports the modern Google Analytics 4 (GA4) standard, legacy Universal Analytics (UA), and includes native event tracking for interaction-heavy documentation sites. ## Configuration Enable analytics by adding your tracking credentials to the `plugins` section of `docmd.config.js`. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { analytics: { // 1. Google Analytics 4 (Recommended) googleV4: { measurementId: 'G-XXXXXXX' }, // 2. Legacy Universal Analytics googleUA: { trackingId: 'UA-XXXXXXX-X' }, // 3. Behavioral Tracking Settings autoEvents: true, // Track clicks, downloads, and TOC interactions trackSearch: true // Track search keywords used by readers } } }); ``` ## Tracked Events When `autoEvents` is enabled, the plugin automatically captures the following user interactions and sends them to your analytics provider: * **External Links**: Track when users depart for external resources. * **File Downloads**: Automatically log clicks on links with the `download` attribute or common file extensions (`.pdf`, `.zip`, `.tar`, etc.). * **Table of Contents (TOC)**: Monitor which sections are most engaging by tracking clicks in the right-hand navigation. * **Heading Anchors**: Log when users click on "permalinks" (heading anchors) to share specific sections. * **Search Queries**: When `trackSearch` is active, keywords are captured (with a 1-second debounce) to help you understand what your users are looking for. ## Technical Details The plugin injects the necessary tracking scripts into the `<head>` of every page. Event listeners are attached to the `<body>` using efficient event delegation to ensure zero impact on page load performance or Single Page Application (SPA) transitions. ::: callout info "Privacy & GDPR" By default, this plugin does not anonymize IP addresses as that is now handled natively by GA4. If you require advanced cookie consent management, you can manually inject your consent manager scripts using the `customCss` or a custom plugin hook. ::: --- ## [Building Plugins](https://docs.docmd.io/06/plugins/building-plugins/) --- title: "Building Plugins" description: "A comprehensive guide to extending docmd with custom logic and interactive features." --- Plugins are the primary extension mechanism for `docmd`. They allow you to inject custom HTML, modify the Markdown parsing logic, and automate post-build tasks. This guide outlines the plugin API and best practices for creating shareable components. ## Plugin API Reference A `docmd` plugin is a standard JavaScript object (or a module that exports one as default) that implements one or more of the following asynchronous hooks. | Hook | Description | | :--- | :--- | | `markdownSetup(md, opts)` | Extend the `markdown-it` instance. Synchronous. | | `generateMetaTags(config, page, root)` | Inject `<meta>` or `<link>` tags into the `<head>`. | | `generateScripts(config, opts)` | Return an object containing `headScriptsHtml` and `bodyScriptsHtml`. | | `getAssets(opts)` | Define external files or CDN scripts to be injected. | | `onPostBuild(ctx)` | Run logic after the generation of all HTML files. | | `actions` | An object of named action handlers for WebSocket RPC calls from the browser. | | `events` | An object of named event handlers for fire-and-forget messages from the browser. | ## Creating a Local Plugin Creating a plugin is as simple as defining a JavaScript file. For example, `my-plugin.js`: ```javascript // my-plugin.js import path from 'path'; export default { // 1. Extend the Markdown Parser markdownSetup: (md, options) => { // Example: Add a rule or use a markdown-it plugin }, // 2. Inject Page Metadata generateMetaTags: async (config, page, relativePathToRoot) => { return `<meta name="x-build-id" content="${config._buildHash}">`; }, // 3. Post-Build Automation onPostBuild: async ({ config, pages, outputDir, log, options }) => { log(`Custom Plugin: Verified ${pages.length} pages.`); // Example: Generate a custom manifest or notification } }; ``` To enable your plugin, reference its **full package name** in your `docmd.config.js`: ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { 'my-awesome-plugin': { // Your custom options go here } } }); ``` > **Note:** Shorthand names (e.g. `math`, `search`) are reserved exclusively for official `@docmd/plugin-*` packages. Third-party plugins must always be referenced by their full npm package name. ### Plugin Resolution The `docmd` engine resolves plugin names as follows: - **Official shorthands** (`math`, `search`, `seo`, etc.) automatically expand to `@docmd/plugin-<name>`. Since the `@docmd` npm scope is owned by the project, only official packages can exist under it. - **Third-party plugins** must use their full package name (e.g. `my-awesome-plugin`, `@myorg/docmd-extras`). There is no alias or shorthand system for external plugins - this prevents confusion and eliminates supply-chain attack vectors entirely. ### Scoping Plugins (`noStyle`) By default, plugins inject their CSS/JS universally. However, developers can explicitly prevent their plugin from rendering on `noStyle` pages (like minimal landing templates) by exporting a `noStyle` boolean: ```javascript export default { noStyle: false, // Prevents generateMetaTags and generateScripts from running on noStyle pages generateScripts: () => { ... } } ``` Users can also override this behaviour through their configuration (`plugins: { math: { noStyle: false } }`) or dynamically via Markdown frontmatter (`plugins: { math: true }`). ## Deep Dive: Asset Injection The `getAssets()` hook allows your plugin to bundle client-side logic securely. ```javascript getAssets: (options) => { return [ { url: 'https://cdn.example.com/lib.js', // External CDN script type: 'js', location: 'head' }, { src: path.join(__dirname, 'plugin-init.js'), // Local source dest: 'assets/js/plugin-init.js', // Destination in build/ type: 'js', location: 'body' } ]; } ``` ## WebSocket RPC Actions Starting in `0.6.8`, plugins can register **action handlers** and **event handlers** that run on the dev server and are callable from the browser via the `window.docmd` API. ```javascript // my-live-plugin.js export default { // Server-side action - browser calls via docmd.call() actions: { 'my-plugin:save-note': async (payload, ctx) => { const content = await ctx.readFile(payload.file); const updated = content + '\n\n> ' + payload.note; await ctx.writeFile(payload.file, updated); return { saved: true }; } }, // Server-side event - browser sends via docmd.send() events: { 'my-plugin:page-viewed': (data, ctx) => { console.log(`Page viewed: ${data.path}`); } } }; ``` The `ctx` (ActionContext) object provides: | Method | Description | | :--- | :--- | | `ctx.readFile(path)` | Read a file relative to the project root. | | `ctx.writeFile(path, content)` | Write a file (triggers rebuild + reload). | | `ctx.readFileLines(path)` | Read a file as an array of lines. | | `ctx.broadcast(event, data)` | Push an event to all connected browsers. | | `ctx.source` | Source editing tools for block-level markdown manipulation. | | `ctx.projectRoot` | Absolute path to the project root. | | `ctx.config` | Current docmd site configuration. | All file operations are sandboxed to the project root - path traversal attempts are rejected automatically. ::: callout info "Dev Mode Only 🛡️" The WebSocket RPC system is only active during `docmd dev`. Production builds do not include the API client or any server-side action handling. ::: ## Best Practices 1. **Async/Await**: Always use `async` functions for `onPostBuild` and action handlers to prevent blocking the build engine during I/O operations. 2. **Statelessness**: Avoid maintaining state within the plugin object, as `docmd` may re-initialise plugins during development "Hot Reloads." 3. **Naming Convention**: For community plugins, prefix your package name with `docmd-plugin-` (e.g., `docmd-plugin-analytics`). 4. **Action Namespacing**: Prefix your action names with your plugin name (e.g., `my-plugin:save-note`) to avoid collisions. 5. **Logging**: Use the provided `log()` helper in `onPostBuild` to ensure your messages respect the user's `--verbose` settings. ::: callout tip "AI-Ready Design 🤖" The `docmd` plugin API is designed to be **LLM-Optimal**. Because the hooks use standard JavaScript objects and types without hidden complex class hierarchies, AI agents can generate bug-free custom plugins for you with minimal instruction. ::: --- ## [LLM Context Plugin](https://docs.docmd.io/06/plugins/llms/) --- title: "LLM Context Plugin" description: "Optimised your documentation for AI Consumption with automated llms.txt and llms-full.txt generation." --- The `@docmd/plugin-llms` plugin ensures your documentation is perfectly optimised for Large Language Models (LLMs) and AI Agents. It follows the growing industry standard of providing a high-level summary and a comprehensive context file that AI tools can ingest to understand your project with minimal hallucination. ## Configuration The LLM plugin is enabled by default. To function correctly, you must provide a `siteUrl` in your `docmd.config.js`. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ siteUrl: 'https://docs.example.com', plugins: { llms: {} // Enabled by default } ### Excluding a Page If a page contains sensitive information or internal notes you don't want AI models to learn: ```yaml --- title: "Internal Dev Secrets" llms: false --- ``` ::: callout tip By hosting an `llms-full.txt` file, you are essentially providing an **Open API for AI Models**. This makes your project the preferred choice for developers working with AI assistance, as they can reliably get accurate answers without your docs "hallucinating" or being outdated by the model's training cutoff. ::: --- ## [Math Plugin](https://docs.docmd.io/06/plugins/math/) --- title: "Math Plugin" description: "Native KaTeX/LaTeX mathematics integration for docmd." --- The **Math plugin** adds native LaTeX and KaTeX support to your docmd sites. It utilizes `markdown-it-texmath` as securely integrated with the `katex` computation engine to render both inline and block-level mathematical equations smoothly without requiring complex client-side javascript libraries. ## Setup ```bash docmd add math ``` ```javascript plugins: { math: {} } ``` ## How It Works 1. Enable the plugin via your `docmd.config.js`. 2. Wrap your standard LaTeX mathematics in `$` (inline) or `$$` (block) indicators. 3. The server intelligently processes these math rules during the static-site build exactly as raw static HTML tags. 4. Minimal injected CSS automatically scopes these classes directly, yielding immediate visualization the moment the user views the page! ## Usage ### Inline Mathematics You can inject standard equations flawlessly within a paragraph utilizing single dollar signs `$`: ```markdown Here is an inline equation: $E = mc^2$ ``` Here is an inline equation: $E = mc^2$ ### Block Mathematics For wider mathematical proofs or distinct formulations, use double dollar signs `$$` for block level formatting: ```markdown $$ \sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$ ``` $$ \sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$ --- ## [Mermaid Diagrams](https://docs.docmd.io/06/plugins/mermaid/) --- title: "Mermaid Diagrams" description: "Create professional architectural diagrams, flowcharts, and sequence diagrams directly in your Markdown files using Mermaid.js syntax." --- The `@docmd/plugin-mermaid` plugin integrates the powerful [Mermaid.js](https://mermaid.js.org/) engine into your documentation pipeline. It allows you to transform plain-text descriptions into high-fidelity, interactive diagrams without ever leaving your Markdown environment. ## Key Features - **Zero Scripting**: No need to manually include external scripts or CDN links. `docmd` detects the usage and injects the rendering engine only where needed. - **Theme Awareness**: Diagrams automatically adapt their colour schemes to match your site's **Light** or **Dark** mode transitions. - **Isomorphic Lazy Loading**: For optimum performance, diagrams are initialised and rendered only as they enter the user's viewport. - **Technical Readability**: Diagrams remain pure text in your source, making them easily version-controlled and readable by AI agents. ## Configuration To enable diagram support, add the `mermaid` plugin to your `docmd.config.js`: ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { mermaid: {} // Enabled with zero-config } }); ``` ## Implementation Gallery To render a diagram, place your Mermaid syntax within a fenced code block with the `mermaid` language identifier. ### 1. Sequence Diagrams Ideal for illustrating interactions between multiple system components. ::: tabs == tab "Preview" ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Enters URL Browser->>Server: HTTP Request Server-->>Browser: HTTP Response Browser-->>User: Displays Page ``` == tab "Markdown Source" ````markdown ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Enters URL Browser->>Server: HTTP Request Server-->>Browser: HTTP Response Browser-->>User: Displays Page ``` ```` ::: ### 2. Analytical Charts Visualize data using built-in chart types like Pie Charts or Bar Charts. ::: tabs == tab "Preview" ```mermaid pie title Project Composition "Documentation" : 45 "Core Engine" : 30 "Plugins" : 15 "UI Components" : 10 ``` == tab "Markdown Source" ````markdown ```mermaid pie title Project Composition "Documentation" : 45 "Core Engine" : 30 "Plugins" : 15 "UI Components" : 10 ``` ```` ::: ### 3. Git Workflows Visualize branching and merging strategies for your developer guides. ::: tabs == tab "Preview" ```mermaid gitGraph commit branch develop checkout develop commit commit checkout main merge develop commit ``` == tab "Markdown Source" ````markdown ```mermaid gitGraph commit branch develop checkout develop commit commit checkout main merge develop commit ``` ```` ::: ## Technical Implementation The Mermaid plugin operates by intercepting `mermaid` code blocks during the parsing phase and wrapping them in a specialized `<div class="mermaid">` container. 1. **Detection**: The engine scans the rendered HTML for the presence of mermaid containers. 2. **Asset Injection**: If containers are found, `docmd` injects a lightweight `init-mermaid.js` module. 3. **Rendering**: The Mermaid library is fetched asynchronously and renders the diagrams client-side, ensuring that your initial HTML payload remains small and fast. ::: callout tip "Diagrams for AI Agents" While diagrams are visually helpful for humans, they are technically transparent to AI. Because the source is pure text, models like GPT-4 or Claude can "see" your system architecture or logic flows through the `llms-full.txt` stream. This allows the AI to explain complex architectural relationships based on your diagrams. ::: --- ## [PWA & Offline Support](https://docs.docmd.io/06/plugins/pwa/) --- title: "PWA & Offline Support" description: "Transform your documentation into a progressive web application with offline caching and mobile-first features." --- The `@docmd/plugin-pwa` plugin enables Progressive Web App (PWA) features for your documentation site. It adds a web manifest for mobile installation and registers a service worker to handle intelligent offline caching, ensuring your technical manuals remain accessible even in low-connectivity environments. ## Configuration The PWA plugin can be customised to match your branding within the `plugins` section of `docmd.config.js`. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { pwa: { enabled: true, // Enabled by default if the plugin is loaded themeColor: '#1e293b', // The primary colour of the mobile UI bgColor: '#ffffff', // Background colour for the splash screen logo: '/assets/logo.png' // Fallback for app icons if not explicitly defined } } }); ``` ## Core Features ### 1. Offline Caching The plugin automatically generates a `service-worker.js` file that implements a "Stale-While-Revalidate" caching strategy. When a user visits a page, the service worker: * Returns the cached version instantly for maximum speed. * Fetches the latest version from the network in the background. * Updates the cache for the next visit. ### 2. Mobile Installation By generating a `manifest.webmanifest` and injecting the required `<meta>` tags, the plugin allows users to "Add to Home Screen" on iOS and Android. Your documentation will behave like a standalone application, with its own splash screen and window frame. ### 3. Smart Asset Resolution The plugin attempts to generate app icons automatically by looking for your project's `logo` or `favicon`. For more control, you can provide an explicit `icons` array: ```javascript pwa: { icons: [ { src: '/icons/icon-192x192.png', sizes: '192x192', type: 'image/png' }, { src: '/icons/icon-512x512.png', sizes: '512x512', type: 'image/png' } ] } ``` ## Technical Implementation The service worker is designed to be compatible with Single Page Application (SPA) routing. It includes specific fail-safe logic for Safari's strict security policies regarding redirected streams, ensuring stability across all modern browsers. ::: callout tip "Dev Mode" Service workers are typically disabled or bypassed in local development (`docmd dev`) to prevent aggressive caching from interfering with your edits. To test the PWA functionality, perform a production build with `docmd build` and serve the output directory using a static host. ::: ### Fully Remove Simply delete the `pwa` block from your `plugins`. The next time you run `docmd build`, a new manifest is not generated. When users visit the site, docmd's client-side bootstrap (`docmd-main.js`) checks for the presence of `<link rel="manifest">`. If it's missing but a Service Worker is registered, it automatically **unregisters all existing ghost workers** and clears the cached shell - requiring no user action. ::: callout warning The `manifest.webmanifest` and `service-worker.js` files from a previous build persist on disk until you clear your output directory (`site/` by default) with `docmd build` or `rm -rf site`. This is a filesystem artifact, not an active PWA. ::: ## Configuration Reference All fields are optional. The defaults are designed for zero-config use. ```javascript export default { plugins: { pwa: { // --- Icon Configuration --- // Priority: pwa.logo > config.logo > config.favicon > (no icons) logo: 'assets/images/app-icon.png', // Path relative to your src folder // Or for full manual control: icons: [ { src: '/assets/images/icon-192.png', sizes: '192x192', type: 'image/png' }, { src: '/assets/images/icon-512.png', sizes: '512x512', type: 'image/png' } ], // --- Manifest Colours --- themeColor: '#1e293b', // Browser chrome / top bar accent bgColor: '#ffffff', // Splash screen background during install // --- Disable the plugin entirely --- enabled: false } } } ``` ### Icon Resolution Priority docmd resolves your PWA icon from the following cascade: 1. `pwa.icons` - Manual array, used as-is 2. `pwa.logo` - Single image path, used for both 192x192 and 512x512 entries 3. `config.logo` - Your global site logo 4. `config.favicon` - Your global favicon 5. *(No icons declared in manifest)* - If none of the above are set ## Testing Locally Browsers restrict Service Workers to `https://` or `localhost`. Use: ```bash docmd dev ``` Open Chrome DevTools → **Application** → **Manifest** and **Service Workers** to view the activated registration in real-time. Safari → **Develop** → **Service Workers** panel works equally well. --- ## [Search Plugin](https://docs.docmd.io/06/plugins/search/) --- title: "Search Plugin" description: "Enable high-speed, offline-first full-text search for your documentation using MiniSearch." --- The `@docmd/plugin-search` plugin provides a powerful, client-side search experience for your documentation. It uses [MiniSearch](https://github.com/lucaong/minisearch) to build a lightweight index during the build process, allowing users to find technical information instantly without a server-side database. ## Configuration Search is enabled by default in most `docmd` templates. You can control its visibility and placement via the `layout` configuration. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ layout: { optionsMenu: { position: 'header', // 'header', 'sidebar-top', 'sidebar-bottom', or 'menubar' components: { search: true // Set to false to disable the search plugin entirely } } } }); ``` ## How It Works ### 1. Indexing (Build-time) During the `docmd build` process, the search plugin iterates through every page on your site. It extracts the title, headings, and plain-text prose, then compiles this data into a compressed `search-index.json` file. * **Deep Linking**: The indexer automatically registers every heading (`#`, `##`, etc.) as a searchable target. * **Relevancy Boosting**: Titles are given the highest weight, followed by headings, then page content. ### 2. Retrieval (Client-side) When a user opens the search modal (usually via `/` or `Ctrl+K`), the `search-index.json` is fetched by the browser. Searches are performed locally using fuzzy matching (allowing for small typos) and instant prefix matching. ## Customising Search Behaviour While the search plugin is designed for zero-config simplicity, you can exclude specific pages from the index by using the `noindex` flag in their frontmatter: ```yaml --- title: "Internal Specification" noindex: true # This page will not appear in search results or sitemaps --- ``` ## Technical Implementation The plugin injects a minimalist search modal into the `<body>` of your site. It is designed to be fully accessible (ARIA compliant) and supports keyboard navigation for a native app-like experience. ::: callout tip "Search Analytics" If you have the [Analytics Plugin](./analytics) enabled, search keywords used by your readers are automatically captured and sent to your analytics provider, giving you insights into what information is missing or hardest to find. ::: Because the search happens entirely on the client, no data - not even keystrokes - is ever sent to a server. This makes `docmd` the Gold Standard for documentation search in privacy-sensitive industries (Healthcare, Finance, Security). ## Comparison Many documentation generators (like Docusaurus) rely on **Algolia DocSearch**. While Algolia is powerful, it introduces friction: | Feature | docmd Search | Algolia / External | | :--- | :--- | :--- | | **Setup** | **Zero Config** (Automatic) | Complex (API Keys, CI/CD crawling) | | **Privacy** | **100% Private** (Client-side) | Data sent to 3rd party servers | | **Offline** | **Yes** | No | | **Cost** | **Free** | Free tier limits or Paid | | **Speed** | **Instant** (In-memory) | Fast (Network latency dependent) | --- ## [SEO Plugin](https://docs.docmd.io/06/plugins/seo/) --- title: "SEO Plugin" description: "Optimise your documentation for search engines and control AI crawler access with native meta tag generation." --- The `@docmd/plugin-seo` plugin is responsible for generating high-quality metadata for every page. It ensures your documentation is not only discoverable by human readers on search engines but also correctly interpreted by AI models and social media platforms. ## Global Configuration Configure site-wide SEO defaults in your `docmd.config.js`. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { seo: { defaultDescription: 'Comprehensive documentation for the docmd ecosystem.', aiBots: false, // Set to false to block common AI crawlers (GPTBot, etc.) openGraph: { defaultImage: '/assets/og-image.png' }, twitter: { siteUsername: '@docmd_io', cardType: 'summary_large_image' } } } }); ``` ## Page-Level Overrides You can fine-tune SEO settings for individual pages using frontmatter. Page-level settings always take precedence over global defaults. ```yaml --- title: "Advanced Configuration" description: "Learn how to master docmd's internal engine." noindex: true # Hide this specific page from all search engines seo: keywords: ["docmd", "javascript", "ssg"] ogType: "article" canonicalUrl: "https://mysite.com/canonical-path" aiBots: true # Override global block to allow AI access to this page --- ``` ## Core Features ### 1. Smart Description Fallback If a description is not provided in the frontmatter or global config, the plugin automatically extracts the first 150 characters of the page's prose to use as the `<meta name="description">`, ensuring every page has basic metadata for search snippets. ### 2. AI Bot Governance By setting `aiBots: false`, the plugin injects `noindex` instructions specifically for major AI crawlers (including `GPTBot`, `Claude-Web`, and `Google-Extended`). This allows you to differentiate between traditional search engine indexing and LLM training sessions. ### 3. Canonical Resolution The plugin automatically generates `<link rel="canonical">` tags based on your `siteUrl`. It intelligently handles directory indexes, converting `guide/index.html` to a clean `/guide/` canonical URL to prevent duplicate content issues. ### 4. Rich Social Previews Native support for Open Graph and Twitter Cards ensures that links to your documentation look professional when shared on platforms like X (Twitter), LinkedIn, and Discord. ::: callout tip "Search Discovery" For the best SEO results, ensure your `siteUrl` is defined in the root of your configuration. Without a base URL, the plugin cannot generate absolute canonical links or Open Graph image paths. ::: ## Structured Data (LD+JSON) `docmd` can automatically generate [Article Schema](https://developers.google.com/search/docs/appearance/structured-data/article) to help Search Engines display rich snippets. ```yaml --- title: "How to Build a docmd Plugin" seo: ldJson: true --- ``` ::: callout tip "Structured Data" A well-configured SEO plugin helps AI-powered search engines (like SearchGPT or Perplexity) summarize your site accurately. By providing clear descriptions and blocked bots, you control exactly how AI models perceive and source your content online. ::: --- ## [Sitemap Plugin](https://docs.docmd.io/06/plugins/sitemap/) --- title: "Sitemap Plugin" description: "Automatically generate a standard-compliant sitemap.xml for better search engine discovery." --- The `@docmd/plugin-sitemap` plugin automatically generates a `sitemap.xml` file at the root of your build directory. This file provides search engines like Google and Bing with a comprehensive map of your site's architecture, ensuring that all pages - including deep links within versioned documentation - are crawled and indexed. ## Configuration Enable sitemap generation by providing your `siteUrl` in the root configuration. You can customise the crawl weight of various sections within the `plugins` object. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ siteUrl: 'https://docs.example.com', // Required for sitemap generation plugins: { sitemap: { defaultChangefreq: 'weekly', // 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never' defaultPriority: 0.8, // Default weight for standard pages rootPriority: 1.0 // Weight for the homepage (index.md) } } }); ``` ## Page-Level Controls You can override sitemap behaviour for specific pages using frontmatter. ```yaml --- title: "Archive Page" priority: 0.3 # Lower weight for legacy content changefreq: "monthly" # Hint to crawlers that this page rarely changes lastmod: "2024-03-15" # Explicitly set the last modification date sitemap: false # Exclude this specific page from the sitemap.xml --- ``` ## Core Features ### 1. Automatic URL Construction The plugin intelligently resolves page paths to their canonical public URLs. It handles directory indexes automatically, ensuring that `guide/index.html` is listed as `https://yoursite.com/guide/` to maintain clean URL structures. ### 2. Versioned Discovery If your project uses [Versioning](../configuration/versioning), the sitemap plugin automatically includes all pages from all versions (e.g., `/v1/getting-started`, `/v2/getting-started`), allowing search engines to discover your archived documentation without manual configuration. ### 3. Smart Exclusions Pages marked with `noindex: true` or `sitemap: false` in their frontmatter are automatically excluded from the generated `sitemap.xml`, giving you granular control over what is presented to search engines. ::: callout tip "Validation" After building your site, you can typically find the sitemap at `your-output-dir/sitemap.xml`. Most search engine consoles allow you to submit this file directly to accelerate indexing. ::: --- ## [Threads Plugin](https://docs.docmd.io/06/plugins/threads/) --- title: "Threads Plugin" description: "Add inline discussion threads to your documentation - stored directly in your markdown files." --- The **Threads plugin** brings collaborative inline comments to your documentation. Select any text on the page, leave a comment, start a discussion - all stored directly in your markdown source files with zero database needed. Original Author: [@svallory](https://github.com/svallory) ::: callout info "Alpha Release" This plugin is in alpha. The API and storage format are stable, but the UI is under active development. ::: ## Setup ```bash docmd add threads ``` ```javascript plugins: { threads: {} } ``` ### Configuration Options | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `sidebar` | `boolean` | `false` | When `true`, threads stay grouped at the bottom of the page. When `false` (default), threads are positioned inline next to their highlighted text. | ```javascript // Keep threads at bottom of page instead of inline plugins: { threads: { sidebar: true } } ``` ## How It Works 1. **Select text** on any documentation page during `docmd dev` 2. A **comment popover** appears - write your comment and submit 3. The selected text gets **highlighted** with a thread marker 4. Threads are stored as `::: threads` blocks at the bottom of the markdown file 5. **No database** - your markdown files are the source of truth ## Preview Here's what threads look like on a live page. Text with discussions gets <span class="threads-preview-highlight">highlighted like this</span> and thread cards appear below. <div class="threads-preview-card"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 2d ago</div> <div class="threads-preview-body">This section could use a diagram to explain the architecture. What do you think?</div> </div> <div class="threads-preview-comment threads-preview-reply"> <div class="threads-preview-avatar">B</div> <div class="threads-preview-meta"><strong>Bob</strong> · 1d ago</div> <div class="threads-preview-body">Good idea - I'll add a Mermaid flowchart. Does <code>sequenceDiagram</code> work here?</div> <div class="threads-preview-reactions"> <div class="threads-preview-reaction">👍 <span>2</span></div> <div class="threads-preview-reaction">🚀 <span>1</span></div> </div> </div> <div class="threads-preview-comment threads-preview-reply"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 12h ago</div> <div class="threads-preview-body">Perfect. A simple flowchart would be ideal.</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> And here's a <span class="threads-preview-highlight-blue">second highlight with a different colour</span> - threads cycle through a palette of colours automatically. <div class="threads-preview-card threads-preview-card-blue"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">C</div> <div class="threads-preview-meta"><strong>Charlie</strong> · 3d ago</div> <div class="threads-preview-body">Should we mention backward compatibility here?</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> Resolved threads appear dimmed: <div class="threads-preview-card threads-preview-card-resolved"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 5d ago  <span class="threads-preview-resolved-badge">✓ Resolved</span></div> <div class="threads-preview-body">Fixed the typo in the config example.</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> A floating **discussion button** <span class="threads-preview-fab">💬<span class="threads-preview-fab-badge">2</span></span> appears in the bottom-right corner showing the count of open threads. Click it to jump to the first thread on the page. ## Storage Format Threads are embedded in your markdown using docmd's container syntax: ```markdown # My Documentation Page Some content with ==highlighted text=={t-a1b2c3d4} that has a thread. ::: threads ::: thread t-a1b2c3d4 ::: comment c-e5f6a7b8 "Alice" "2026-04-09" This text needs clarification. ::: ::: comment c-d9e0f1a2 "Bob" "2026-04-09" reply-to c-e5f6a7b8 Updated it - does this work? ::: reactions - 👍 Alice ::: ::: ::: ::: ``` The `==text=={threadId}` syntax links highlighted text in the document body to a specific thread. ## Features | Feature | Description | | :--- | :--- | | **Text Selection** | Select any text to start a new thread | | **Replies** | Nested reply chains within each thread | | **Reactions** | Emoji reactions on individual comments | | **Edit / Delete** | Modify or remove your comments | | **Resolve** | Mark threads as resolved with author + timestamp | | **Author Profiles** | Git-based author detection with Gravatar support | | **Highlight Markers** | Visual indicators on the page showing where threads are anchored | | **Floating Button** | Quick-access FAB with open thread count | | **Scroll Preservation** | Page stays in place after adding comments | ## Actions API The threads plugin exposes the following actions via the WebSocket RPC system. These can be called from browser plugins using `docmd.call()`: | Action | Description | | :--- | :--- | | `threads:get-threads` | Parse and return all threads from a file | | `threads:add-thread` | Create a new thread with its first comment | | `threads:add-comment` | Add a comment to an existing thread | | `threads:edit-comment` | Edit an existing comment's body | | `threads:delete-comment` | Remove a comment from a thread | | `threads:delete-thread` | Remove an entire thread and cleanup highlights | | `threads:resolve-thread` | Toggle resolved/unresolved status | | `threads:toggle-reaction` | Toggle an emoji reaction on a comment | | `threads:get-authors` | Read the author profile map | | `threads:upsert-author` | Create or update an author profile | ## Author Profiles Author information is stored in `<docsRoot>/.threads/authors.json`: ```json { "alice@example.com": { "name": "Alice", "avatarUrl": "https://gravatar.com/avatar/..." } } ``` During development, the plugin automatically detects your git username and email for author identification. ::: callout tip "Version Control Friendly" Since threads are stored in your markdown files, they are automatically version-controlled with git. Review comments in PRs, track discussion history, and collaborate through your existing workflow. ::: --- ## [Using Plugins](https://docs.docmd.io/06/plugins/usage/) --- title: "Using Plugins" description: "Install, configure, and manage docmd plugins - from required defaults to optional add-ons." --- `docmd` features a modular plugin architecture. Required plugins ship with the core and need no installation. Optional plugins can be installed with a single CLI command. ## Installing Plugins Use the `docmd` CLI to install and remove plugins: ```bash # Install a plugin docmd add <plugin-name> # Remove a plugin docmd remove <plugin-name> ``` The installer automatically detects your package manager (npm, pnpm, yarn, or bun), resolves short names to full package names, and injects the plugin config into your `docmd.config.js`. Use `--verbose` for full installer output: ```bash docmd add <plugin-name> --verbose ``` ## Required Plugins These plugins are bundled with `@docmd/core` - no installation needed. Enable them in your `docmd.config.js`: ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { search: {}, // Offline full-text search seo: { aiBots: false }, // Meta tags, Open Graph, AI bot controls sitemap: {}, // Automatic sitemap.xml generation analytics: {}, // Google Analytics v4 pwa: { themeColor: '#0097ff' }, // Progressive Web App support llms: {}, // LLM context generation (llms.txt) mermaid: {} // Native interactive diagrams } }); ``` ## Optional Plugins Optional plugins require installation before enabling. | Plugin | Install Command | Description | | :--- | :--- | :--- | | [Threads](threads.md) | `docmd add threads` | Inline discussion comments stored in your markdown | | [Math](math.md) | `docmd add math` | Native KaTeX and LaTeX mathematics integration | ## Plugin Scopes and `noStyle` Overrides Plugins inject CSS and behaviour by default globally across all pages. However, you can explicitly configure them to bypass specific pages or entirely disable their execution on unstyled landing templates (`noStyle: true`). ### Global Config Extent You can instruct any plugin to automatically skip injecting into `noStyle` pages via your `docmd.config.js`: ```javascript plugins: { math: { noStyle: false // math css/js will no longer load on minimalistic landing pages } } ``` ### Page Local Scope (Frontmatter) Regardless of your global config (or what the plugin developer set by default), you can definitively enable or disable any plugin uniquely per-document via markdown frontmatter. ```markdown --- noStyle: true plugins: math: true threads: false --- # Only Math renders here, Threads are completely blocked ``` ## Plugin Lifecycle Plugins hook into different stages of the build and development process: | Hook | Description | | :--- | :--- | | `markdownSetup(md, opts)` | Extend the Markdown parser with custom rules or containers | | `generateMetaTags(config, page, root)` | Inject `<meta>` and `<link>` tags into the `<head>` | | `generateScripts(config, opts)` | Inject scripts into `<head>` or `</body>` | | `getAssets(opts)` | Define external files or CDN scripts to inject | | `onPostBuild(ctx)` | Run logic after all HTML files are generated | | `actions` | Server-side handlers callable from the browser via WebSocket RPC | | `events` | Fire-and-forget handlers for browser-pushed events | ::: callout tip "AI-Transparent Architecture 🤖" The plugin architecture is designed to be **deterministic**. Every meta-tag and script injected by a plugin is traceable, allowing AI agents (and human developers) to understand exactly how the site behaves without hidden side effects. ::: --- ## [Recipe: Optimising for AI Agents](https://docs.docmd.io/06/recipes/ai-optimisation/) --- title: "Recipe: Optimising for AI Agents" description: "Engineer your documentation for maximum ingestibility by LLMs and AI Agents." --- `docmd` is architected as an "AI-First" documentation engine. By adhering to these structural best practices, you ensure that LLMs (such as ChatGPT, Claude, and GitHub Copilot) can parse your project's logic and architecture with surgical precision. ## 1. Enable the LLM Plugin The baseline for AI optimisation is the native `llms` plugin. It generates structured context files specifically designed for model ingestion. ```javascript // docmd.config.js export default { plugins: { llms: { fullContext: true // Generates the comprehensive llms-full.txt } } } ``` ## 2. Semantic Heading Integrity AI models utilize H-tags to build a hierarchical map of internal technical relationships. * **Logical Descent**: Never skip heading levels (always go H1 → H2 → H3). * **Technical Density**: Use descriptive headings. Instead of "Auth," use "Implementing OAuth2 Password Grants." * **The H1 Singular**: Ensure your Markdown frontmatter `title` is descriptive; `docmd` utilizes this as the primary semantic entry point. ## 3. Lexical Code Metadata Always explicitly specify the language identifier for fenced code blocks. This allows the AI's internal tokenizer to apply the correct grammar rules during context retrieval. ````markdown ```typescript // Optimised entry point const docmd = new Engine(); ``` ```` ## 4. Using the Context Pipeline The `llms-full.txt` file is a high-fidelity, concatenated stream of your entire static site. * **Prompt Engineering**: Direct your AI: *"Use the semantic structure in /llms.txt and the comprehensive technical content in /llms-full.txt to analyse this codebase."* * **Context Control**: Use `llms: false` in specific page frontmatter to exclude sensitive or internal-only documentation from the public AI context stream. ## 5. High-Fidelity Alt-Text While vision-capable models (Multimodal LLMs) are advancing, descriptive text remains the most reliable signal for reasoning engines. Comprehensive `alt` text for diagrams and screenshots ensures that the agent understands the visual logic even during text-only processing phases. --- ## [Recipe: Integrating Custom Fonts](https://docs.docmd.io/06/recipes/custom-fonts/) --- title: "Recipe: Integrating Custom Fonts" description: "Personalize your site's typography via Google Fonts and CSS variable overrides." --- `docmd` utilizes a reliable CSS variable system to manage design tokens. Personalizing your site's typography involves importing external font assets and overriding the core root variables. ## 1. Define Your Typography Manifest Establish a custom CSS file within your project (e.g., `assets/css/typography.css`). Identify your target font family on [Google Fonts](https://fonts.google.com) and utilize the `@import` directive to fetch the assets. Then, map these fonts to the `docmd` Typography tokens. ```css /* assets/css/typography.css */ /* 1. Import font assets */ @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;700&family=JetBrains+Mono&display=swap'); :root { /* 2. Override the primary Sans-Serif stack */ --font-family-sans: "Outfit", -apple-system, system-ui, sans-serif; /* 3. Override the Monospace (Code Block) stack */ --font-family-mono: "JetBrains Mono", monospace; } ``` ## 2. Register the Stylesheet Inject your custom manifest into the build pipeline via the `docmd.config.js` file. ```javascript export default { // ... theme: { name: 'sky', appearance: 'dark', customCss: [ '/assets/css/typography.css' // Path is absolute relative to the site/ directory ] } } ``` ## 3. Verify Changes Execute `docmd dev` to preview the typographical changes. The engine will automatically bundle the custom CSS and apply the variable overrides across all documentation nodes. --- ## [Recipe: Implementing Custom Favicons](https://docs.docmd.io/06/recipes/favicon/) --- title: "Recipe: Implementing Custom Favicons" description: "Establish project-wide branding by adding a custom favicon to your build." --- The favicon is a critical branding element rendered within the browser tab. `docmd` provides a centralized configuration key to automate the injection and resolution of these assets. ## 1. Format Preparation While `docmd` supports `.png` and `.svg` sources, utilize an `.ico` bundle for maximum legacy browser compatibility. Ensure your asset is at least 32x32px. ## 2. Asset Staging Place your processed image within the `assets/` directory of your project source. ```bash # Recommended Directory Mapping my-project/ ├── assets/ │ └── brand-favicon.ico <-- Source asset ├── docs/ └── docmd.config.js ``` ## 3. Configuration Binding Define the `favicon` property within your `docmd.config.js`. The path should reflect the location relative to the final `site/` output root. ```javascript export default { // ... // Maps to site/assets/brand-favicon.ico favicon: '/assets/brand-favicon.ico', // ... }; ``` ## 4. Final Build & Verification Execute `docmd build`. The engine will automatically: 1. Copy the asset to the production build directory. 2. Inject high-priority `<link rel="icon">` tags into the `<head>` of every generated HTML page. --- ## [Recipe: Designing Custom Landing Pages](https://docs.docmd.io/06/recipes/landing-page/) --- title: "Recipe: Designing Custom Landing Pages" description: "Master the noStyle mode to create high-impact marketing pages and product entries." --- While `docmd` excels at structured technical documentation, you can easily bypass the default UI logic to create bespoke landing pages, product showcases, or marketing splash screens using **No-Style Pages**. ## The Architectural Concept By activating `noStyle: true` in a page's frontmatter, the engine strips away the standard Sidebar, Header, and default CSS framework. This provides a "Blank Canvas" while maintaining access to the documentation engine's SEO meta tags and Markdown parsing capabilities. ## Implementation Workflow Create or refine your project's root entry point at `docs/index.md`. ```html --- title: "Next-Gen Documentation" description: "The minimalist, isomorphic, AI-ready engine for modern developers." noStyle: true components: meta: true # Retain structured SEO and OpenGraph tags favicon: true # Retain project branding scripts: false # Opt-out of the default SPA router for this page customHead: | <style> body { font-family: 'Inter', sans-serif; margin: 0; background: #000; color: #fff; } .hero { height: 80vh; display: flex; flex-direction: column; align-items: centre; justify-content: centre; } .btn { background: #3b82f6; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; } </style> --- <div class="hero"> <h1>Architecture Meets Documentation.</h1> <p>Isomorphic execution. AI-optimised context. Zero-reload navigation.</p> <br> <a href="/getting-started/" class="btn">Launch Documentation →</a> </div> <div class="feature-grid"> <!-- Inject custom landing page HTML or specialized Markdown Cards here --> </div> ``` ## Technical Outcomes When the project is compiled via `docmd build`, the root `index.html` will render as a bespoke landing page. This page serves as a high-fidelity entry point that easily directs users into the standardised documentation environment. --- ## [Recipe: Technical Writing Standards](https://docs.docmd.io/06/recipes/writing-guide/) --- title: "Recipe: Technical Writing Standards" description: "Best practices for authoring clear, scannable, and AI-optimised documentation." --- High-quality documentation is defined by its architectural clarity and scannability. This guide outlines the professional standards for utilizing `docmd` features to optimise the user and machine experience. ## Scannability & Semantic Density Technical users rarely read documentation linearly; they scan for specific solutions. * **Descriptive Semantic Headings**: Avoid generic titles. Use "Initialising the Production Pipeline" instead of "Startup." * **Concise Paragraphs**: Encapsulate single concepts into 2-3 sentence blocks to prevent cognitive overload. * **Lexical Emphasis**: Utilize **Bold Text** for key technical terms, file paths, and terminal commands to ensure they remain distinct during rapid scanning. ## Strategy for Interactive Containers `docmd` provides specialized UI blocks. Use them intentionally to reinforce your document's mental model. ### Callouts vs. Cards * **Callouts (Alerts)**: Use for "Out-of-band" information. `tip` for performance shortcuts, `warning` for cautionary logic, and `danger` for critical breaking changes. * **Cards (Structural Blocks)**: Use for "In-band" content clustering. Cards are ideal for feature summaries on a landing page or grouping related configuration keys. ### Sequential Workflows When documenting a multi-step procedure, always utilize the `::: steps` container. This provides a high-impact visual timeline that is significantly more legible than a standard numbered list for both humans and AI agents. ## High-Fidelity Linking `docmd`’s SPA router enables instant, zero-reload navigation. Maintain this experience through reliable referencing: * **Filesystem-Aware Paths**: Always utilize relative paths to your source `.md` files (e.g., `../core/engine.md`). This ensures link integrity across IDEs, local dev servers, and production builds. * **Descriptive Anchors**: Avoid "Read more." Utilize high-fidelity descriptors like "[Analyse the Browser API Reference](/api/browser-api)." ## Code Block Professionalism * **Explicit Language Labeling**: Always specify the language identifier (e.g., ` ```typescript `). This enables both accurate syntax highlighting and reliable AI parsing. * **Automated Portability**: `docmd` automatically attaches interactive copy buttons to every code block; prioritise concise, ready-to-execute snippets to maximise developer utility. --- ## [Release notes for docmd 0.6.0 release](https://docs.docmd.io/06/release-notes/0-6-0/) --- title: "Release notes for docmd 0.6.0 release" description: "Monorepo TypeScript & ESM migration, docmd Dev Environment Tools suite, and CI/CD automation." --- This landmark release marks a complete architectural overhaul of the `docmd` monorepo, transitioning the entire engine to TypeScript and ESM while launching a premium suite of automated developer tools. ## ✨ Highlights ### 🛡️ The docmd Dev Environment Tools We've transformed the contributor workflow into a professional, automated experience. No more manual `npm install` blocks or confusing build sequences. * **`pnpm onboard`**: A single command to set up a fresh fork. It silently handles dependency installation and monorepo builds. Use `--link-docmd` to instantly add `docmd` to your system path. * **`pnpm verify`**: Our new production-grade verification suite. It runs a branded E2E failsafe process, ensuring every parser rule, theme asset, and plugin lifecycle is 100% sound before release. * **`pnpm reset`**: A total environmental purge. Safely stops background servers, unlinks global binaries, and wipes all build caches for a truly fresh start. ### 🏗️ TypeScript & ESM Native The core engine has "grown up." We've migrated the entire monorepo from JavaScript (CJS) to TypeScript (ESM) to ensure long-term stability and developer agility. * **Type-Safe Core**: Internal APIs (Parser, Builder, Plugin System) now feature full type definitions, making contributions safer and eliminating "undefined" runtime errors. * **Modern Modules (ESM)**: Dropped legacy CommonJS in favour of native ECMAScript Modules, resulting in faster execution and better compatibility with the modern JS ecosystem. * **Plugin Ecosystem Upgrade**: We didn't stop at the core! All official plugins (`plugin-mermaid`, `plugin-pwa`, `plugin-search`, `plugin-seo`, `plugin-sitemap`, `plugin-analytics`, `plugin-installer`, `plugin-llms`) have been rewritten in fully typed ESM. Frontend assets are now independently bundled with `esbuild`. * **Version-Specific Navigation**: You can now override the global `navigation` for specific versions, allowing you to tailor the sidebar for legacy documentation versions. ## 📝 Complete Changelog ### 🤖 CI/CD Guardrails * **Automated Verification**: Introduced GitHub Actions that automatically run `pnpm verify` on every **Push** and **Pull Request** to the `main` branch. * **Release Automation**: Modernized the NPM publish workflow to use the new branded verification suite as a final release gatekeeper. ### 🐛 Refinements & Fixes * **Branded CLI**: All developer commands now feature the blue `docmd` branding and consistent dimmed status feedback. * **Playground Bridges**: Added `playground:add` and `playground:remove` workspace aliases to allow testing CLI features safely inside an isolated playground context. * **Optimised Failsafe**: The verification suite now automatically handles monorepo builds and supports a `--skip-setup` flag for lightning-fast CI execution. --- ## [Release notes for docmd 0.6.1 release](https://docs.docmd.io/06/release-notes/0-6-1/) --- title: "Release notes for docmd 0.6.1 release" description: "Hotfix release resolving NPM publishing failures and an installer runtime error." --- This is a hotfix release addressing pipeline publication issues and a critical runtime error in the plugin installer introduced in `0.6.0`. ## 🐛 Bug Fixes ### 🚀 CI/CD NPM Publisher * **Monorepo Workspaces**: Fixed a major bug in the `docmd Release to NPM` GitHub Actions workflow where `npm publish` interpreted package paths as GitHub remote repositories. * **Fail-Safe Publishing**: Completely overhauled the publisher to robustly handle partial updates (e.g. ignoring `EPRIVATE` packages and safely skipping already-published packages) without failing the release pipeline. ### 🔌 Plugin Installer (Runtime) * **Missing Registry**: Resolved a critical `MODULE_NOT_FOUND` error that crashed `docmd build` on user sites. The `registry/plugins.json` database was inadvertently excluded from the published NPM tarball, causing imports to fail in production. * **Explicit Whitelisting**: Added the `registry` folder to the `"files"` array in `@docmd/plugin-installer`'s `package.json`, ensuring the registry data is properly bundled in all future NPM releases. --- ## [Release notes for docmd 0.6.2 release](https://docs.docmd.io/06/release-notes/0-6-2/) --- title: "Release notes for docmd 0.6.2 release" description: "Smart Version Switcher, Navigation V2 (navigation.json), Breadcrumbs, Analytics V2, and core security fixes." --- The `docmd` 0.6.2 release focuses on refining the navigation architecture for complex, versioned documentation sites while providing deep insights through enhanced analytics and improving site-wide user experience with automated breadcrumbs. ## ✨ Highlights ### Smart Version Switcher Say goodbye to 404s when switching versions. The version switcher now intelligently checks if the current page exists in the target version. If an exact match isn't found, it gracefully falls back to the root of that version instead of showing a "Not Found" page. ### Navigation Architecture V2 (`navigation.json`) Manage large, versioned documentation sites with ease. You can now place a `navigation.json` file directly inside your versioned documentation folders (e.g., `docs-05/navigation.json`). This eliminates the need for massive, duplicated navigation arrays in your main `docmd.config.js`. ### Automated Breadcrumbs Every documentation page now features automated breadcrumbs located right above the title. This improves user orientation within deeply nested hierarchies and provides better context for both human readers and AI models. Breadcrumbs are enabled by default and can be toggled via `config.layout.breadcrumbs`. ### Analytics V2 (Auto-Event Tagging) The Analytics plugin has been significantly upgraded to support auto-event tagging. It now automatically tracks: * **External Link Clicks**: Understand where your users go after reading your docs. * **Downloads**: Automatically track clicks on PDFs, ZIPs, and other binary assets. * **Search Keywords**: Track what users are looking for with debounced keyword logging (can be disabled via `trackSearch: false`). * **Navigation Interactions**: Track Table of Contents (TOC) clicks and permalink (heading anchor) usage. ## 📝 Complete Changelog ### 🛠️ Core Generator * **V2 Nav Resolution**: Added support for the `navigation.json` resolution pattern. * **Breadcrumb Logic**: Implemented automated crumb trail calculation based on navigation active-state. * **Stable Version Switching**: updated `docmd-main.js` with `fetch(HEAD)` validation for version links. ### 🛡️ Security & Stability * **Dependency Fix**: Patched a high-priority vulnerability in the `flatted` library related to unbounded recursion DoS in the `parse()` revive phase. * **PWA Safety**: Added an explicit Service Worker unregistration safety net to prevent ghost caches for users who remove the PWA plugin. ### 🔌 Plugins * **Analytics V2**: New `autoEvents` option (enabled by default) for event tracking without manual code injection. --- ## [Release notes for docmd 0.6.3 release](https://docs.docmd.io/06/release-notes/0-6-3/) --- title: "Release notes for docmd 0.6.3 release" description: "Contextual Heading IDs, improved Table of Contents accuracy, and deep-link disambiguation." --- The `docmd` 0.6.3 release introduces major refinements to the project's structural integrity, a important patch to the hot-reload Dev Server and a complete overhaul of our internal build and linting verification pipeline. ## ✨ Highlights ### Contextual Heading IDs (Nested Permalinks) Duplicate headers (like "Options" or "Examples") appearing multiple times across different sections of a single page are now automatically disambiguated. IDs are now "Nested" based on their parent hierarchy. For example, a `### Options` header under a `## docmd dev` section will now correctly generate the ID `#docmd-dev-options` instead of a generic `#options`. This ensures: - **Unique Deep Links**: Every section on a page now has a truly unique permalink. - **Accurate TOC**: The Table of Contents now points to the correct section position. - **Enhanced Search**: The search engine can now link users to the exact sub-section they are looking for. ### Collision Safety In the rare case where identical headers appear within the same section, `docmd` now implements an automated numbering suffix (e.g., `#options-1`, `#options-2`), preventing ID collisions and ensuring valid HTML across your entire site. ## 📝 Complete Changelog ### 🛠️ Core Parser - **Smart ID Generation**: Updated the `headingIdPlugin` to track heading levels and parent IDs. - **TOC Integrity**: Improved ID extraction logic to ensure nested IDs are accurately reflected in the sidebar and navigation. - **Search Optimisation**: Refined the metadata generation for headings, providing higher-quality search handles to the MiniSearch engine. ### 🏗️ Internal Tooling & Developer Experience - **Strict Linting Automation**: Activated and strictly integrated ESLint logic directly into the CI verification workflows natively across the entire monorepo (`@docmd-monorepo`). - **Release Preparation Pipeline**: Introduced the new `pnpm prep` CLI tool utilizing seamless end-to-end sandbox reset, installation, compilation, linting, intensive test executions, and security audits into one single cohesive pre-flight deployment sequence! - **Resolved Auditing Traps**: Forced `pnpm.overrides` against `flatted` legacy trees to extinguish false-positive high-risk security blockages during deployment cycles. ### 🐛 Bug Fixes - **Dev Server**: Fixed an issue where the `docmd dev` command would fail to broadcast hot-reload signals due to a `WebSocket is not defined` error in the Node environment. --- ## [Release notes for docmd 0.6.4 release](https://docs.docmd.io/06/release-notes/0-6-4/) --- title: "Release notes for docmd 0.6.4 release" description: "Reliable Emoji Parsing, Auto-Adjusting Grids Container, and Dependency Security." --- The `docmd` 0.6.4 release introduces major refinements to the project's structural integrity with native support for grids, bulletproof container title parsing including emojis, and security upgrades for dependencies. ## ✨ Highlights ### Reliable Title Emojis Inline markdown elements, specifically emojis (e.g., `:rocket:`), are now perfectly parsed within the double quotes of container titles! This supports `card`, `callout`, `collapsible`, `tabs`, and `button` components transparently. The improved parser strictly ignores stray characters outside string headers, ensuring max stability. ### Auto-Adjusting Grids Container Added new `::: grids` and `::: grid` layout wrappers. They form an inherently responsive grid structure that automatically partitions available width (up to typical 4-column limits) while stacking gracefully on narrow mobile displays. No HTML or manual CSS required! ## 📝 Complete Changelog ### 🛠️ Core Parser - **Strict Emoji Parsing**: Updated the `parseQuotedTitle` helper to safely extract strings and ignore trailing unquoted inputs. - **Grids Component**: Introduced the `grids` structural container. ### 🐛 Bug Fixes - **Checklist Styling**: Resolved an issue where bullet points would still mistakenly render alongside checkboxes in standard markdown task lists. Task items now utilize a reliable flexbox layout to isolate the checkbox properly. - **Dependency Security**: Executed a comprehensive workspace audit to upgrade transitive dependencies (including patching known vulnerabilities in `picomatch` and `brace-expansion`). ## Migration Guide No breaking changes. You can upgrade safely without altering any of your existing markdown content. --- ## [Release notes for docmd 0.6.5 release](https://docs.docmd.io/06/release-notes/0-6-5/) --- title: "Release notes for docmd 0.6.5 release" description: "Zero-Latency URL Embeds Engine, Massive Ecosystem Integrations, and Sandbox Hardening." --- The `docmd` 0.6.5 release is an explosive visual deployment introducing official native support for **13+ leading media and developer ecosystem platforms**, easily bridging rich components directly into docmd output using zero-latency compilation powered by `embed-lite@0.1.4`. ## ✨ Highlights ### Zero-Latency Built-in Embeds We've integrated an entirely agnostic embedding bridge natively directly inside the core Markdown parser! You can now map dynamic video, audio, code snippets, and social media blocks onto the page purely by typing its exact URL dynamically: ```md ::: embed https://www.youtube.com/watch?v=dQw4w9WgXcQ ``` The internal engine rigidly intercepts the syntax, automatically validates the ecosystem, and completely formats the resulting player into our secure CSS-bounded UI frameworks - with absolutely out-of-the-box native Responsive Support! ### Core Platforms Fully Supported: * **Video:** YouTube (standard and native 9:16 Shorts), Vimeo, Dailymotion, TikTok * **Social Connectivity:** X (Twitter), Reddit, Instagram, Facebook, LinkedIn (Intelligently intercepts messy `ugcPost` links!) * **Developers & Designers:** GitHub Gists, CodePen, Figma, Google Maps * **Audio Renders:** Spotify, SoundCloud ## 📝 Complete Changelog ### 🛠️ Core UI Integrations - **TikTok V2 Architecture**: Completely sidestepped TikTok's external un-reliable `embed.js` blockquotes (which commonly die against ad-blockers and geographic firewalls) by natively routing docmd components into TikTok's secure, unblockable `/embed/v2` data pipeline! - **GitHub Gists Sandbox Typographic Execution**: Eradicated the raw skeleton fonts usually generated by default Gist injections. `docmd 0.6.5` elegantly forces `data-URIs` payloads to flawlessly inherit our strict premium typographic suite (`-apple-system, Roboto, sans-serif`) with deeply smoothed `.gist` boundary borders directly natively into legacy outputs. - **Embedded Ratio Constraints**: Connected explicit internal flags (e.g. `data-short="true"`) to accurately squash vertical ratios onto `9:16` bounding boxes (ideal for YouTube Shorts) completely dynamically while automatically managing `16:9` ratios for Google Maps and standard iFrames natively using internal CSS layouts. - **Dependencies Bump**: System components heavily locked aggressively against `embed-lite@0.1.4`. ## Migration Guide No breaking changes. You can upgrade safely without altering any of your existing markdown content! --- ## [Release notes for docmd 0.6.6 release](https://docs.docmd.io/06/release-notes/0-6-6/) --- title: "Release notes for docmd 0.6.6 release" description: "The Great Shedding - removing massive dependencies in favour of ultra-light, zero-config in-house packages." --- The `docmd` 0.6.6 release is a massive architectural deployment fundamentally overhauling the core engine to prioritise raw compilation speed and minimal installation footprint by stripping out the heaviest dependencies in the open-source ecosystem in favour of bespoke, ultra-fast custom architectures. ## ✨ Highlights ### The Great Dependency Shedding Instead of relying on heavy legacy packages with cascading "waterfall" dependencies, `docmd` now utilizes native solutions and our own newly published `lite-*` libraries. This collapses the internal engine constraints from ~30 cascading external packages down to exactly **1** (`yaml`), dropping ~2.5MB of weight and making compilation up to **8.1x faster**! ### Core Packages Eliminated: | Legacy Package | New Engine | Waterfall Reduction | Performance Gain | Approx Weight Shed | |------------------|-------------|---------------------|-------------------|--------------------| | **`highlight.js`**| `lite-hl` | No waterfall deps | **~8.1x faster** | **~2MB** | | **`ejs`** | `lite-template`| 7 packages removed | **~3.2x faster** | **~50KB** | | **`gray-matter`** | `lite-matter` | 9 packages removed | Highly optimised | **~100KB** | | **`chokidar`** | `native fs` | 14+ packages removed| Native speed | **~200KB** | | **`commander`** | `util.parseArgs`| No 3rd party deps | Zero overhead | **~60KB** | ## 📝 Complete Changelog ### 🛠️ Core Engine Patches - **Zero-Config Root Index Fix**: Resolved the pervasive 404 bug at the domain root. If an `index.md` is missing, the auto-router now successfully dictates the designated fallback homepage directly to the generator engine natively. - **Native EJS Content Pages**: `.ejs` files are now recognised as first-class content pages natively by the auto-router. They process frontmatter dynamically and render alongside standard Markdown files easily. - **Recursive Frontmatter Stripping**: When utilizing `<%- await include(...) %>` inside complex nested components, `docmd` natively strips YAML frontmatter blocks from the sub-templates before rendering them, guaranteeing clean markdown compilation. ### 📦 The `lite-*` Public Releases - **lite-template@0.1.2**: Evolved into a genuinely standalone async alternative to EJS, natively resolving `include()` from the disk (or virtually via `includer` memory hooks). - **lite-hl@0.1.2**: Re-mapped to guarantee pixel-perfect legacy `highlight.js` CSS theme compatibility. Upgraded to support 60+ complex shell commands (`grep`, `find`, `awk`) and dynamic `$VARIABLES`. - **lite-matter@0.1.1**: Officially released as a reliable standalone metadata extraction library capable of natively parsing YAML structures instantly without arbitrary parsing bottlenecks. - **TypeScript & ESM Support**: All `lite` packages have strict `exports` map resolution introduced to guarantee flawlessly typed ESM module ingestion across modern IDE architectures natively. ## Migration Guide No breaking changes. You can upgrade safely without altering any of your existing markdown content! --- ## [Release notes for docmd 0.6.7 release](https://docs.docmd.io/06/release-notes/0-6-7/) --- title: "Release notes for docmd 0.6.7 release" description: "Live Build Engine Optimisation and Absolute Path Correction." --- The `docmd` 0.6.7 release brings a massive upgrade to our landing-page capabilities with the introduction of the new Hero 2.0 component, alongside important stability patches for our build infrastructure and container parsing logic. ## ✨ Highlights ### 🚀 Landing Page Revolution & Hero We've significantly empowered **No-Style Pages** (docmd's answer to landing pages). You can now selectively re-enable the core `menubar` and `scripts` while maintaining a blank canvas, allowing you to build high-fidelity entry points that feel deeply integrated with your documentation. To make building those pages effortless, we are introducing the **Hero Container**. Designed for high-impact visual storytelling, this component automatically renders stunning, responsive hero sections. It supports advanced features like `layout:split` for side-by-side media, `layout:slider` for interactive carousels, and `glow:true` for premium visual effects. ### 🍱 Enhanced Embed Ergonomics We've updated the `::: embed` syntax to be more flexible, now supporting optional brackets or quotes around the URL (e.g., `::: embed [url]` or `::: embed "url"`), improving structural consistency and developer ergonomics. ## 📝 Complete Changelog ### 🛠️ Core UI & Build Patches - **Hero Integration**: Added the powerful new `::: hero` markdown component with split and slider layout generation. - **Container Depth Tracking Fix**: Resolved a critical parsing bug where single-line containers (like `::: button` and `::: embed`) would corrupt the depth tracking of parent containers, breaking complex nested layouts. - **Markdown Rendering on No-Style Pages**: Fixed a regression where `noStyle: true` bypassed the markdown engine, ensuring core components like buttons and callouts work as expected on custom pages. - **Enhanced Component Opt-in**: Added `menubar: true` and `spa: true` toggles for `noStyle` pages, giving developers granular control over the landing page environment. - **Live Build Source Fallback**: Implemented an automated asset discovery resolver that gracefully falls back to looking for build components in the `dist/` folder when the package is installed as a pure NPM dependency. ## Migration Guide No breaking changes. You can upgrade safely without altering any of your existing markdown content! --- ## [Release notes for docmd 0.6.8 release](https://docs.docmd.io/06/release-notes/0-6-8/) --- title: "Release notes for docmd 0.6.8 release" description: "Plugin API expansion with WebSocket RPC, source editing tools, and the new threads plugin." --- The `docmd` 0.6.8 release is a foundational leap for the plugin ecosystem. It introduces a **WebSocket RPC protocol** that enables real-time browser-to-server communication, powerful **source editing tools** for manipulating markdown files from the browser, and a brand-new **Threads plugin** for inline discussion comments - all without adding any new runtime dependencies. ## ✨ Highlights ### 🔌 WebSocket RPC - Live Plugin Communication The dev server's existing WebSocket connection (used for live-reload) has been upgraded with a **JSON-based RPC protocol**. Plugins can now register server-side action handlers that the browser can call in real-time. This opens the door to live-editing features, collaborative workflows, and interactive documentation tools. A new `window.docmd` browser API is automatically injected during development, providing: - `docmd.call(action, payload)` - RPC calls with response - `docmd.send(name, data)` - Fire-and-forget events - `docmd.on(name, callback)` - Subscribe to server-pushed events - `docmd.afterReload()` / `docmd.scheduleReload()` - State persistence across live reloads ### 🧰 Source Editing Tools A new `source-tools` utility provides block-level markdown manipulation from plugin code. It can locate text within blocks, wrap content with syntax markers, insert/replace/remove blocks - all with frontmatter-aware line tracking and path traversal protection. ### 🧵 Threads Plugin (Alpha) Introducing `@docmd/plugin-threads` - inline discussion threads stored directly in your markdown files. Select text, leave comments, reply, react with emoji, and resolve threads. No database needed - comments are the source of truth in the `.md` files. ### 📤 Parser Export The `createDepthTrackingContainer` function is now exported from `@docmd/parser`, allowing external plugins to register custom `::: container` syntax with proper nesting support. ## 📝 Complete Changelog ### 🔌 Plugin API - **WebSocket RPC Protocol**: JSON-based message handling alongside the existing `reload` string protocol for full backward compatibility. - **Action Dispatcher**: Routes incoming RPC calls to registered plugin action handlers with a sandboxed `ActionContext`. - **Plugin Hooks Expansion**: Plugins can now export `actions` and `events` objects alongside existing build-time hooks. - **Type Definitions**: New `PluginModule` interface documents the full plugin contract (`types.ts`). - **Browser API Client**: `docmd-api.js` injected automatically during dev mode with reconnect and retry logic. ### 🧰 Core Improvements - **Plugin Loader Hardening**: Refactored the core module resolver with reliable `try/catch` fallbacks to gracefully warn against malformed plugins without crashing the build or throwing. - **Source Tools**: New `getBlockAt`, `findText`, `wrapText`, `insertAfter`, `replaceBlock`, `removeBlock` utilities for markdown source manipulation. - **RPC DOM Mapping**: Injected `data-source-file` automatically into the UI `<body>` layout container, enabling browser-to-server file tracking during interaction loops. - **Bundlephobia Compatibility**: Explicitly defined the `"browser": false` boundary on `@docmd/core` to prevent legacy external compilers from incorrectly trying to browserify server-side engine APIs. - **Codebase Standardisation**: Comprehensive alignment of license boundaries, boilerplate headers, trailing whitespaces, and metadata schemas across all plugins, legacy setups, and failsafe scripts. - **Git Dev Info**: Dev server detects git user info and injects it for plugin author identification (lazy-loaded). - **Path Security**: All file operations are sandboxed via `safePath()` validation against the project root. - **Native File Watcher**: Preserved the chokidar-free `fs.watch` implementation introduced in 0.6.6. ### 🧵 New Plugin: Threads - Text selection and highlight-based thread anchoring (`==text=={threadId}` syntax). - Full CRUD: create threads, add/edit/delete comments, reply chains, emoji reactions. - Thread resolution with author tracking and timestamps. - Author profiles stored in `.threads/authors.json` with Gravatar support. - Lit-based Web Components for the client-side UI. ### 📤 Parser - **Exported `createDepthTrackingContainer`**: Available via `import { createDepthTrackingContainer } from '@docmd/parser'` for plugin authors building custom container syntax. - Added comprehensive JSDoc documentation to the container API. ### 🧹 Bug Fixes & Refactors - **TypeScript Overhauls**: Vast strict-null enforcement, non-implicit global declarations, and DOM explicit-typing integrations finalized inside `@docmd/plugin-mermaid` and `@docmd/plugin-search` clients. - **CSS Layout Issues**: Fixed iframe aspect-ratios, Hero component bounds, and plugin-threads text area sizing. Realigned responsive padding breakpoints. - **Legacy Header Cleanups**: Stripped conflicting or malformed document headers from ecosystem forks and standardised `docmd.io` branding definitions consistently across active `packages/*`. ## Migration Guide No breaking changes. The WebSocket RPC protocol is additive - existing live-reload behaviour is fully preserved. The new `docmd-api.js` replaces the inline reload script with an enhanced version that handles both reload and RPC. --- ## [Release notes for docmd 0.6.9 release](https://docs.docmd.io/06/release-notes/0-6-9/) --- title: "Release notes for docmd 0.6.9 release" description: "Core architectural stability, reliable plugin dynamic resolution, and the official KaTeX math plugin." --- The `docmd` 0.6.9 release focuses on significant core stability updates, hardening the plugin resolution architecture, and the introduction of a highly requested mathematical plugin using server-side rendered LaTeX. ## ✨ Highlights ### 🧮 Math Plugin (KaTeX) Introducing `@docmd/plugin-math` - an official extension providing native parsed `LaTeX` and `KaTeX` support easily decoupled into docmd. Writing `$E = mc^2$` or block arrays `$$` automatically hooks into reliable server-side build steps producing purely static visual nodes. No client-side Javascript compilation is required! ### 🏗️ Plugin Security Hardening The plugin resolution architecture has been completely rewritten. Shorthand names (e.g. `math`, `search`) are now **strictly reserved** for official `@docmd/plugin-*` packages. Third-party plugins must be referenced by their full package name - there is no fallback cascade to community or bare npm names. This eliminates supply-chain attack vectors via namespace squatting entirely. ### 🧹 Layout & UI Stability This release contains sweeping fixes protecting custom UI definitions matching `#101`. `noStyle` structurally broken layout grids have been resolved restoring total CSS conformity across customised landing pages heavily featuring `.menubar` blocks. Navigational headers explicitly linked toward raw `.md` domains are also safely purged enforcing clean-urls matching the generated HTML structure! ## 📝 Complete Changelog ### 🧰 Core Improvements - **Plugin Security Hardening**: Rewrote `core/src/utils/plugin-loader` - shorthand names now resolve exclusively to official `@docmd/plugin-*` scope. Third-party plugins require full package names with no fallback cascade. - **Expanded Asset Parsing (#100)**: Rewrote `core/src/engine/assets.ts` to natively verify and append nested `config.src/assets` definitions concurrently alongside root `CWD/assets` supporting local documentation directories explicitly. - **UX Menu Linking**: Menubar now uses absolute base paths instead of relative paths, fixing broken URLs on versioned pages where menubar links incorrectly resolved to version-scoped paths (e.g. `/05/nostyle` instead of `/nostyle`). ### 🧵 Bug Fixes & Refactors - **miniSearch Fatal Crashes (#8)**: Fixed a runtime structural array duplication resulting in a failed indexing routine. Added `seenIds` tracking inside `plugins/search/src/index.ts` intercepting overlapping layout blocks silently. - **Menubar Flex Structural Collapse (#101)**: Found and deleted orphaned closing elements inside `menubar.ejs`. Options menus (`theme`, `search`) correctly load into `menubar-right` aligned grids completely separate from iterated loop structures bridging un-styled overrides easily. - **SPA Sidebar URL Nesting**: Fixed an issue where SPA navigation caused sidebar hrefs to nest incorrectly (e.g. `/nostyle/nostyle/`). The SPA router now resolves fetched sidebar hrefs to absolute paths before syncing them into the current DOM. - **Removed Implicit `.md` Stripping**: The config normalizer no longer silently strips `.md` extensions from navigation and menubar URLs. Users should use clean URLs in their config as documented - this prevents hidden routing conflicts with SPA navigation. - **TypeScript Strictness**: Added `"types": ["node"]` to monorepo base `tsconfig.json` and replaced `import.meta.dirname` with `fileURLToPath` for universal type compatibility across all packages. ## Migration Guide No breaking changes for users of official plugins. If you were relying on shorthand names for third-party plugins, update your `docmd.config.js` to use the full package name instead. --- ## [Assets Management](https://docs.docmd.io/06/theming/assets-management/) --- title: "Assets Management" description: "How docmd handles CSS, JavaScript, and Image assets during the build process." --- `docmd` takes a "Mirror & Map" approach to assets. This ensures that your local development paths stay consistent with your production build. ## Directory Structure By default, `docmd` looks for an `assets/` folder in your project root. ```bash my-docs/ ├── assets/ # Source Assets │ ├── css/ │ ├── js/ │ └── images/ ├── docs/ # Content ├── docmd.config.js └── site/ # Build Output (Automatically mirrored) ``` ## Automatic Copying (v0.5.1+) When you run `docmd build` or `docmd dev`: 1. **The Mirroring Logic**: The entire contents of your `assets/` folder are recursively copied to `site/assets/`. 2. **Stability**: We use a hardened copy engine with automatic retries to prevent "File Busy" or "ENOENT" errors on macOS and modern SSDs. 3. **Referencing**: You should always reference assets from your Markdown or Config using the **root-relative** path: ```markdown ![Logo](/assets/images/logo.png) ``` ## Custom CSS & JS Integration To link your assets to every page, add them to your theme configuration: ```javascript // docmd.config.js export default { theme: { customCss: ['/assets/css/branding.css'] }, customJs: ['/assets/js/utils.js'] } ``` ## AI Recognition Strategy When adding assets: * **Organise by type**: Keep `/css`, `/js`, and `/images` separate. This helps AI agents locate relevant styles or scripts instantly when you ask them to "edit the header colour". * **Use Descriptive Filenames**: Naming an image `authentication-flow-diagram.png` provides much more context to the `llms.txt` crawler than `img_01.png`. --- ## [Available Themes](https://docs.docmd.io/06/theming/available-themes/) --- title: "Available Themes" description: "Explore docmd's built-in themes including Sky, Ruby, and Retro. Learn how to switch themes with a single config line." --- `docmd` provides a set of professionally designed, light/dark responsive themes. You can switch your entire site's aesthetic by changing a single key in `docmd.config.js`. ## How to Switch Themes ```javascript // docmd.config.js export default { theme: { name: 'sky', appearance: 'system', // Options: 'light', 'dark', 'system' } } ``` ## Built-in Theme Gallery | Theme | Best For | Vibes | | :--- | :--- | :--- | | `default` | Low-profile docs | Minimal, lightweight, clean | | `sky` | Product Docs | Modern, premium, standard-issue | | `ruby` | Brand Identity | Sophisticated, serif headers, vibrant | | `retro` | Dev Tools | 80s Terminals, monospace, neon accents | <div class="theme-picker" style="display: flex; gap: 10px; margin: 20px 0;"> <button onclick="switchDocTheme('default')" class="docmd-button" style="color:#fff;background: #2e2e2e;">Default</button> <button onclick="switchDocTheme('sky')" class="docmd-button" style="color:#fff;background: #0097ff;">Sky</button> <button onclick="switchDocTheme('ruby')" class="docmd-button" style="color:#fff;background: #960b0b;">Ruby</button> <button onclick="switchDocTheme('retro')" class="docmd-button" style="color:#fff;background: #a95308; border: 1px solid #0ec80e;">Retro</button> </div> ### 1. `sky` (Default) The gold standard for modern documentation. It features crisp typography, subtle transitions, and high-contrast light/dark modes that match modern SaaS platforms. ### 2. `ruby` A high-elegance theme using serif typography for headers and a deep, jewel-toned colour palette. Perfect for documentation that needs to feel authoritative and premium. ### 3. `retro` A nostalgia-fueled theme inspired by vintage computing. Features include phosphor-green text on black backgrounds (in dark mode), scanline effects, and monospace fonts like Fira Code by default. ### 4. `default` A total "Blank Slate" theme. Use this if you plan on adding extensive custom CSS and don't want any built-in design layers interfering with your branding. ## Theming Architecture 1. **CSS Layering**: Themes are additive. Choosing `sky` actually loads the base `default` styles and then overlays the `sky` aesthetic on top. 2. **Native dark-mode**: Every theme includes a first-class dark mode implementation. 3. **No Refresh**: When users switch themes via the UI, the SPA engine updates the `--docmd-primary` variables instantly without a page reload. ::: callout tip When describing your documentation layout to an AI developer tool, mentioning your theme (e.g., "I'm using the `retro` theme") helps the model suggest custom CSS overrides that align with that specific theme's variable schema. ::: --- ## [Custom Styles & Scripts](https://docs.docmd.io/06/theming/custom-css-js/) --- title: "Custom Styles & Scripts" description: "Inject your own CSS and JS files to extend docmd's functionality and branding." --- While `docmd` themes are highly flexible, you may want to inject your own stylesheets or interactive scripts. This is done via the `theme.customCss` and `customJs` arrays in your configuration. ## Custom CSS Use `theme.customCss` to override existing styles or add new ones. ```javascript // docmd.config.js export default { theme: { customCss: [ '/assets/css/branding.css' // Path relative to site root ] } } ``` ### How it Works 1. Place your CSS file inside your project’s assets folder (e.g., `docs/assets/css/branding.css`). 2. `docmd` will automatically copy it to the build folder and inject a `<link>` tag into every page. 3. Custom CSS is loaded **after** the theme styles, ensuring your overrides take priority. ## Custom JavaScript Use the top-level `customJs` array for scripts that add behaviour or integrate 3rd-party services. ```javascript // docmd.config.js export default { customJs: [ '/assets/js/feedback-widget.js' ] } ``` ### Life-cycle Awareness Scripts are injected at the bottom of the `<body>` tag. Since `docmd` is a **Single Page Application (SPA)**, remember that: * The page does not fully reload when navigating between links. * You may need to listen for the `docmd:navigated` event to re-initialise your scripts on new pages. ```javascript // Example: Re-init on page change document.addEventListener('docmd:page-mounted', () => { console.log('New page loaded via SPA router'); initMyCustomWidget(); }); ``` ::: callout tip Adding custom CSS and JS allows AI models (like ChatGPT) to suggest much more tailored UI improvements. If you mention "I have a custom `branding.css` file", the model can provide specific selectors that won't conflict with the core `docmd` engine. ::: --- ## [Customisation & Variables](https://docs.docmd.io/06/theming/customisation/) --- title: "Customisation & Variables" description: "A complete reference of docmd's CSS variables and component classes for advanced styling." --- `docmd` is built using a CSS variable-first architecture. This means you can restyle your entire site by simply overriding a few keys in a `:root` block without writing complex CSS selectors. ## Global Variable Reference | Variable | Default (Light) | Default (Dark) | Description | | :--- | :--- | :--- | :--- | | `--bg-color` | `#ffffff` | `#09090b` | Main page background. | | `--text-color` | `#3f3f46` | `#a1a1aa` | Standard body text. | | `--text-heading` | `#09090b` | `#fafafa` | Title and Header colours. | | `--link-color` | `#068ad5` | `#068ad5` | Primary accent / links. | | `--border-color` | `#e4e4e7` | `#27272a` | Dividers and borders. | | `--sidebar-bg` | `#fafafa` | `#09090b` | Navigation background. | | `--ui-border-radius` | `6px` | `6px` | Rounding for all UI items. | | `--sidebar-width` | `260px` | `260px` | Sidebar column width. | ## Example Override To change your site's primary accent colour, add this to your `customCss`: ```css :root { --link-color: #f43f5e; /* Rose 500 */ } body[data-theme="dark"] { --link-color: #fb7185; /* Rose 400 */ } ``` ## Component Targeting If you need to style specific components, use these top-level classes: * `.main-content`: The wrapper for all Markdown content. * `.sidebar-nav`: The internal navigation list. * `.page-header`: The top navigation bar. * `.docmd-search-modal`: The search overlay. * `.docmd-tabs`: Tab container components. * `.callout`: The alert/note boxes. ## Troubleshooting specificity Most `docmd` styles use low specificity. If your overrides aren't applying, ensure your `customCss` is registered correctly and check if adding a `body` prefix (e.g., `body .main-content`) helps. ::: callout tip Because `docmd` uses standard CSS variables, you can ask an AI: *"Give me a professional colour palette using --link-color and --bg-color for docmd"*. The model will be able to provide ready-to-paste CSS that integrates perfectly with the built-in themes. ::: --- ## [Icons](https://docs.docmd.io/06/theming/icons/) --- title: "Icons" description: "How to use and customise Lucide icons in your documentation." --- `docmd` comes with built-in support for the [Lucide](https://lucide.dev/) icon library. Icons can be used in your navigation sidebar, buttons, and custom components to provide visual cues and improve scannability. ## Navigation Icons Assign an icon to any navigation item in your `docmd.config.js`. Use the kebab-case name of any icon found on the Lucide website. ```javascript navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Setup', path: '/setup', icon: 'settings' } ] ``` ## Button Icons You can also use icons inside your button labels by including the raw HTML or using standard Lucide naming if supported by your theme. ```markdown ::: button "Download" /download icon:download ``` ## CSS Styling All icons are rendered as inline SVGs with the class `.lucide-icon`. You can globally change their size or stroke weight in your `customCss`: ```css .lucide-icon { stroke-width: 1.5px; /* Thinner icons for a modern look */ width: 1.2rem; height: 1.2rem; } /* Target a specific icon */ .icon-rocket { color: #ff5733; } ``` ## Icon Reference We support the entire Lucide library. You can browse the thousands of available icons here: ::: button "Browse Lucide Icons" external:https://lucide.dev/icons --- ## [Light & Dark Mode](https://docs.docmd.io/06/theming/light-dark-mode/) --- title: "Light & Dark Mode" description: "How to configure the default viewing mode and manage the theme switcher for the best user experience." --- `docmd` provides built-in support for light and dark colour schemes. It detects user system preferences automatically and allows manual overrides via a UI toggle. ## Default Viewing Mode You specify the starting state of your documentation in `docmd.config.js`. ```javascript // docmd.config.js export default { theme: { name: 'sky', appearance: 'system' // Options: 'light', 'dark', 'system' (default) } } ``` * **`system`**: Matches the user's OS preference (Recommended). * **`light`**: Force light mode on initial load. * **`dark`**: Force dark mode on initial load. ## Configuring the Toggle Button The theme switcher is part of the **Options Menu**. You can control its visibility and position within the `layout` object. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom' components: { themeSwitch: true // Show or hide the Sun/Moon toggle } } } ``` ## How it works (Technical) The theme engine applies a `data-theme` attribute to the `<body>` tag: * `<body data-theme="light">` * `<body data-theme="dark">` If you are using a themed design like `sky`, the attribute will be `sky-light` or `sky-dark`. ### CSS Variables `docmd` themes use CSS variables for all colours. You can override these variables in your own CSS to customise the look of either mode. ```css /* Custom CSS override */ :root { --docmd-primary: #4f46e5; /* Primary accent for light mode */ } body[data-theme="dark"] { --docmd-primary: #818cf8; /* Primary accent for dark mode */ } ``` ## User Persistence When a user manually toggles the mode, their preference is stored in `localStorage`. `docmd` instantly reads this value on every page load to prevent "theme flickering" (FOUC). ::: callout tip When generating content, LLMs prefer high-contrast structures. `docmd` ensures that code snippets and callouts remain accessible in both modes, ensuring that `llms-full.txt` payloads are correctly understood as semantic blocks regardless of which mode was active during the build. ::: --- ## [Browser API (Client-Side)](https://docs.docmd.io/07/api/browser-api/) --- title: "Browser API (Client-Side)" description: "Interact with docmd from the browser - live compilation and dev-mode plugin communication." --- `docmd` provides two browser APIs: the **isomorphic compile engine** for rendering markdown in the browser, and the **dev-mode plugin API** for real-time communication with the dev server. ## Isomorphic Compile Engine The same engine that generates static sites in Node.js can run entirely within a web browser. This is ideal for building CMS previews, interactive playgrounds, or embedding documentation into existing web applications. ### Installation via CDN ```html <!-- Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- The Isomorphic Engine --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` ### `docmd.compile(markdown, config)` Compiles raw Markdown into a full HTML document string using the default `docmd` layout. **Parameters:** - `markdown` (String): The raw Markdown content. - `config` (Object): Configuration overrides (same schema as `docmd.config.js`). **Returns:** `Promise<String>`: The complete HTML document. ### Example: Live Preview To ensure style isolation, it is recommended to render the output inside an `<iframe>` using the `srcdoc` attribute. ```javascript const editor = document.getElementById('editor'); const preview = document.getElementById('preview'); async function updatePreview() { const html = await docmd.compile(editor.value, { title: 'Preview', theme: { appearance: 'light' } }); preview.srcdoc = html; } editor.addEventListener('input', updatePreview); ``` ## Dev-Mode Plugin API During `docmd dev`, a `window.docmd` global is automatically injected into every page. This API enables real-time communication between browser-side plugin code and server-side action handlers via WebSocket RPC. ::: callout info "Dev Mode Only" The plugin API methods below are only available during `docmd dev`. They are not included in production builds. ::: ### `docmd.call(action, payload)` Call a server-side action handler registered by a plugin. Returns a promise that resolves with the handler's return value. ```javascript // Call a plugin action and get a result const threads = await docmd.call('threads:get-threads', { file: 'docs/getting-started.md' }); console.log(threads); // Array of thread objects ``` If the action modifies source files, the page automatically reloads after the promise resolves. ### `docmd.send(name, data)` Send a fire-and-forget event to the server. No response is returned. ```javascript // Notify the server of a page view (no response expected) docmd.send('analytics:page-view', { path: window.location.pathname }); ``` ### `docmd.on(name, callback)` Subscribe to server-pushed events. Returns an unsubscribe function. ```javascript // Listen for server-broadcast events const unsub = docmd.on('threads:updated', (data) => { console.log('Threads updated:', data); }); // Later: unsubscribe unsub(); ``` ### `docmd.afterReload(name, callback)` Declare a handler that runs after a page reload. If context was stashed with `scheduleReload`, the callback receives it. ```javascript // Restore scroll position after a live-reload docmd.afterReload('scroll-restore', (ctx) => { window.scrollTo(0, ctx.scrollY); }); ``` ### `docmd.scheduleReload(name, context)` Stash context into `sessionStorage` for a named `afterReload` handler. The matching handler fires with this context after the next page reload. ```javascript // Before a file edit triggers a reload, save state docmd.scheduleReload('scroll-restore', { scrollY: window.scrollY }); ``` ## Considerations - **No File System**: The browser engine cannot scan folders. You must provide the `navigation` array explicitly in the config object if you need a sidebar. - **Node-Only Plugins**: Plugins that rely on Node.js APIs (like Sitemap or LLM text generation) are disabled in the browser environment. - **WebSocket Connection**: The dev-mode API requires an active WebSocket connection to the dev server. It will auto-reconnect with exponential backoff if the connection drops. --- ## [CLI Commands](https://docs.docmd.io/07/api/cli-commands/) --- title: "CLI Commands" description: "Command-line reference for docmd - all available commands and options." --- ## Commands Overview | Command | Description | |:--------|:------------| | [`docmd init`](#docmd-init) | Scaffold a new documentation project | | [`docmd dev`](#docmd-dev) | Start the development server with hot reload | | [`docmd build`](#docmd-build) | Generate a production static site | | [`docmd live`](#docmd-live) | Launch the browser-based Live Editor | | [`docmd stop`](#docmd-stop) | Kill running dev servers | | [`docmd deploy`](#docmd-deploy) | Generate deployment configs (Docker, Nginx, Caddy) | | [`docmd migrate`](#docmd-migrate) | Upgrade legacy configs to V2 schema | | [`docmd add <plugin>`](#docmd-add-plugin) | Install and configure a plugin | | [`docmd remove <plugin>`](#docmd-remove-plugin) | Remove a plugin and its config | ## Global Options | Option | Alias | Description | |:-------|:------|:------------| | `--config <path>` | `-c` | Path to config file (default: `docmd.config.js`) | | `--verbose` | `-V` | Show detailed build logs | | `--version` | `-v` | Output the installed version | | `--help` | `-h` | Display help menu | | `--cwd <path>` | - | Override working directory (for monorepos) | ## `docmd init` Scaffold a new documentation project in the current directory. ```bash docmd init ``` Creates: - `docs/index.md` - boilerplate home page - `docmd.config.js` - recommended defaults - Updated `package.json` with build scripts ## `docmd dev` Start a development server with instant hot reload. ```bash docmd dev [options] ``` | Option | Alias | Description | |:-------|:------|:------------| | `--port <number>` | `-p` | Server port (default: `3000`) | | `--config <path>` | `-c` | Path to config file | ## `docmd build` Generate a production-ready static site in `site/`. ```bash docmd build [options] ``` | Option | Alias | Description | |:-------|:------|:------------| | `--offline` | - | Rewrite links to `.html` for `file://` browsing | | `--config <path>` | `-c` | Path to config file | ## `docmd live` Launch the browser-based Live Editor. ```bash docmd live [options] ``` | Option | Description | |:-------|:------------| | `--build-only` | Generate the editor bundle without starting the server | ## `docmd stop` Kill running docmd dev servers. ```bash docmd stop [options] ``` | Option | Alias | Description | |:-------|:------|:------------| | `--port <number>` | `-p` | Stop only the server on this port | | `--force` | `-f` | Also kill `serve` processes on ports 3000, 3001, 8080, 8081 | ## `docmd deploy` Generate deployment configuration files. ```bash docmd deploy [options] ``` | Option | Description | |:-------|:------------| | `--docker` | Generate a `Dockerfile` | | `--nginx` | Generate `nginx.conf` | | `--caddy` | Generate `Caddyfile` | | `--force` | Overwrite existing deployment files | ## `docmd migrate` Upgrade legacy docmd V1 configs to the V2 schema. ```bash docmd migrate ``` Automatically re-maps deprecated keys (e.g., `siteTitle` → `title`) and restructures the config object. ## `docmd add <plugin>` Install and configure an official or community plugin. ```bash docmd add <plugin-name> ``` | Example | Description | |:--------|:------------| | `docmd add analytics` | Install `@docmd/plugin-analytics` | | `docmd add search` | Install `@docmd/plugin-search` | The CLI detects your package manager (npm, pnpm, yarn, or bun) and injects recommended defaults into `docmd.config.js`. ## `docmd remove <plugin>` Safely uninstall a plugin and clean up its config. ```bash docmd remove <plugin-name> ``` Removes: - The npm package - Plugin configuration from `docmd.config.js` ::: callout tip "Agent-Compatible Logging :robot:" `docmd` uses structured terminal logging. AI agents can parse output precisely for error detection and automated maintenance. ::: --- ## [Client-Side Events](https://docs.docmd.io/07/api/client-side-events/) --- title: "Client-Side Events" description: "Hook into the docmd SPA lifecycle to add interactive features." --- `docmd` utilises a lightweight Single Page Application (SPA) router to provide instant page transitions. Because the browser does not perform a full reload during navigation, scripts relying on `DOMContentLoaded` will not re-execute. To handle this, `docmd` dispatches custom lifecycle events that you can listen for in your `customJs` files. ## `docmd:page-mounted` This event is dispatched whenever a new page has been successfully fetched and injected into the DOM. ### Usage Add a listener to the `document` object to re-initialise third-party libraries or trigger custom animations. ```javascript document.addEventListener('docmd:page-mounted', (event) => { const { url } = event.detail; console.log(`Navigated to: ${url}`); // Re-initialise components // Example: Prism.highlightAll(); }); ``` ### Event Details (`event.detail`) | Property | Type | Description | | :--- | :--- | :--- | | `url` | `String` | The absolute URL of the page that was just mounted. | ## Best Practices 1. **Idempotency**: Ensure your initialisation logic can be safely called multiple times on the same page or cleaned up before the next navigation. 2. **Global Scope**: Scripts added via `customJs` are executed in the global scope. Use an IIFE (Immediately Invoked Function Expression) to avoid polluting the `window` object. 3. **Cleanup**: If your script adds global event listeners (e.g., `window.onresize`), consider tracking the current path to remove them when the user navigates away. --- ## [Live Editor](https://docs.docmd.io/07/api/live-api/) --- title: "Live Editor" description: "Understanding the docmd Live Editor and its browser-based authoring workflow." --- The `docmd` Live Editor is a dedicated environment for real-time documentation authoring. It uses the isomorphic core of `docmd` to provide an instant, side-by-side preview of your Markdown content without requiring a backend build process. ## Launching the Editor Start the local Live Editor by running: ```bash docmd live ``` The editor will typically be available at `http://localhost:3000`. ## Architecture Unlike the standard `dev` server which rebuilds files on the disk, the Live Editor runs the `docmd` engine directly in your browser. This enables: 1. **Instant Feedback**: Content is re-rendered as you type. 2. **Portable Playgrounds**: The editor can be bundled into a static site for hosting on platforms like GitHub Pages. 3. **Cross-Platform Consistency**: The preview uses the exact same rendering logic as the production build. ## Static Deployment Generate a shareable, standalone version of the editor: ```bash docmd live --build-only ``` This creates a `dist/` directory containing the editor's HTML and the bundled isomorphic engine. --- ## [Node.js API](https://docs.docmd.io/07/api/node-api/) --- title: "Node.js API" description: "Integrate docmd's build engine into your custom Node.js scripts and automation pipelines." --- For advanced workflows, you can import and use the `docmd` build engine directly within your own Node.js applications. This is ideal for custom CI/CD pipelines, automated documentation generation, or extending `docmd` for specialised environments. ## Installation Ensure `@docmd/core` is installed in your project: ```bash npm install @docmd/core ``` ## Core Functions ### `buildSite(configPath, options)` The primary build function. It handles configuration loading, Markdown parsing, and asset generation. ```javascript import { buildSite } from '@docmd/core'; async function runBuild() { await buildSite('./docmd.config.js', { isDev: false, // Set to true for watch mode logic offline: false, // Set to true to optimise for file:// access zeroConfig: false // Set to true to bypass config file detection }); } ``` ### `buildLive(options)` Generates the browser-based **Live Editor** bundle. ```javascript import { buildLive } from '@docmd/core'; async function generateEditor() { await buildLive({ serve: false, // true starts a local server; false generates static files port: 3000 // Custom port if serve is true }); } ``` ## Example: Custom Pipeline You can wrap `docmd` to create complex documentation workflows. ```javascript import { buildSite } from '@docmd/core'; import fs from 'fs-extra'; async function deploy() { // 1. Generate dynamic content await fs.writeFile('./docs/dynamic.md', '# Generated Content'); // 2. Execute docmd build await buildSite('./docmd.config.js'); // 3. Move output await fs.move('./site', './public/docs'); } ``` ::: callout tip The programmatic API is highly compatible with **AI-Driven Documentation**. Agents can trigger builds after content updates to verify integrity and manage deployments autonomously. ::: ## Plugin API (`@docmd/api`) The `@docmd/api` package is the dedicated home for the plugin system. It provides hook registration, WebSocket RPC dispatch, source editing tools, and **centralised URL utilities**. ```bash npm install @docmd/api ``` ### URL Utilities Plugins should use these centralised utilities instead of rolling their own URL logic. #### `outputPathToSlug(outputPath)` Convert a build engine output path to a clean directory-style slug. ```javascript import { outputPathToSlug } from '@docmd/api'; outputPathToSlug('guide/index.html'); // → 'guide/' outputPathToSlug('index.html'); // → '/' outputPathToSlug('de/v1/api/index.html'); // → 'de/v1/api/' ``` #### `outputPathToPathname(outputPath)` Convert to a root-relative pathname. ```javascript import { outputPathToPathname } from '@docmd/api'; outputPathToPathname('guide/index.html'); // → '/guide/' outputPathToPathname('index.html'); // → '/' ``` #### `outputPathToCanonical(outputPath, siteUrl)` Build a full canonical URL. ```javascript import { outputPathToCanonical } from '@docmd/api'; outputPathToCanonical('guide/index.html', 'https://example.com'); // → 'https://example.com/guide/' ``` #### `sanitizeUrl(url)` Collapse double slashes (except after protocol). ```javascript import { sanitizeUrl } from '@docmd/api'; sanitizeUrl('https://example.com//path/'); // → 'https://example.com/path/' sanitizeUrl('/foo//bar/'); // → '/foo/bar/' ``` #### `buildAbsoluteUrl(base, localePrefix, versionPrefix, pagePath)` Build an absolute URL with locale and version prefixes. ```javascript import { buildAbsoluteUrl } from '@docmd/api'; buildAbsoluteUrl('/', 'de/', 'v1/', 'guide/'); // → '/de/v1/guide/' ``` #### `resolveHref(href)` Normalise user-written hrefs to clean URLs. Handles `.md` stripping, trailing slashes, `external:` and `raw:` prefixes. ```javascript import { resolveHref } from '@docmd/api'; resolveHref('overview.md'); // → { href: 'overview/', isExternal: false, isRaw: false } resolveHref('external:https://github.com/docmd-io/docmd'); // → { href: 'https://github.com/docmd-io/docmd', isExternal: true, isRaw: false } resolveHref('raw:docs/readme.md'); // → { href: 'docs/readme.md', isExternal: false, isRaw: true } ``` ### Pre-computed Page URLs Every page object includes pre-computed URL data. Plugins can read these directly - zero computation needed. ```javascript export async function onPostBuild({ pages, config }) { for (const page of pages) { console.log(page.urls.slug); // "guide/" console.log(page.urls.canonical); // "https://example.com/guide/" console.log(page.urls.pathname); // "/guide/" } } ``` | Property | Type | Description | |:---------|:-----|:------------| | `slug` | `string` | Clean directory-style slug (e.g., `guide/` or `/`) | | `canonical` | `string` | Full canonical URL (only if `config.url` is set) | | `pathname` | `string` | Root-relative path (e.g., `/guide/`) | > **Backward Compatibility:** All exports from `@docmd/api` are also re-exported from `@docmd/core`, so existing code continues to work without changes. New projects are encouraged to import directly from `@docmd/api`. ### `createActionDispatcher(hooks, options)` Creates a dispatcher that routes WebSocket RPC messages to plugin action/event handlers. ```javascript import { createActionDispatcher } from '@docmd/api'; const dispatcher = createActionDispatcher( { actions: myPlugin.actions, events: myPlugin.events }, { projectRoot: '/path/to/project', config, broadcast } ); const { result, reload } = await dispatcher.handleCall('my-action', payload); ``` ### `createSourceTools({ projectRoot })` Creates source editing utilities for markdown file manipulation. ```javascript import { createSourceTools } from '@docmd/api'; const source = createSourceTools({ projectRoot: '/path/to/project' }); // Get block information at a specific line range const block = await source.getBlockAt('docs/page.md', [10, 12]); // Wrap text with syntax markers await source.wrapText('docs/page.md', [10, 12], 'important', 0, '**', '**'); ``` ### `loadPlugins(config, options)` Loads, validates, and registers all plugins declared in the config. Returns the populated hooks registry. ```javascript import { loadPlugins, hooks } from '@docmd/api'; const registeredHooks = await loadPlugins(config, { resolvePaths: [__dirname] // Help resolve plugins in pnpm workspaces }); ``` ### Type Exports For TypeScript plugin authors, the following types are available: ```typescript import type { PluginModule, // Full plugin contract interface PluginDescriptor, // Plugin metadata (name, version, capabilities) PluginHooks, // Shape of the hook registry PageContext, // Context passed to build hooks (sourcePath, html, etc) Capability, // Hook category declaration (init, body, actions, etc) ActionContext, // Context passed to action/event handlers ActionHandler, // Signature for action handlers EventHandler, // Signature for event handlers SourceTools, // Source editing tools interface BlockInfo, // Block information returned by getBlockAt TextLocation, // Text location returned by findText } from '@docmd/api'; ``` --- ## [Comparison](https://docs.docmd.io/07/comparison/) --- title: "Comparison" description: "How docmd stacks up against Docusaurus, VitePress, MkDocs, Starlight, and Mintlify - real numbers, real features." --- You picked a documentation tool before. You'll pick one again. Here's what actually matters - and where docmd stands. ## Start writing in 3 seconds, not 30 minutes ::: tabs == tab "docmd" ```bash npx @docmd/core dev ``` Done. Your docs are live. No config files, no project scaffolding, no dependency maze. == tab "Docusaurus" ```bash npx create-docusaurus@latest my-site classic cd my-site npm install npm start ``` Four commands, a generated project with ~250MB in `node_modules`, and a `docusaurus.config.js` you'll need to edit before anything useful happens. == tab "VitePress" ```bash npx vitepress init ``` Asks you 5 questions, generates a config file, then you run `vitepress dev`. Clean - but still requires scaffolding. == tab "MkDocs" ```bash pip install mkdocs-material mkdocs new my-site && cd my-site mkdocs serve ``` Python ecosystem. You'll need `pip`, a virtual environment, and a `mkdocs.yml` before the first page renders. ::: ## The payload gap is real Your readers shouldn't download a React app just to read a paragraph. Here's what the browser actually receives on a 50-page site: | Generator | Total initial load | JS payload | CSS payload | |:----------|:------------------:|:----------:|:----------:| | **docmd** | **~18 KB** | ~12 KB | ~6 KB | | MkDocs Material | ~40 KB | ~25 KB | ~15 KB | | VitePress | ~50 KB | ~35 KB | ~15 KB | | Mintlify | ~120 KB | ~80 KB | ~40 KB | | Docusaurus | ~250 KB | ~200 KB | ~50 KB | ::: callout tip "Why this matters" Every 100 KB of JavaScript costs ~50ms of parse time on a mid-range phone. docmd's 12 KB JS means your docs load instantly, even on 3G. Docusaurus ships 16× more JavaScript for the same content. ::: ## Build speed Building the same 50-page site on an M1 MacBook Air: | Generator | Cold build | Hot rebuild (dev) | |:----------|:----------:|:-----------------:| | **docmd** | **~1.2s** | **~80ms** | | VitePress | ~2.5s | ~150ms | | MkDocs Material | ~3.0s | ~500ms | | Docusaurus | ~15s | ~2s | docmd rebuilds are fast enough that the page refreshes before you switch windows. ## i18n that actually works This is where most tools fall apart. You add 6 languages, translate 3 pages in Hindi, and suddenly your users hit 404s on every untranslated page. | Capability | docmd | VitePress | Docusaurus | Starlight | |:-----------|:-----:|:---------:|:----------:|:---------:| | Per-page fallback to default locale | ✅ | ❌ (404) | ❌ (404) | ✅ | | Localised "not translated" warning | ✅ | ❌ | ❌ | ✅ | | Auto-disable missing locales in switcher | ✅ | ❌ | ❌ | ❌ | | Instant page-existence check (no network) | ✅ | ❌ | ❌ | ❌ | | Versioning + i18n combined | ✅ | ❌ | ❌ | ❌ | | Zero-config (no custom React/Vue) | ✅ | Partial | ❌ | ✅ | ::: callout warning "What happens in VitePress and Docusaurus" If a reader switches to Hindi and that page isn't translated, they get a **404 error**. The only workaround is server-side redirects or writing a custom React/Vue component. docmd handles this at build time - unavailable locales show an "N/A" badge, and untranslated pages fall back silently with a localised warning callout. ::: ## Multi-project Organisations maintaining multiple tools under one domain need separate docs for each - different versions, different navigation, different release cycles. Most generators force you to either maintain separate sites or hack around plugin systems. | Capability | docmd | Docusaurus | VitePress | MkDocs | Starlight | |:-----------|:-----:|:----------:|:---------:|:------:|:---------:| | Native multi-project support | ✅ | Plugin | ❌ | Plugin | ❌ | | Single config line per project | ✅ | ❌ | ❌ | ❌ | ❌ | | Independent versioning per project | ✅ | ✅ | ❌ | ❌ | ❌ | | Independent i18n per project | ✅ | ❌ | ❌ | ❌ | ❌ | | Shared assets across projects | ✅ | ❌ | ❌ | ❌ | ❌ | | Single `site/` output (no proxy needed) | ✅ | ❌ | ❌ | ❌ | ❌ | | Zero-config detection | ✅ | ❌ | ❌ | ❌ | ❌ | ::: callout info "How docmd does it" ```javascript // That's the entire root config. module.exports = defineConfig({ projects: [ { prefix: '/', src: 'main-docs' }, { prefix: '/sdk', src: 'sdk-docs' } ] }); ``` Each project folder has its own `docmd.config.js` with independent configuration. One `docmd build` produces a single deployable directory - no reverse proxy, no nginx, no separate CI pipelines. ::: Docusaurus achieves something similar with multi-instance plugins, but requires complex configuration - each instance needs separate plugin entries, sidebar files, and manual route configuration. MkDocs requires the third-party `mkdocs-monorepo-plugin`. VitePress, Starlight, and Mintlify have no native multi-project support. ## Full feature matrix | Feature | docmd | Docusaurus | VitePress | MkDocs Material | Starlight | Mintlify | |:--------|:-----:|:----------:|:---------:|:---------------:|:---------:|:--------:| | **Zero-config start** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Config required** | None | `docusaurus.config.js` | `config.mts` | `mkdocs.yml` | `astro.config.mjs` | `mint.json` | | **Multi-project** | ✅ | Plugin | ❌ | Plugin | ❌ | ❌ | | **SPA navigation** | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | | **Native versioning** | ✅ | ✅ | ❌ | Plugin | ❌ | ✅ | | **Native i18n** | ✅ | ✅ | Manual | Plugin | ✅ | ✅ | | **Built-in search** | ✅ | ❌ (Algolia) | ✅ | ✅ | ✅ | Cloud | | **llms.txt** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Inline discussions** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **PWA support** | ✅ | Community | ❌ | ❌ | ❌ | ❌ | | **Self-hosted** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | **Deploy config generator** | ✅ | ❌ | ❌ | ❌ | ❌ | N/A | ## Configuration overhead Lines of config required for a site with versioning, i18n, search, and sitemap: | Generator | Config lines | Files required | |:----------|:------------:|:--------------:| | **docmd** | **~15 lines** | 1 (`docmd.config.js`) | | MkDocs Material | ~50 lines | 1 + plugins | | VitePress | ~80 lines | 1 + theme dir | | Docusaurus | ~120 lines | 3+ config files | ## Quality assurance docmd ships with a brute test suite that validates **25 distinct scenarios** across **85 assertions** - covering every feature in isolation and in combination. Every release must pass all 85 assertions and 13 internal failsafe checks before shipping. ::: callout tip "Run the tests yourself" ```bash git clone https://github.com/docmd-io/docmd.git cd docmd && node scripts/brute-test.js ``` ::: No other documentation generator in this class publishes a comparable end-to-end feature test suite as part of its source. --- ## [Layout & UI Zones](https://docs.docmd.io/07/configuration/layout-ui/) --- title: "Layout & UI Zones" description: "Control the interface structure by managing headers, sidebars, and functional UI slots." --- A standard `docmd` page is divided into six primary functional zones: 1. **Menubar**: A full-width top navigation bar for global site links. 2. **Header**: The persistent secondary bar containing the page title and utility buttons. 3. **Sidebar**: The primary navigation tree (usually on the left). 4. **Content Area**: The central Markdown rendering zone, including **Breadcrumbs**. 5. **Table of Contents (TOC)**: Right-hand heading navigation for the current page. 6. **Footer**: Bottom area for copyright, branding, and site-wide links. ## Global Component Configuration `docmd` features a modular layout system. Most UI zones are configured within the `layout` section of your `docmd.config.js`. ### Menubar The menubar provides a high-level navigation layer above your documentation. It supports brand titles, regular links, and nested dropdowns. * **Location**: Fixed at the `top` or inline within the `header`. * **Documentation**: See [Menubar Configuration](menubar.md) for full item schemas and styling. ### The Page Header The header contains the page title, breadcrumbs, and usually the utility menus. * **Controls**: Enable/disable the header or breadcrumbs site-wide via `layout.header` and `layout.breadcrumbs`. * **Overriding**: Use `hideTitle: true` in your [Page Frontmatter](../content/frontmatter.md) to hide the title area on specific pages. ### Utility Menus (Options Menu) The `optionsMenu` consolidates core utilities like **Global Search**, **Theme Toggle**, and **Sponsorship links**. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom', 'menubar' components: { search: true, // Enable full-text search themeSwitch: true, // Enable Light/Dark mode toggle sponsor: 'https://github.com/sponsors/your-profile' } } } ``` ::: callout info "Automatic Fallback" If the chosen position targets a container that is disabled, `docmd` will automatically render the options menu in the `sidebar-top` slot to ensure core utilities remain accessible. ::: ### Sidebar & Navigation The sidebar is the primary navigation tree for your site. Its structure is defined either in your config or via external JSON files. * **Behaviour**: Supports animations, collapsible groups, and automatic path preservation. * **Documentation**: See [Navigation Configuration](navigation.md) for structuring your sidebar tree. ### Footer `docmd` provides both **minimal** and **complete** layouts for your site footer. ```javascript layout: { footer: { style: 'complete', // Options: 'minimal' or 'complete' description: 'Documentation built with docmd.', branding: true, // Controls the "Built with docmd" badge columns: [ { title: 'Community', links: [ { text: 'GitHub', url: 'https://github.com/docmd-io/docmd' } ] } ] } } ``` ::: callout tip "Interface Hierarchy" For the best user experience, keep your **Menubar** for global external links and your **Sidebar** for logical documentation structure. AI agents frequently utilise this hierarchy to understand the relationship between different documentation modules. ::: --- ## [Localisation](https://docs.docmd.io/07/configuration/localisation/) --- title: "Localisation" description: "Serve documentation in multiple languages with locale-first routing, translated navigation, and automatic fallback." --- Add multi-language support to your documentation site. docmd serves each locale at its own URL prefix, translates system UI strings, and falls back gracefully when a translation is missing. ## Add languages to your config ```js // docmd.config.js export default { i18n: { default: 'en', locales: [ { id: 'en', label: 'English' }, { id: 'hi', label: 'हिन्दी' }, { id: 'zh', label: '中文' } ] } } ``` The `default` locale renders at the site root (`/`). All other locales render at `/{id}/`. You choose the IDs, labels, and which locale is the default - there are no hardcoded assumptions. If you want Hindi as the default, set `default: 'hi'` and Hindi renders at `/` whilst English renders at `/en/`. | Key | Type | Description | |:----|:-----|:------------| | `default` | `string` | Locale ID that renders at `/`. Defaults to the first locale if omitted. | | `locales` | `array` | List of locale objects. Each must have an `id`. | | `position` | `string` | Where the language switcher appears. `options-menu` (default), `sidebar-top`, or `sidebar-bottom`. | | `stringMode` | `boolean` | When `true`, generates locale pages from a single source using `data-i18n` attribute replacement. Default `false`. | | `inPlace` | `boolean` | When `true` (with client-side script), swaps strings without URL navigation. For SPAs/dashboards only. Default `false`. | Each locale object accepts: | Key | Type | Default | Description | |:----|:-----|:--------|:------------| | `id` | `string` | - | Any identifier you choose (e.g. `en`, `hi`, `fr-ca`). Used as the folder name and URL prefix. Required. | | `label` | `string` | Same as `id` | Display name shown in the language switcher. | | `dir` | `string` | `ltr` | Text direction. Set to `rtl` for Arabic, Hebrew, etc. | | `translations` | `object` | `{}` | Custom UI string overrides (see [Custom UI strings](ui-strings.md)). | ## URL structure The default locale has no URL prefix. Non-default locales are nested under `/{id}/`. When combined with [versioning](../versioning.md), the URL is `/{locale}/{version}/page`. ``` / ← default locale, current version /getting-started ← default locale page /05/ ← default locale, old version /hi/ ← non-default locale, current version /hi/getting-started ← non-default locale page /hi/05/ ← non-default locale, old version ``` The language switcher preserves your current page and version when you switch locales. The version switcher preserves your current locale. ## Missing locale directories If a locale is declared in `locales` but its source directory does not exist (e.g. no `docs/hi/` folder), docmd automatically **disables** that locale in the language switcher. The locale still appears in the dropdown - with an "N/A" badge and greyed-out styling - but clicking it does nothing. This prevents 404 errors when you list planned languages before their content is ready. ## Position the language switcher Control where the language switcher appears using the `position` option: ```js i18n: { position: 'options-menu', // default // ... } ``` | Position | Behaviour | |:---------|:----------| | `options-menu` | Compact globe icon alongside theme toggle and search. Default. | | `sidebar-top` | Full dropdown with label at the top of the sidebar. | | `sidebar-bottom` | Full dropdown with label at the bottom of the sidebar. | ## String Mode (noStyle pages only) Standard i18n uses separate directories per locale (`docs/en/`, `docs/hi/`), each with its own markdown files. **String Mode** is a simpler alternative designed specifically for [noStyle pages](../../content/no-style-pages.md) - pages that use raw HTML instead of markdown. ```js // docmd.config.js export default { i18n: { default: 'en', stringMode: true, locales: [ { id: 'en', label: 'English' }, { id: 'zh', label: '中文' } ] } } ``` With `stringMode: true`: 1. Source files stay in the root `docs/` directory (no locale subdirectories) 2. The default locale builds at `/` as normal 3. For each non-default locale, docmd clones the rendered HTML and applies **server-side string replacement** using JSON files from `assets/i18n/{locale}.json` 4. Output goes to `/{locale}/` - e.g. `/zh/index.html` - with full SEO (hreflang tags, correct `lang` attribute) 5. If a translation file is missing, the page renders with the default language text For full details on the `data-i18n` attribute syntax and JSON file format, see [noStyle string replacement](../../content/no-style-pages.md#string-replacement-i18n-for-nostyle). ::: callout warning "String Mode does not translate markdown content" String replacement works by finding `data-i18n` attributes in the rendered HTML. Standard markdown content (`## Heading`, paragraphs, lists) renders to plain HTML tags without these attributes - so there is nothing for the replacer to find. - **Documentation sites** → use directory mode (the default). Each locale has its own markdown files with fully translated prose. - **Landing pages, marketing sites, dashboards** → use string mode. These are noStyle pages with custom HTML where you control every tag and can add `data-i18n` attributes. If your site has both - for example, a noStyle landing page plus documentation - use directory mode for the docs and add `data-i18n` attributes to your noStyle page. String mode will translate the noStyle HTML while directory mode handles the documentation content. ::: ## Next steps - [Translated content](translated-content.md) - directory structure, writing translations, navigation - [UI strings & SEO](ui-strings.md) - customising system text, hreflang tags - [noStyle string replacement](../../content/no-style-pages.md#string-replacement-i18n-for-nostyle) - `data-i18n` attribute syntax and JSON format for noStyle pages --- ## [Translated Content](https://docs.docmd.io/07/configuration/localisation/translated-content/) --- title: "Translated Content" description: "Organise translations in locale subdirectories with per-file fallback and per-locale navigation." --- ## Directory structure Every locale - including the default - lives in its own subdirectory inside the source directory. The folder name matches the locale `id` from your config. ``` docs/ ├── en/ ← default locale content │ ├── index.md │ ├── navigation.json │ └── getting-started/ │ └── installation.md ├── hi/ ← second locale │ ├── index.md ← translated homepage │ ├── navigation.json ← translated navigation labels │ └── getting-started/ │ └── installation.md ← translated page └── zh/ ← third locale └── index.md ← only the homepage translated ``` The source directory is a clean container - it holds only locale folders. No content files sit at the root level when i18n is enabled. ::: callout info "Folder names are your choice" The folder names come directly from the `id` values in your config. If your config says `{ id: 'fr-ca' }`, your folder is `docs/fr-ca/`. If Hindi is your default locale (`default: 'hi'`), then `docs/hi/` is the canonical content directory. ::: ## Per-file fallback You don't need to translate every page. docmd scans the **default locale's directory** as the canonical list of pages. For every other locale, it checks whether a translated version of each page exists: - If `docs/hi/getting-started/installation.md` exists → serves the Hindi translation - If it doesn't exist → serves the default locale's version of that page When a page falls back, docmd can display a translated callout informing viewers that the page is shown in the default language. This message is customisable via your [UI strings](ui-strings.md) configuration. ## Locale-exclusive pages A non-default locale can also have pages that don't exist in the default locale. These are rendered only for that locale - they don't appear in other locales. ## Translate the navigation Each locale directory can have its own `navigation.json`. `docmd` uses a cascading priority system (Level 1-3) to resolve the sidebar. For details on the resolution hierarchy and visual examples, see [Navigation Resolution Priority](../navigation.md#navigation-resolution-priority). A locale's `navigation.json` uses the same format: ```json [ { "title": "शुरू करें", "children": [ { "title": "इंस्टालेशन", "path": "/getting-started/installation" }, { "title": "स्थानीयकरण", "path": "/configuration/localisation" } ] } ] ``` ::: callout tip "Partial navigation" You only need to create a locale `navigation.json` when you want translated labels. If it's missing, the default locale's navigation is used - pages still render, just with untranslated labels. ::: ## Versioning and i18n together When both versioning and i18n are configured, the source structure is: ``` docs/ ← current version (container) en/ ← current version, default locale hi/ ← current version, translated locale docs-v1/ ← old version index.md ← old version content (no locale structure) navigation.json ``` Old versions that predate i18n work automatically - docmd reads them directly when no locale subdirectories are present. Only the default locale renders the old version. To add translations to an old version, create a locale subdirectory inside it: ``` docs-v1/ hi/ ← Hindi translation for v1 index.md navigation.json ``` The output URLs nest locale first, then version: ``` / ← default locale, current version /hi/ ← translated locale, current version /v1/ ← default locale, old version /hi/v1/ ← translated locale, old version ``` --- ## [UI Strings & SEO](https://docs.docmd.io/07/configuration/localisation/ui-strings/) --- title: "UI Strings & SEO" description: "Customise system UI text per locale and understand automatic SEO tags for multi-language sites." --- ## Built-in language support docmd and its official plugins (Search, Threads, etc.) ship with built-in translations for common languages. When you configure a supported locale, all system text - search placeholders, navigation labels, theme toggles - is automatically translated. For unsupported languages or custom phrasing, the system falls back to English. You can override any string per locale. ## Custom UI strings Use the `translations` property on any locale to override system text: ```js export default { i18n: { default: 'en', locales: [ { id: 'en', label: 'English' }, { id: 'ar', label: 'العربية', dir: 'rtl', translations: { onThisPage: 'في هذه الصفحة', previous: 'السابق', next: 'التالي', search: 'بحث', toggleTheme: 'تبديل المظهر', editThisPage: 'تعديل هذه الصفحة', selectLanguage: 'اختر اللغة', selectVersion: 'اختر الإصدار', fallbackMessage: 'هذه الصفحة غير متاحة بعد باللغة {active}. عرض اللغة الافتراضية ({default}).' } } ] } } ``` The merge order is: **system translations → plugin translations → your config translations**. Your config always wins. ## Available keys | Key | Default (English) | |:----|:-------------------| | `skipToContent` | Skip to main content | | `toggleSidebar` | Toggle Sidebar | | `previous` | Previous | | `next` | Next | | `onThisPage` | On This Page | | `search` | Search | | `toggleTheme` | Toggle theme | | `selectLanguage` | Select Language | | `selectVersion` | Select Version | | `editThisPage` | Edit this page | | `builtWith` | Built with | | `copyCode` | Copy code | | `copiedToClipboard` | Copied! | | `mainNavigation` | Main Navigation | | `fallbackMessage` | This page is not yet available in {active}. Showing default language ({default}). | The `fallbackMessage` key supports `{active}` and `{default}` placeholders, replaced with locale labels at build time. ## SEO and hreflang docmd automatically generates `<link rel="alternate" hreflang="...">` tags for every page across all locales. The default locale also receives the `x-default` hreflang value. ```html <!-- Generated automatically on every page --> <link rel="alternate" hreflang="en" href="/"> <link rel="alternate" hreflang="x-default" href="/"> <link rel="alternate" hreflang="hi" href="/hi/"> <link rel="alternate" hreflang="zh" href="/zh/"> ``` No configuration is required - these tags are injected into every page when i18n is enabled. ::: callout info "noStyle Pages" The UI strings system described above applies to themed layout pages (server-side). For noStyle pages that use custom HTML, see the [client-side string replacement](../../content/no-style-pages/#string-replacement-i18n-for-nostyle) system which uses `data-i18n` attributes and JSON files in `assets/i18n/`. ::: --- ## [Menubar](https://docs.docmd.io/07/configuration/menubar/) --- title: "Menubar" description: "Structure and position your menubar, manage navigation links, and configure drop-down menus." --- The `menubar` is a premium navigation layer that provides global context across your documentation site. It can be positioned as a fixed bar at the top of the viewport or as a relative component above the page header. ## Configuration The menubar is configured within the `layout` section of your `docmd.config.js`. ```javascript export default defineConfig({ layout: { menubar: { enabled: true, position: 'top', // 'top' (fixed) or 'header' (inline) left: [ { type: 'title', text: 'Brand', url: '/', icon: 'home' }, { text: 'Documentation', url: '/docs' }, { type: 'dropdown', text: 'Ecosystem', items: [ { text: 'GitHub', url: 'https://github.com/docmd-io/docmd', external: true }, { text: 'Live Editor', url: 'https://live.docmd.io' } ] } ], right: [ { text: 'Support', url: '/support', icon: 'help-circle' } ] } } }); ``` ### Options | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `Boolean` | `false` | Toggles the visibility of the menubar. | | `position` | `String` | `'top'` | `'top'` (fixed at absolute top) or `'header'` (positioned above the page title). | | `left` | `Array` | `[]` | Navigation items aligned to the left section. | | `right` | `Array` | `[]` | Navigation items aligned to the right section. | ## Item Types The `left` and `right` arrays support various item types to structure your navigation effectively: ### 1. Standard Link The most common item type. - `text`: Display label. - `url`: Path or external URL. - `icon`: Optional Lucide icon name. - `external`: Set to `true` to open in a new tab. ### 2. Title (Brand) Set `type: 'title'` to apply branding styles (usually bold or with a specific font weight) to the link. ### 3. Dropdown Menu Set `type: 'dropdown'` and provide an `items` array to create a nested menu. ## Utility Integration You can host the global search and theme toggle within the menubar by setting the `optionsMenu.position` to `'menubar'`. ```javascript layout: { optionsMenu: { position: 'menubar' } } ``` When integrated, the options menu will automatically align to the **right region** of the menubar, appearing after any links defined in the `right` array. ::: callout info If the `menubar` is disabled, any utility components assigned to it will automatically fall back to the `sidebar-top` position. ::: ## Custom Styling You can fine-tune the menubar's appearance using CSS variables in your `customCss` files: ```css :root { --menubar-height: 56px; --menubar-bg: var(--docmd-bg-secondary); --menubar-border: var(--docmd-border-colour); --menubar-text: var(--docmd-text-primary); } ``` --- ## [Multi-Project Configuration](https://docs.docmd.io/07/configuration/multi-project/) --- title: "Multi-Project Configuration" description: "Build multiple independent documentation sites from a single docmd instance. Shared assets, independent versioning, one deployment." --- Build and deploy multiple documentation projects from a single repository. Each project maintains its own configuration, versioning, and navigation while sharing a common theme and asset pipeline. ## Overview Multi-project mode is designed for organisations that maintain multiple tools, libraries, or products under one domain. Instead of running separate docmd instances behind a reverse proxy, a single `docmd build` produces a unified `site/` directory. ``` docs.example.com/ → Main documentation docs.example.com/sdk/ → SDK reference docs.example.com/cli/ → CLI documentation ``` ## Setup ### 1. Directory Structure Organise your repository with one directory per project: ``` my-docs/ ├── assets/ ← shared assets (all projects) ├── main-docs/ │ ├── docmd.config.js ← project config │ └── v01/ ← versioned content │ └── en/ ├── sdk-docs/ │ ├── docmd.config.js ← project config │ └── docs/ ← unversioned content ├── docmd.config.js ← root multi-project config └── package.json ``` ### 2. Root Configuration The root `docmd.config.js` contains **only** the `projects` array: ```javascript module.exports = defineConfig({ projects: [ { prefix: '/', src: 'main-docs' }, { prefix: '/sdk', src: 'sdk-docs' } ] }); ``` | Key | Description | | :-- | :---------- | | `prefix` | URL prefix for this project. Use `'/'` for the root project. | | `src` | Directory containing this project's `docmd.config.js` and content. | ::: callout warning Every multi-project configuration **must** include a root project with `prefix: '/'`. ::: ### 3. Project Configurations Each project directory has its own `docmd.config.js` with full independent configuration. Do **not** include `src` or `out` keys - the parent config provides those automatically. Each project can have completely independent: - **i18n** - different locales, different default languages - **Versioning** - different version numbers and structures - **Plugins** - enable only what each project needs - **Navigation** - custom sidebar for each project ## Assets ### Shared Assets Place shared resources (logos, favicons, global CSS) in the root `assets/` directory. These are copied into every project's output automatically. ### Project-Specific Assets Each project can have its own `assets/` directory. Project assets take priority over shared assets when filenames overlap. ``` my-docs/ ├── assets/ │ └── images/ │ └── logo.png ← used by all projects ├── sdk-docs/ │ └── assets/ │ └── images/ │ └── logo.png ← overrides shared logo for SDK only ``` ## Development Start the multi-project dev server: ```bash docmd dev ``` The server builds all projects and serves them from a single port: ``` ┌─ DEV SERVER │ │ Local http://127.0.0.1:3000 │ Network http://192.168.1.5:3000 │ │ Project http://127.0.0.1:3000/ │ Project http://127.0.0.1:3000/sdk └────────────────────────────────────────────────────────── ``` File changes in any project trigger a targeted rebuild with live reload. Only the affected project rebuilds - other projects remain untouched for fast iteration. Shared asset changes rebuild all projects. ## Building & Deployment ```bash docmd build ``` Output is a single static directory: ``` site/ ├── index.html ← main-docs root ├── sdk/ │ └── index.html ← sdk-docs root ├── assets/ ← merged assets ├── 404.html └── sitemap.xml ``` Deploy to any static hosting (GitHub Pages, Netlify, Vercel, Cloudflare Pages) with no additional configuration. No nginx or proxy rules needed. ## Rules & Constraints 1. **Root project required** - one project must have `prefix: '/'` 2. **No duplicate prefixes** - each project needs a unique URL prefix 3. **No `src`/`out` in children** - the parent config provides these 4. **Independent everything** - each project has its own title, versions, i18n, plugins, and navigation 5. **Root config is minimal** - only `projects` should be in the root `docmd.config.js` ## Example The official docmd documentation uses multi-project to serve the main docs and semantic search docs from one domain: ```javascript // Root docmd.config.js module.exports = defineConfig({ projects: [ { prefix: '/', src: 'docmd-main' }, { prefix: '/search', src: 'docmd-search' } ] }); ``` Check the [documentation repo](external:https://github.com/docmd-io/docs). This produces: - `docs.docmd.io/` - main docmd documentation (versioned, multilingual) - `docs.docmd.io/search/` - docmd search documentation (independent versioning) Each project has its own: - `docmd.config.js` with different title, URL, and plugins - Version structure (main has v0.5-v0.7, search has its own versioning) - Navigation and sidebar configuration --- ## [Navigation Configuration](https://docs.docmd.io/07/configuration/navigation/) --- title: "Navigation Configuration" description: "Structure your sidebar, categorise links, and assign icons for human readers and LLMs." --- `docmd` provides explicit control over your site's structure. By defining your `navigation` in `docmd.config.js`, you create a logical hierarchy that optimises the Single Page Application (SPA) experience and provides a clear context map for AI models and search engines. ## The Navigation Array <img width="260" class="with-border" src="/assets/previews/navigation-hierarchy.webp"> Each object in the array defines a **Link** or a **Category Group**. ```javascript export default defineConfig({ navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Installation', path: '/getting-started/installation', icon: 'download' } ] }); ``` ## Available Properties | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | | **`title`** | `String` | Yes | The display text for the link or category. | | **`path`** | `String` | No | Destination URL. Must start with `/` for local paths. | | **`icon`** | `String` | No | Name of a [Lucide Icon](external:https://lucide.dev/icons) (e.g., `rocket`). | | **`children`** | `Array` | No | Nested items used to create a submenu or group. | | **`collapsible`**| `Boolean` | No | If `true`, the group can be expanded/collapsed by the user. | | **`external`** | `Boolean` | No | If `true`, the link opens in a new browser tab. | ## Organising Groups You can nest navigation items to create deep hierarchies. There are two primary ways to organise groups: ### 1. Clickable Group (Directory with Index) If the parent has a `path`, clicking the label navigates to that page and automatically expands the children in the sidebar. ```javascript { title: 'Cloud Setup', path: '/cloud/overview', children: [ { title: 'AWS', path: '/cloud/aws' }, { title: 'GCP', path: '/cloud/gcp' } ] } ``` ### 2. Static Label (Category Header) If you **omit the `path`**, the item becomes a static category header. This is the recommended approach for grouping related technical sections that don't share a common landing page. ```javascript { title: 'Content & Formatting', icon: 'layout', children: [ { title: 'Syntax Guide', path: '/content/syntax' }, { title: 'Containers', path: '/content/containers' } ] } ``` ## Automated Breadcrumbs <img width="500" class="with-border" src="/assets/previews/navigation-breadcrumb.webp"> `docmd` automatically generates breadcrumbs for every page based on your navigation hierarchy. These crumbs are rendered above the main page title to improve orientation and navigation speed. ### Behaviour * **Auto-Resolution**: The engine traces the path through your `navigation` tree to identify the current page's ancestors. * **Active State**: The current page is listed as the final, non-linked crumb. * **Mobile Support**: Breadcrumbs are intelligently adjusted or hidden on smaller screens to preserve header space. ### Disabling Breadcrumbs Breadcrumbs are enabled by default. To disable them site-wide, update your `docmd.config.js`: ```javascript layout: { breadcrumbs: false } ``` ## Navigation Resolution Priority `docmd` provides a flexible cascading resolution system. This allows you to maintain a central navigation config while overriding specific parts for different languages or versions. The resolution follows a "closest file wins" logic based on folder nesting. The hierarchy is as follows (from highest priority to lowest): ```text my-project/ ├── docmd.config.js [Level 3: Global Config] - Lowest Priority ├── docs-v1/ │ ├── navigation.json [Level 2: Version Navigation] - Medium Priority │ └── zh/ │ └── navigation.json [Level 1: Language Navigation] - Highest Priority ``` 1. **Level 1: Language-Specific** (`docs-v1/zh/navigation.json`): Overrides everything for the specific locale and version. 2. **Level 2: Version-Specific** (`docs-v1/navigation.json`): Overrides the global config for all languages in this version. 3. **Level 3: Global Configuration** (`config.navigation`): The final fallback defined in your root config file. ### Smart Broken-Link Filtering Even when falling back to a parent configuration (Level 2 or 3), `docmd` automatically filters out sidebar items that link to files not present in the current version's source folder. This guarantees no broken links when users select an older version. ### JSON Structure Each `navigation.json` must follow the standard array structure: ```json [ { "title": "Home", "path": "/" }, { "title": "Release Notes", "path": "/release-notes" } ] ``` ## Icons Integration `docmd` comes pre-bundled with the entire **Lucide** icon library. Simply use the icon name in kebab-case (e.g., `brain-circuit`, `terminal`, `settings`). ::: callout tip Use descriptive `title` keys even if the page content starts with a header. Clear, consistent navigation titles allow AI agents (using `llms-full.txt`) to build an accurate mental map of your project structure effortlessly. ::: --- ## [General Configuration](https://docs.docmd.io/07/configuration/overview/) --- title: "General Configuration" description: "Configure docmd.config.js schema, branding, layout, and engine features." --- The `docmd.config.js` file serves as the definitive configuration for your documentation project. It controls site structure, branding, UI behaviour, and engine-level processing rules. ## The Configuration File We recommend using the `defineConfig` helper provided by `@docmd/core`. This provides full IDE autocomplete and type-checking, enabling effortless discovery of available settings. ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ title: 'My Project', url: 'https://docs.myproject.com', // ... configuration settings }); ``` ## Core Settings `docmd` utilises a simple configuration schema. Below are the primary top-level settings: | Key | Description | Default | | :--- | :--- | :--- | | `title` | The name of your documentation site. Used in the header and browser titles. | `Documentation` | | `url` | Your production base URL. Critical for SEO, Sitemaps, and OpenGraph. | `null` | | `src` | The relative path to the directory containing your Markdown files. | `docs` | | `out` | The relative path for the generated static site output. | `site` | | `base` | The base path if hosting in a subfolder (e.g., `/docs/`). | `/` | | `i18n` | Configuration for [multi-language support](localisation/index.md). | `null` | | `plugins` | Configuration for any standard or custom [plugins](../plugins/usage.md). | `{}` | ## Branding & Identity Configure how your brand is represented in the navigation header and browser tabs. ```javascript logo: { light: 'assets/images/logo-dark.png', // Logo shown in Light Mode dark: 'assets/images/logo-light.png', // Logo shown in Dark Mode href: '/', // Link destination when clicking the logo alt: 'Company Logo', // Alternative text for accessibility height: '32px' // Optional: Explicit height for the logo }, favicon: 'assets/favicon.ico', // Path to your site's favicon ``` ## Site Layout & UI `docmd` features a modular layout system. You can toggle UI components like the **Sidebar**, **Header**, **Menubar**, and **Global Search** via the `layout` object. For a full breakdown of functional zones and configuration options, see [Layout & UI Zones](layout-ui.md). ## Core Engine Features Fine-tune how `docmd` processes and renders your documentation content. ```javascript minify: true, // Minifies production assets (CSS/JS) for better performance autoTitleFromH1: true, // Uses the first H1 heading as the page title if frontmatter 'title' is missing copyCode: true, // Adds a 'Copy' button to all code blocks automatically pageNavigation: true, // Adds 'Previous' and 'Next' navigation links at the bottom of pages ``` ## Legacy Support If you are upgrading from an older version of `docmd`, the following keys are automatically mapped to the modern schema for backward compatibility: * `siteTitle` → `title` * `siteUrl` / `baseUrl` → `url` * `srcDir` / `source` → `src` * `outDir` / `outputDir` → `out` ::: callout tip Execute `docmd migrate` to automatically upgrade your configuration file to the latest schema while preserving a backup of your original settings. ::: ::: callout warning "Deprecated: editLink" The standalone `editLink` configuration option has been deprecated in favour of the [Git plugin](../plugins/git.md). The Git plugin provides the same edit link functionality plus additional features like last-updated timestamps and commit history tooltips. See the [migration guide](../plugins/git.md#migration-from-editlink) for details. ::: --- ## [Redirects & 404](https://docs.docmd.io/07/configuration/redirects/) --- title: "Redirects & 404" description: "Configure metadata-based redirects and custom branded 404 error pages for static deployments." --- In a static hosting environment, there is no server-side logic (such as Nginx rules or `.htaccess` files) to handle dynamic routing. `docmd` addresses this by generating native HTML failsafes that handle redirection and error states automatically. ## Server-less Redirects You can forward traffic from legacy URLs to new destinations by defining a mapping in the `redirects` object. ```javascript export default defineConfig({ redirects: { '/setup': '/getting-started/installation', // Short URL to deep link '/v1/api': '/api-reference' // Legacy version to modern path } }); ``` ### Technical Implementation When a redirect is defined, `docmd` creates an `index.html` file at the legacy path containing a `<meta http-equiv="refresh">` tag. This strategy ensures: 1. **Seamless Redirection**: Users are forwarded to the new destination instantly after the page loads. 2. **SEO Preservation**: Search engines recognise the redirection, helping to maintain link equity. 3. **Analytics Tracking**: Page views are captured before the redirect occurs, preserving your traffic data. ## Branded 404 Pages When a user attempts to access a non-existent URL, most static hosting providers (Netlify, Vercel, GitHub Pages) automatically look for a `404.html` file in the root directory. `docmd` generates this file by default, ensuring it inherits your site's theme, sidebar, and SPA functionality. ### Customising Error Content You can personalise the 404 error message within your configuration: ```javascript export default defineConfig({ notFound: { title: '404: Page Not Found', content: "We couldn't find the page you're looking for. Use the sidebar to find your way back." } }); ``` ::: callout tip "Local Development" The `docmd dev` server automatically serves your custom 404 page whenever a requested file is missing, allowing you to test the error experience locally. ::: --- ## [Versioning](https://docs.docmd.io/07/configuration/versioning/) --- title: "Versioning" description: "Enable multi-version documentation with seamless switching, sticky path preservation, and isolated build directories." --- `docmd` features a native Versioning Engine that allows you to manage and serve multiple versions of your project simultaneously (e.g., `v1.x`, `v2.x`). The engine automatically handles URL routing, sidebar updates, and switching logic. ## Directory Organisation To enable versioning, organise your documentation into versioned source folders. A common pattern is keeping the active version in `docs/` and archived versions in directories prefixed with `docs-`. ```text my-project/ ├── docs/ # Latest Version (Main) ├── docs-v1/ # Legacy Version ├── docmd.config.js ``` ## Configuration Define your versions within the `versions` object: ```javascript export default defineConfig({ versions: { current: 'v2', // The version ID built to the root (/) position: 'sidebar-top', // Switcher location: 'sidebar-top' or 'sidebar-bottom' all: [ { id: 'v2', dir: 'docs', label: 'v2.x (Latest)' }, { id: 'v1', dir: 'docs-v1', label: 'v1.x' } ] } }); ``` ## Core Features ### 1. Root SEO (The "Current" Version) The version designated as `current` is generated directly at your output root (e.g., `mysite.com/`). This ensures your primary search traffic always lands on your most up-to-date documentation. ### 2. Isolated Sub-directories Non-current versions are automatically built into subfolders matching their `id`. * `v2 (Current)` → `mysite.com/` * `v1` → `mysite.com/v1/` ### 3. Sticky Switching (Path Preservation) `docmd` preserves the relative path when a user switches versions. If a user is reading `mysite.com/getting-started` and switches to **v1**, they are automatically redirected to `mysite.com/v1/getting-started` (if the page exists) rather than being returned to the home page. ### 4. Asset Isolation Each version inherits your global `assets/` directory, but `docmd` ensures they are isolated during the build process to prevent style leakage or version conflicts. ### 5. Versioned Navigation Each version can maintain its own independent navigation structure. `docmd` uses a cascading priority system to resolve the sidebar, allowing you to use a centralised config or per-version/per-language `navigation.json` files. For details on the resolution hierarchy and visual examples, see [Navigation Resolution Priority](navigation.md#navigation-resolution-priority). ## Best Practices 1. **Semantic IDs**: Use concise, URL-friendly IDs like `v1`, `v2`, or `beta`. 2. **Navigation Parity**: Maintain consistent folder structures across versions to maximise the effectiveness of "Sticky Switching." 3. **Unified Configuration**: You do not need separate config files for each version; `docmd` processes all versions in a single pass. --- ## [Buttons](https://docs.docmd.io/07/content/containers/buttons/) --- title: "Buttons" description: "Inject call-to-action buttons for internal routing or external resources with a single-line syntax." --- Buttons are high-impact UI elements used for prominent navigation. Unlike block containers, the `button` is **self-closing** - it is defined on a single line and does not require a closing `:::` tag. ## Syntax ```markdown ::: button "Label" Path [Options] ``` ### Options Reference | Property | Format | Description | | :--- | :--- | :--- | | **Path** | `/path/` | Relative project URL (resolves automatically for SPA navigation). | | **External** | `external:URL`| Opens the target URL in a new browser tab (`target="_blank"`). | | **Colour** | `color:VALUE` | Applies a background colour (supports CSS names or Hex codes). | | **Icon** | `icon:NAME` | Adds a [Lucide](external:https://lucide.dev/icons) icon before the button label. | ## Usage Examples ### 1. Internal Navigation Use relative paths to ensure seamless, zero-reload transitions within the `docmd` SPA. ```markdown ::: button "Install docmd" /getting-started/installation ``` ::: button "Install docmd" /getting-started/installation ### 2. External Resource Link Prepend `external:` to the URL to secure safe external linking. ```markdown ::: button "View GitHub Repository" external:https://github.com/docmd-io/docmd ``` ::: button "View GitHub Repository" external:https://github.com/docmd-io/docmd ### 3. Semantic & Brand Styling Match buttons to your brand identity or semantic priority using colour overrides. ```markdown ::: button "Danger Action" /delete color:crimson ::: button "Success Confirmation" /success color:#228B22 ``` ::: button "Danger Action" ./#delete color:crimson ::: button "Success Confirmation" ./#success color:#228B22 ### 4. Buttons with Icons Add a Lucide icon to enhance visual clarity. ```markdown ::: button "Get Started" /getting-started/installation icon:arrow-right ::: button "View Source" external:https://github.com/docmd-io/docmd icon:github ``` ::: button "Get Started" /getting-started/installation icon:arrow-right ::: button "View Source" external:https://github.com/docmd-io/docmd icon:github ## Critical Note: Self-Closing Logic Because buttons are self-closing, adding a terminal `:::` line will terminate the **parent container** (e.g., a Card or Tab) that the button resides in, potentially breaking your layout. **Incorrect Sequence:** ```markdown ::: card "Setup" ::: button "Begin" /setup ::: <-- Error: This closes the Card prematurely. ::: ``` **Correct Sequence:** ```markdown ::: card "Setup" ::: button "Begin" /setup ::: <-- Correct: This closes the Card. ``` --- ## [Callouts](https://docs.docmd.io/07/content/containers/callouts/) --- title: "Callouts" description: "Highlight critical warnings, pro-tips, and background context using semantic visual blocks." --- Callouts are used to isolate information that requires the reader's immediate attention. `docmd` provides five semantic types, each featuring distinct visual styling and themed iconography. ::: callout info "Migration-Friendly Aliases" If you're migrating from **VitePress** or **Docusaurus**, you can use their native syntax directly: - `:::tip`, `:::warning`, `:::danger`, `:::info` (VitePress) - `:::note`, `:::caution` (Docusaurus) These aliases render identically to their `docmd` equivalents. Spaceless syntax like `:::callout` also works. ::: ## Syntax Reference ```markdown ::: callout type "Optional Title" The technical content or warning goes here. ::: ``` Add an optional `icon:` parameter to override the default type icon with any [Lucide](external:https://lucide.dev/icons) icon: ```markdown ::: callout info "Custom Icon" icon:sparkles This callout uses a custom icon instead of the default info icon. ::: ``` ### Supported Semantic Types | Type | Intent | Visual Signal | | :--- | :--- | :--- | | `info` | **General Data** | Contextual background or helpful non-critical info. | | `tip` | **Optimisation** | Performance shortcuts or "Pro-tips". | | `warning`| **Cautionary** | Potential issues or deprecated features to monitor. | | `danger` | **Critical** | Risk of data loss, breaking changes, or system failure. | | `success`| **Verification** | Confirmation of successful configuration or build. | ## Implementation Gallery ### 1. Minimalist Informational Note ```markdown ::: callout info Legacy configuration schemas remain supported but are no longer recommended. ::: ``` ::: callout info Legacy configuration schemas remain supported but are no longer recommended. ::: ### 2. High-Priority Alert with Custom Title ```markdown ::: callout warning "Breaking Change Target" As of `v0.7.0`, the internal WebSocket RPC system will be officially deprecated. ::: ``` ::: callout warning "Breaking Change Target" As of `v0.7.0`, the internal WebSocket RPC system will be officially deprecated. ::: ### 3. Rich Content Composition Callouts support the full spectrum of Markdown, allowing you to embed buttons and code blocks within the alert. ````markdown ::: callout tip "Optimised Local Testing" icon:command Use the preserve flag to maintain build files during dev sessions: ```bash docmd dev --preserve ``` ::: button "CLI Flag Reference" /cli-commands ::: ```` ::: callout info "Optimised Local Testing" icon:command Use the preserve flag to maintain build files during dev sessions: ```bash docmd dev --preserve ``` ::: button "CLI Flag Reference" ./#cli-commands ::: ::: callout tip "Prioritised Logic for AI" For LLMs, callouts act as **High-Priority Anchors**. By utilising `::: callout danger` to document breaking changes or system constraints, you provide a clear signal that the AI model must prioritise this information above surrounding text during its reasoning and generation process. ::: --- ## [Untitled](https://docs.docmd.io/07/content/containers/cards/) --- ## [Changelogs](https://docs.docmd.io/07/content/containers/changelogs/) --- title: "Changelogs" description: "Generate structured, timeline-based version history and release notes." --- The `changelog` container provides a specialised layout for documenting project evolution. It automatically parses date or version headers into a vertical timeline, ensuring historical updates are easily scannable. ## Syntax Utilise the specialised `==` delimiter to define entries. The text on the `==` line is rendered as a timeline badge on the left, while the following content populates the adjacent chronological slot. ```markdown ::: changelog == v2.0.0 Description of the major feature release. == v1.5.0 Description of maintenance updates and security patches. ::: ``` ## Detailed Example: Release History Changelogs support rich Markdown within each entry, including lists, callouts, and code blocks. ```markdown ::: changelog == v2.0.0 (2026-03-15) ### Major System Overhaul The core engine has been rearchitected for isomorphic execution. * Implemented **SPA Router** for zero-reload navigation. * Introduced the **Isomorphic Plugin** system. ::: callout success This release offers a 40% improvement in initial build speed. ::: == v1.5.1 (2025-12-10) ### Security Patch * Resolved high-severity vulnerability in the internal parser. * Updated dependency `flatted` to `v3.3.2`. == v1.0.0 (2024-05-01) Initial public release. ::: ``` ::: changelog == v2.0.0 (2026-03-15) ### Major System Overhaul The core engine has been rearchitected for isomorphic execution. * Implemented **SPA Router** for zero-reload navigation. * Introduced the **Isomorphic Plugin** system. ::: callout success This release offers a 40% improvement in initial build speed. ::: == v1.5.1 (2025-12-10) ### Security Patch * Resolved high-severity vulnerability in the internal parser. * Updated dependency `flatted` to `v3.3.2`. == v1.0.0 (2024-05-01) Initial public release. ::: ::: callout tip "Historical Context for AI" Changelogs provide a temporal map for AI agents. When an LLM parses the `llms-full.txt` context, the `::: changelog` structure allows it to accurately identify when specific features, breaking changes, or security fixes were introduced, leading to higher accuracy in its development recommendations. ::: --- ## [Collapsible Sections](https://docs.docmd.io/07/content/containers/collapsible/) --- title: "Collapsible Sections" description: "Embed interactive accordion-style toggles for FAQs, deep-dive content, and spoilers." --- The `collapsible` container creates an interactive, toggleable section (accordion). This pattern is ideal for FAQs, detailed technical configuration, or any secondary information that should be accessible without cluttering the primary documentation flow. ::: callout info "VitePress Alias" If you're migrating from **VitePress**, you can use `:::details` as an alias for `:::collapsible`. Spaceless syntax like `:::collapsible` also works. ::: ## Syntax ```markdown ::: collapsible [open] "Title Text" Main content goes here. ::: ``` ### Options Reference - **`open`**: (Optional) If specified, the section initialises in an expanded state. - **`"Title"`**: The text rendered on the interactive toggle bar. Defaults to "Click to expand" if omitted. - **`icon:NAME`**: (Optional) Adds a [Lucide](external:https://lucide.dev/icons) icon before the title text. ## Detailed Implementation Examples ### Standard Usage (Initial State: Closed) Primarily used for FAQs or reducing the visual density of technical pages. ```markdown ::: collapsible "How do I upgrade docmd?" Run `npm update -g @docmd/core` to fetch the latest stable engine. ::: ``` ::: collapsible "How do I upgrade docmd?" Run `npm update -g @docmd/core` to fetch the latest stable engine. ::: ### Opt-In Visibility (Initial State: Open) Ideal for sections that should be visible by default but allow the user to minimise them for a cleaner view. ```markdown ::: collapsible open "Environment Prerequisites" 1. Node.js v18+ (LTS recommended) 2. PNPM package manager ::: ``` ::: collapsible open "Environment Prerequisites" 1. Node.js v18+ (LTS recommended) 2. PNPM package manager ::: ### Nested Technical Data Collapsibles can contain complex Markdown elements, including syntax-highlighted code blocks. ````markdown ::: collapsible "Analyse Sample JSON Response" ```json { "status": "success", "data": { "version": "0.6.2" } } ``` ::: ```` ::: collapsible "Analyse Sample JSON Response" ```json { "status": "success", "data": { "version": "0.6.2" } } ``` ::: ::: callout tip While content inside a `collapsible` may be hidden from the human user, it remains fully visible to the `docmd` search index and is included in the unified `llms-full.txt` stream. This ensures AI agents can provide comprehensive answers based on hidden technical details while the human-facing interface remains clean and prioritised. ::: --- ## [URL Embeds](https://docs.docmd.io/07/content/containers/embed/) --- title: URL Embeds description: How to safely embed dynamic components, videos, and social media directly into your documents. --- `docmd` ships natively with the highly-optimised **[embed-lite](external:https://github.com/mgks/embed-lite)** parser ecosystem. This allows you to aggressively map raw external URLs strictly onto the page, transforming them beautifully into completely secure, zero-latency UI components instantly! ## Supported Platforms The integrated engine natively exposes structured formatters targeting the following networks identically: * **Video Ecosystem:** YouTube (including native 9:16 Shorts support), Vimeo, Dailymotion, TikTok * **Social Connections:** X (Twitter), Reddit, Instagram, Facebook, LinkedIn * **Code & Prototyping:** GitHub Gists, CodePen, Figma, Google Maps * **Music Services:** Spotify, SoundCloud ## Usage Syntax You simply use the `::: embed` container followed by any destination URL. All three enclosing formats are equivalent: ```md ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ``` ### Standard Result Example The rendering engine strictly parses that URL in the background, checking the validation matrix, and structurally injects native HTML nodes directly onto your page output gracefully: ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ## Fallback Safety Don't worry about generating broken screens. If the internal parser scans an unverified or strictly unavailable domain configuration mapping, `docmd` gracefully falls back to generating a simple, solid `<a>` hyperlink button mapping explicitly out to the target: ```md ::: embed "https://docs.docmd.io/content/containers/embed/" ``` *(Proceeds to generate exactly what you would see below)* ::: embed "https://docs.docmd.io/content/containers/embed/" --- ## [Grids](https://docs.docmd.io/07/content/containers/grids/) --- title: "Grids" description: "Organise layout easily with auto-adjusting responsive columns using native markdown containers." --- Grids provide a native, markdown-driven layout system in `docmd`. Instead of writing manual HTML wrappers, you can use the `grids` container to structure elements side-by-side. Columns automatically adjust their widths to fill available space and logically stack into vertical rows on smaller screens (mobile devices). ## Syntax Reference ```markdown ::: grids ::: grid #### Component A Content for the left side. ::: ::: grid #### Component B Content for the right side. ::: ::: ``` ## Practical Implementation Examples ### 1. Feature Showcasing Side-by-Side Use grids to highlight key capabilities next to each other, like combining structural cards with informational blocks. ```markdown ::: grids ::: grid ::: card "Speed :rocket:" Built on a non-blocking I/O pipeline for maximum performance. ::: ::: ::: grid ::: card "Scalability :zap:" Designed for massive monorepos and extensive project structures. ::: ::: ::: ``` ::: grids ::: grid ::: card "Speed :rocket:" Built on a non-blocking I/O pipeline for maximum performance. ::: ::: ::: grid ::: card "Scalability :zap:" Designed for massive monorepos and extensive project structures. ::: ::: ::: ### 2. Layout Balancing Grids will automatically calculate the optimal width per column (up to 4 items per row on ultra-wide screens) based on the content available and easily group rows on narrow viewports. ::: callout tip "Semantic Layouts" Using the `grids` container keeps your documentation structure purely written in Markdown, resulting in cleaner source files and ensuring LLMs interpret your structural relationships flawlessly! ::: --- ## [Hero Sections](https://docs.docmd.io/07/content/containers/hero/) --- title: "Hero Sections" description: "Build high-impact landing page headers and marketing highlights purely in Markdown." --- The `hero` container creates professional, visually striking landing page headers. It handles complex CSS requirements like **Split Layouts**, **Glow Effects**, and **Sliders** while keeping the authoring experience clean. ## Basic Syntax By default, the `hero` centres its content, making it perfect for banners and simple headlines. ```markdown ::: hero # Build Faster. Markdown to production docs in one command. ::: button "Get Started" /intro color:blue ::: ``` ## Advanced Layouts The `hero` container supports specialised flags to control its structural behaviour. | Flag | Effect | | :--- | :--- | | `layout:split` | Divides the hero into a Text area (left) and a Media area (right). Stacks vertically on mobile. | | `layout:slider` | Transforms the hero into a horizontal slider with scroll-snap behaviour. | | `glow:true` | Injects a subtle, radial gradient glow in the background. | ### The Split Layout (`== side`) Use the `== side` separator to define what content goes in the primary text area and what goes in the secondary "side" area (typically an image or a video embed). ```markdown ::: hero layout:split glow:true # docmd 2.0 Isomorphic execution. AI-optimised. ::: button "Quickstart" /getting-started/basic-usage color:blue == side ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ::: ``` ::: hero layout:split glow:true # docmd 2.0 Isomorphic execution. AI-optimised. ::: button "Quickstart" /getting-started/basic-usage color:blue == side ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ::: ### The Slider Layout (`== slide`) Create an interactive hero slider by using the `== slide` separator between different content nodes. ```markdown ::: hero layout:slider == slide # Isomorphic Core The engine renders everywhere. == slide # AI Optimisation Built for the LLM era. ::: ``` ::: hero layout:slider == slide # Isomorphic Core The engine renders everywhere. == slide # AI Optimisation Built for the LLM era. ::: ## Responsive Behaviour The `hero` container is fully responsive by default: - On **Desktop**, `layout:split` displays side-by-side. - On **Mobile**, it automatically transitions to a centred, vertical stack to ensure optimal readability. ## Best Practices 1. **Glow Effects**: Use `glow:true` sparingly on dark mode sites for a premium "neon" feel. 2. **Media Types**: The "side" content of a split layout is perfect for the `::: embed` component, high-quality PNGs, or raw `<video>` tags. 3. **CTA Placement**: Always place `::: button` elements within the primary "Hero Copy" section (before the `== side` separator) to ensure they are the first thing users see on mobile. --- ## [Custom Interactive Containers](https://docs.docmd.io/07/content/containers/) --- title: "Custom Interactive Containers" description: "A comprehensive directory of the interactive UI building blocks available in docmd." --- Standard Markdown excels at basic text formatting, but professional technical documentation requires rich structural components to effectively communicate complex logic. `docmd` extends Markdown with a suite of **isomorphic containers** that render into responsive, high-fidelity UI elements. ::: callout tip "Migrating from Other Documentation Engines?" `docmd` supports syntax aliases from **VitePress** and **Docusaurus** out of the box. Containers like `:::tip`, `:::warning`, `:::note`, `:::details`, and `:::caution` work without modification. Spaceless syntax (e.g., `:::tabs` instead of `::: tabs`) is also supported for all containers. ::: ## Block Syntax Reference All containers utilise a consistent block syntax, ensuring a predictable authoring experience across your entire project. ```markdown ::: type "Optional Header Title" This is the primary content area. It supports **Markdown**, imagery, and deep component nesting. ::: ``` | Component | Keyword | Primary Use Case | | :--- | :--- | :--- | | **[Callouts](callouts.md)** | `callout` | Semantic highlights for tips, warnings, and alerts. | | **[Cards](cards.md)** | `card` | Framed structural blocks for feature grids and layout control. | | **[Grids](grids.md)** | `grids` | Auto-adjusting multi-column structural groups. | | **[Tabs](tabs.md)** | `tabs` | Interactive switchable panes for alternative platform instructions. | | **[Steps](steps.md)** | `steps` | Visual numbered timelines for "How-to" guides and tutorials. | | **[Tags](tags.md)** | `tag` | Self-closing, coloured labels for version, statuses, or highlight. | | **[Buttons](buttons.md)** | `button` | Self-closing, prominent call-to-action navigation links. | | **[Collapsibles](collapsible.md)**| `collapsible`| Interactive accordion toggles for FAQs and deep-dive technical data. | | **[Changelogs](changelogs.md)** | `changelog` | Structured, timeline-based version history and release notes. | | **[Hero](hero.md)** | `hero` | High-impact landing page sections with layout and slider support. | ## The Strategic Importance of Containers Containers facilitate more than visual polish; they provide high-fidelity **Semantic Signals** to the `docmd` engine and downstream AI agents: 1. **AI Context Mapping**: Marking a block as a `callout warning` explicitly tells LLMs to prioritise that information during its reasoning and generation phases. 2. **Structural Integrity**: Combining `cards` with standard CSS allows for the creation of sophisticated landing pages without ever leaving the Markdown environment. 3. **Source Maintainability**: Eliminates "HTML Bloat" in your documentation source, keeping your `.md` files clean and machine-readable. ## Recursive Composition `docmd` supports **Infinite Nesting Depth**. You can compose any container within another to build complex, interactive documentation nodes purely in Markdown. ```markdown ::: card "Architecture Overview" ::: callout info This module utilises an asynchronous I/O pipeline. ::: ::: button "Deep Explore Core Engine" /advanced/developer-guide ::: ``` [Master the Nesting Guide](nested-containers.md) --- ## [Nested Containers](https://docs.docmd.io/07/content/containers/nested-containers/) --- title: "Nested Containers" description: "Use docmd's recursive parser to combine cards, tabs, and callouts into high-fidelity page layouts." --- One of `docmd`’s most powerful technical capabilities is its **Recursive Parsing Engine**. You can nest components within each other infinitely to synthesise complex, interactive documentation blocks that would otherwise require deep HTML knowledge or custom templates. ## The Architectural Rule While nesting is mathematically infinite, always adhere to the **Self-Closing Component Rule**: ::: callout warning "Self-Closing Buttons" Because the `::: button` component is self-closing (single line), never add a terminal `:::` line after it. Doing so will inadvertently close the **parent container** housing the button, resulting in a fractured layout. ::: ## Technical Composition Examples ### 1. Interactive Resource Block Combine a **Card** for structural framing, **Tabs** for environment-specific instructions, and **Callouts** for highlighting critical information. ````markdown ::: card "Monorepo Quickstart" Choose your preferred initialisation path: ::: tabs == tab "Automated" ```bash pnpm onboard ``` ::: callout success This script handles all package installation and build tasks automatically. ::: == tab "Manual" Manually fetch and link the core engine. ::: button "Go to Developer Guide" /advanced/developer-guide ::: ::: ```` ### 2. Multi-Platform Tutorials Nesting **Tabs** inside **Steps** is a professional pattern for providing platform-specific instructions within a standard tutorial sequence. ```markdown ::: steps 1. **Environment Setup** Configure your local operating system. ::: tabs == tab "macOS" Ensure Homebrew is installed and up-to-date. == tab "Linux" Verify the Presence of `curl` and `bash`. ::: 2. **Core Verification** Execute the version check to confirm connectivity. ::: ``` ::: steps 1. **Environment Setup** Configure your local operating system. ::: tabs == tab "macOS" Ensure Homebrew is installed and up-to-date. == tab "Linux" Verify the Presence of `curl` and `bash`. ::: 2. **Core Verification** Execute the version check to confirm connectivity. ::: ## Design Constraints To maintain both performance and mobile responsiveness, observe the following constraints: * **Recursive Tabs**: Nesting tabs within other tabs is technically supported but strongly discouraged. It creates navigation "loops" that are visually confusing on smaller viewports. * **Sequential Conflict**: If you require numbered steps within a tab, utilise a standard ordered list (`1. Step Content`) rather than the `::: steps` container to avoid layout conflicts. * **Legibility**: While `docmd` does not strictly require indentation for nested blocks, using a 2 or 4-space indentation significantly improves the human-readability of the Markdown source. ::: callout tip "Knowledge Segmentation for AI" Nesting provides clear **Semantic Boundaries**. When an AI agent parses the `llms-full.txt` stream, a `callout` nested within a `card` explicitly tells the model that the tip is scoped to that card's specific topic, preventing context leakage and improving technical accuracy in generated responses. ::: --- ## [Steps](https://docs.docmd.io/07/content/containers/steps/) --- title: "Steps" description: "Convert standard ordered lists into high-impact visual timelines and tutorials." --- The `steps` container is designed specifically for "How-to" guides and technical tutorials. It transforms a standard Markdown ordered list into a polished, numbered vertical timeline with automatic spacing and visual emphasis. ::: callout info "Spaceless Syntax" Both `::: steps` and `:::steps` (spaceless) are supported. Use whichever style you prefer. ::: ## Syntax Wrap any standard ordered list in a `::: steps` block. ```markdown ::: steps 1. **Initialise Project** Run the `docmd init` command to scaffold your directory. 2. **Author Content** Write your documentation using standard Markdown files. 3. **Build & Deploy** Generate static assets using `docmd build`. ::: ``` ## Detailed Implementation The `steps` component supports rich Markdown content within each item, including code blocks, images, and nested containers. ```markdown ::: steps 1. **Generate Production Build** Execute the build command to generate a highly optimised static site. ```bash docmd build ``` 2. **Verify Asset Integrity** Inspect the `site/` directory to ensure all assets were correctly compiled. 3. **Deploy to Infrastructure** Synchronise the `site/` directory with your primary hosting provider (e.g., S3, Cloudflare Pages, or Vercel). ::: ``` ::: steps 1. **Generate Production Build** Execute the build command to generate a highly optimised static site. ```bash docmd build ``` 2. **Verify Asset Integrity** Inspect the `site/` directory to ensure all assets were correctly compiled. 3. **Deploy to Infrastructure** Synchronise the `site/` directory with your primary hosting provider (e.g., S3, Cloudflare Pages, or Vercel). ::: ## Advanced Nesting You can nest other documentation components (such as **Callouts** or **Buttons**) inside a step without interrupting the chronological flow of the sequence. ```markdown ::: steps 1. **Configure Environment** Define your project-specific variables in `docmd.config.js`. ::: callout tip Use `defineConfig` to enable IDE autocompletion for configuration keys. ::: 2. **Validate Schema** Run `docmd verify` to ensure your configuration is structurally sound. ::: ``` ::: callout tip "Workflow Optimisation" Modern AI models interpret the `steps` container as a high-fidelity signal for **Sequential Workflows**. To maximise AI accuracy in the `llms-full.txt` context, always start your list items with a **Bolded Title**. This allows agents to reliably parse the objective of each step before processing the implementation details. ::: --- ## [Tabs](https://docs.docmd.io/07/content/containers/tabs/) --- title: "Tabs" description: "Organise dense, alternative, or multi-language information into switchable interactive panes." --- Tabs are the optimal UI pattern for presenting mutually exclusive or related data sets (e.g., "Install via NPM vs. Yarn" or "macOS vs. Windows" instructions) within a compact, interactive format. ::: callout info "Spaceless Syntax" Both `::: tabs` and `:::tabs` (spaceless) are supported. Use whichever style you prefer. ::: ## Syntax Reference The `tabs` container utilises the specialised sub-delimiter `== tab "Label"`. You can optionally add an icon using the `icon:name` syntax. ```markdown ::: tabs == tab "Label 1" icon:rocket Content for the first tab. == tab "Label 2" icon:settings Content for the second tab. ::: ``` ## Implementation Gallery ### 1. Package Management Tabs are most commonly used to show installation instructions for different package managers in a single view. ::: tabs == tab "pnpm" ```bash pnpm add @docmd/core ``` == tab "npm" ```bash npm install @docmd/core ``` == tab "yarn" ```bash yarn add @docmd/core ``` ::: ### 2. Multi-Language Code Snippets Keep your logic clean by separating different programming languages or environments. ::: tabs == tab "TypeScript" icon:hexagon ```typescript import { build } from '@docmd/core'; await build('./docmd.config.js'); ``` == tab "JavaScript" icon:braces ```javascript const { build } = require('@docmd/core'); build('./docmd.config.js'); ``` ::: ## Core Capabilities ### Isomorphic Lazy Rendering `docmd` implements **Conditional Resource Laziness**. If a tab contains computationally expensive elements (e.g., **Mermaid.js** diagrams or high-resolution images), these assets are only initialised and rendered once the user activates that specific tab. This ensures rapid initial page loads. ### State Persistence The default SPA router tracks the active tab's index across similar documentation pages. If a user selects "pnpm" on one page and navigates to another page with a matching tab structure, the "pnpm" tab will remain active automatically. ## Technical Constraints | Constraint | Note | | :--- | :--- | | **Nesting Depth** | To preserve layout integrity, tabs cannot be nested inside other tab components. | | **Interactive Conflict**| High-conflict syntax: To nest Steps inside a Tab, use a standard ordered list (`1. Step One`) instead of the `::: steps` container. | | **Responsive Limit** | It is recommended to limit tab counts to 6 per block to ensure mobile device compatibility. | ::: callout tip "AI Context Mapping" When utilising tabs for code snippets, always include the target language directly in the tab label (e.g., `== tab "TypeScript"`). This allows LLMs to instantly identify and extract the technically relevant section from the `llms-full.txt` context stream. ::: --- ## [Tags](https://docs.docmd.io/07/content/containers/tags/) --- title: "Tags" description: "Use the tag container to label versions, statuses, or highlight short text snippets easily inline." --- The `tag` container is a self-closing component used to insert small, pill-shaped badges directly into your text. Unlike block containers, tags do not inherit massive sizing from parent elements like headings, they retain their tight, clean proportions no matter where they are placed. ## Basic Usage To create a basic tag, simply provide the text you want to display: ::: tabs == tab "Preview" This feature was added in ::: tag "v0.7.4" color:blue and works perfectly. == tab "Markdown Source" ```markdown This feature was added in ::: tag "v0.7.4" and works perfectly. ``` ::: ## Customising Colours You can override the default tag styling by providing any valid CSS colour string (e.g., `#ff0000`, `blue`, or `hsl(...)`) using the `color:` attribute. `docmd` will automatically calculate a beautiful tinted background with perfectly contrasted text and borders! ::: tabs == tab "Preview" ::: tag "Deprecated" color:#ef4444 ::: tag "Beta" color:#eab308 ::: tag "Stable" color:#22c55e == tab "Markdown Source" ````markdown ::: tag "Deprecated" color:#ef4444 ::: tag "Beta" color:#eab308 ::: tag "Stable" color:#22c55e ```` ::: ## Adding Icons Just like buttons and callouts, you can easily attach an icon from the `docmd` icon library using the `icon:` attribute. ::: tabs == tab "Preview" ::: tag "Verified" icon:check-circle color:#10b981 == tab "Markdown Source" ````markdown ::: tag "Verified" icon:check-circle color:#10b981 ```` ::: ## Linking Tags If you need your tag to act as a hyperlink (for instance, linking a version tag directly to its release notes), you can use the `link:` attribute. External links are automatically detected and opened in a new tab. ::: tabs == tab "Preview" Check out the latest ::: tag "Release Notes" icon:external-link link:/release-notes/0-7-4 == tab "Markdown Source" ````markdown Check out the latest ::: tag "Release Notes" icon:external-link link:/release-notes/0-7-4 ```` ::: ## Using Tags in Headings Because tags are true inline elements, they look gorgeous when used to label major headings. They will automatically align to the baseline without inheriting the heading's massive font-size. ::: tabs == tab "Preview" # Search Filtering ::: tag "New" color:#8b5cf6 == tab "Markdown Source" ````bash # Search Filtering ::: tag "New" color:#8b5cf6 ```` ::: --- ## [Frontmatter Reference](https://docs.docmd.io/07/content/frontmatter/) --- title: "Frontmatter Reference" description: "The complete guide to page-level metadata and configuration in docmd." --- Frontmatter allows you to override global settings on a per-page basis. It must be written in YAML format at the very top of your Markdown file. ## Core Metadata | Key | Type | Description | | :--- | :--- | :--- | | `title` | `String` | **Required.** Sets the HTML `<title>` and the primary section header. | | `description` | `String` | Sets the meta description for SEO and search results. | | `keywords` | `Array` | A list of keywords for the `<meta name="keywords">` tag. | ::: callout warning "Title is important" While not strictly required, the `title` field is strongly recommended. Without it, docmd falls back to the first `# H1` heading or the filename - which can produce less ideal `<title>` tags and search results. ::: ## Visibility & Indexing | Key | Type | Description | | :--- | :--- | :--- | | `noindex` | `Boolean` | Excludes the page from the internal search index. | | `llms` | `Boolean` | Set to `false` to exclude this page from the AI context files (`llms.txt`). | | `hideTitle` | `Boolean` | Hides the title from the sticky header (useful if using a custom H1). | | `bodyClass` | `String` | Adds a custom CSS class to the `<body>` tag of this page. | ## Layout Control | Key | Type | Description | | :--- | :--- | :--- | | `layout` | `String` | Set to `full` to use the primary content width and hide the TOC sidebar. | | `toc` | `Boolean` | Set to `false` to disable the Table of Contents entirely. | | `noStyle` | `Boolean` | Disables the entire `docmd` UI (Sidebar, Header, Footer) for custom pages. | | `titleAppend` | `Boolean` | Set to `false` to prevent appending the site title to the html `<title>`, OpenGraph (`og:title`), and Twitter metadata tags. Default: `true`. | ### `noStyle` Component Control When `noStyle: true` is active, you must explicitly opt-in to the components you wish to retain: ```yaml --- noStyle: true components: meta: true # Injects SEO metadata favicon: true # Injects site favicon css: true # Injects docmd-main.css theme: true # Injects theme-specific styling highlight: true # Injects syntax highlighting scripts: true # Injects the SPA router logic sidebar: true # Injects the navigation sidebar footer: true # Injects the site footer --- ``` ## Plugin Overrides ### SEO (`seo`) * `image`: Custom social share image URL for the page. * `aiBots`: Set to `false` to block specifically AI crawlers from this page. * `canonicalUrl`: Sets a custom canonical link for SEO. --- ## [Live Preview](https://docs.docmd.io/07/content/live-preview/) --- title: "Live Preview" description: "Run docmd entirely in the browser without a backend server using the Live architecture." --- `docmd` features a modular architecture that separates filesystem operations from core processing logic. This enables the documentation engine to run **entirely within the browser**, facilitating live editors and CMS previews without the need for a Node.js backend. ::: button "Open Live Editor" external:https://live.docmd.io ## The Live Editor The built-in Live Editor provides a high-performance, split-pane interface. Author your Markdown in the left pane and observe the rendered output navigate and synchronise in real-time on the right. ### Local Execution To launch the Live Editor locally within your project: ```bash docmd live ``` ### Static Distribution Generate a standalone, static version of the editor for hosting on platforms like Vercel or GitHub Pages: ```bash docmd live --build-only ``` This generates a `dist/` directory containing the `index.html` entry point and the bundled `docmd-live.js` isomorphic engine. ## Embedding docmd You can integrate the browser-compatible bundle into your own applications to provide internal Markdown rendering or preview capabilities. ### 1. Resource Integration Include the required CSS and JavaScript bundles from your assets or a CDN: ```html <link rel="stylesheet" href="/assets/css/docmd-main.css"> <script src="/docmd-live.js"></script> ``` ### 2. Isomorphic API The global `docmd` object provides the `compile` method for instantaneous rendering. ```javascript const html = await docmd.compile(markdown, { siteTitle: 'Dynamic Preview', theme: { appearance: 'dark' } }); // Inject into an iframe for style isolation document.getElementById('preview-frame').srcdoc = html; ``` ::: callout tip "AI Feedback Loops" The Live architecture is ideal for building **AI-Agent Sandboxes**. Instead of providing an agent with filesystem write access, you can pipe its suggested documentation changes to a live-compilation buffer. This allows you to visually verify AI suggestions in a "ghost" environment before committing changes to your repository. ::: --- ## [docmd : Bespoke No-Style Page Demo](https://docs.docmd.io/07/content/no-style-example/) --- title: "docmd : Bespoke No-Style Page Demo" description: "A functional demonstration of the noStyle architectural feature." noStyle: true components: meta: true favicon: true css: true theme: true scripts: true mainScripts: true copyCode: true customHead: | <style> body { font-family: 'Inter', -apple-system, system-ui, sans-serif; margin: 0; padding: 0; line-height: 1.6; background: var(--bg-primary); color: var(--text-primary); } .demo-container { max-width: 900px; margin: 0 auto; padding: 80px 20px; } .demo-hero { text-align: centre; margin-bottom: 60px; } .demo-hero h1 { font-size: 3.5rem; margin-bottom: 20px; color: var(--brand-primary, #4a6cf7); } .demo-hero p { font-size: 1.25rem; color: var(--text-secondary); } .demo-card { background: var(--bg-secondary, #f8f9fa); padding: 40px; border-radius: 16px; border: 1px solid var(--border-colour); box-shadow: 0 4px 20px rgba(0,0,0,0.05); } .demo-button { display: inline-block; padding: 14px 28px; background-color: var(--brand-primary, #4a6cf7); color: white; text-decoration: none; border-radius: 8px; font-weight: 600; margin-top: 30px; transition: filter 0.2s ease; } .demo-button:hover { filter: brightness(1.1); } </style> --- <div class="demo-container"> <div class="demo-hero"> <h1>Bespoke Page Architecture</h1> <p>Demonstrating the absolute layout control enabled via <code>noStyle: true</code>.</p> </div> <div class="demo-card"> <h2>Logical Foundation</h2> <p> This demonstration utilises the <code>noStyle: true</code> frontmatter directive to bypass the global documentation layout (Sidebar, Header, and TOC). This provides a "Zero-Friction" canvas for creating marketing landing pages or custom product dashboards. </p> <h3>Enabled System Components</h3> <p>When in No-Style mode, you explicitly opt-in to the documentation engine's core features:</p> <ul> <li><strong>SEO Meta Engine</strong>: Structured tags and social graph data are retained.</li> <li><strong>Project Branding</strong>: Global favicon injection remains active.</li> <li><strong>Foundational Typography</strong>: The processed <code>docmd-main.css</code> provides base styling.</li> <li><strong>Theme Synchronisation</strong>: Light/Dark mode state is fully preserved.</li> <li><strong>Interactive Capabilities</strong>: The SPA router and component logic remain available.</li> </ul> <h3>Technical Implementation</h3> <p> The layout for this page is authored using standard HTML wrappers and scoped CSS defined within the <code>customHead</code> frontmatter field. This ensures zero CSS leakage to the rest of the documentation site. </p> <a href="/content/no-style-pages/" class="demo-button">Analyse the Implementation Guide →</a> </div> </div> --- ## [No-Style Pages](https://docs.docmd.io/07/content/no-style-pages/) --- title: "No-Style Pages" description: "Create custom landing pages and unique layouts by disabling the default docmd theme." --- `docmd` allows you to bypass the standard documentation layout (Sidebar, Header, and Footer) on a per-page basis. This is ideal for creating product landing pages, custom dashboards, or marketing splash screens while maintaining access to the documentation engine's components. ## Enabling No-Style Mode To disable the global UI, add `noStyle: true` to the page's frontmatter. ```yaml --- title: "Product Showcase" noStyle: true components: meta: true # Retain SEO and OpenGraph tags favicon: true # Retain site favicon css: true # Inject docmd-main.css for typography --- <!-- Raw HTML or specialised Markdown goes here --> <div class="hero"> <h1>Next-Gen Documentation</h1> <p>Zero-config. Isomorphic. AI-Ready.</p> </div> ::: callout info "Infinite Nesting Support" Even with `noStyle: true`, all standard `docmd` containers like `::: card`, `::: tabs`, and `::: hero` are fully supported and can be nested at any depth. ::: ``` ## Component Opt-In When `noStyle` is active, you start with a blank canvas. Selectively re-enable core system components as needed: | Component | Description | | :--- | :--- | | `meta` | Injects `<title>`, SEO meta tags, and structured OpenGraph data. | | `favicon` | Injects the project-wide favicon. | | `css` | Injects `docmd-main.css`. Highly recommended for foundational grid and typography. | | `menubar` | Injects the site's top menubar. | | `theme` | Injects the active theme's CSS variables and appearance overrides. | | `scripts` | Injects interactive component logic (requires `mainScripts: true`). | | `spa` | Enables the single-page application router (requires `scripts: true`). | ## Composable Landing Pages The primary power of `noStyle` is that it allows you to use the entire suite of `docmd` components as high-fidelity "widgets" on a blank canvas. You aren't limited to raw HTML; you can build complex, structural designs purely in Markdown. ### Building a Modern Entry Point ```yaml --- title: "Welcome" noStyle: true components: meta: true css: true menubar: true # Use the site's top navigation scripts: true # Enable interactive components mainScripts: true --- ::: hero layout:split glow:true # Build Documentation that Wows. The zero-config engine for modern engineering teams. ::: button "Get Started" /introduction color:blue ::: button "GitHub" github:docmd-io/docmd color:gray == side ::: embed [https://www.youtube.com/watch?v=dQw4w9WgXcQ] ::: ::: ::: grids ::: card "Zero Configuration" Just write markdown. No complex React logic or build scripts. ::: ::: card "AI Optimised" Structure-aware parsing for the LLM era. ::: ::: card "Fast Without the Framework Tax" Static generation with isomorphic SPA navigation. ::: ::: ``` ::: callout tip "AI-Generated Layouts" Because `noStyle` pages support raw HTML alongside `docmd` containers, they are perfectly suited for **AI-driven UI design**. You can prompt an AI: *"Design a modern hero section using Tailwind-like utility classes and docmd buttons, wrapped in a noStyle: true container."* The AI can iterate on the design within your static site pipeline with zero additional configuration. ::: ## String Replacement (i18n for noStyle) When your site has [i18n configured](../configuration/localisation/index.md), themed documentation pages get full server-side translations automatically - each locale has its own markdown files in separate directories. But noStyle pages use custom HTML, not markdown, so that approach doesn't apply. Instead, docmd provides **string replacement** - translating your HTML via `data-i18n` attributes and JSON translation files. ::: callout info "Why this only works for noStyle pages" String replacement finds elements with `data-i18n` attributes in the rendered HTML and swaps their text content. Standard markdown content renders to plain `<p>`, `<h2>`, `<li>` tags - there are no `data-i18n` attributes for the replacer to find. For translating documentation written in markdown, use [directory mode](../configuration/localisation/translated-content.md) - separate markdown files per locale. ::: ### How It Works There are two modes for string replacement: - **Server-side (recommended)**: With [`stringMode: true`](../configuration/localisation/index.md#string-mode-nostyle-pages-only) in your i18n config, docmd resolves `data-i18n` attributes **at build time** and generates fully translated HTML in `/{locale}/` directories. Each locale gets its own URL - fully indexable by search engines. - **Client-side**: The `docmd-i18n-strings.js` script loads translations at runtime via XHR. This is injected automatically on noStyle pages when i18n is configured. Useful for in-place switching without page reload (e.g. SPAs, dashboards). Both modes use the same `data-i18n` attribute syntax and JSON file format. 1. Place JSON translation files inside `assets/i18n/` - one per locale: ``` assets/ i18n/ en.json hi.json zh.json ``` 2. Each JSON file is a flat key-value map: ```json { "hero.title": "Markdown → Production Docs", "hero.subtitle": "The zero-config documentation engine.", "nav.docs": "Documentation", "nav.editor": "Live Editor", "cta.getStarted": "Get Started", "cta.install": "npm i @docmd/core" } ``` 3. Use `data-i18n` attributes on your HTML elements: ```html <h1 data-i18n="hero.title">Markdown → Production Docs</h1> <p data-i18n="hero.subtitle">The zero-config documentation engine.</p> <a data-i18n="nav.docs" href="/docs">Documentation</a> ``` The default-language text is written directly in the HTML (acts as the fallback). When a non-default locale is active, the script loads the matching JSON and replaces the text. ### Attribute Translation To translate element attributes like `placeholder`, `title`, or `aria-label`, use `data-i18n-{attr}`: ```html <input data-i18n-placeholder="search.placeholder" placeholder="Search..."> <button data-i18n-aria-label="nav.menuLabel" aria-label="Open menu">☰</button> <a data-i18n-title="nav.tooltip" title="Go to docs">Docs</a> ``` ### HTML Content For keys that contain HTML markup, use `data-i18n-html` instead of `data-i18n`: ```html <p data-i18n-html="hero.desc">Static HTML for SEO. <br>SPA for speed.</p> ``` ### Switching Locales The i18n strings module exposes a global API at `window.DOCMD_I18N_STRINGS`: ```js // Switch to Hindi DOCMD_I18N_STRINGS.switchLocale('hi'); // Get current locale console.log(DOCMD_I18N_STRINGS.locale); // 'en' // Get all configured locales console.log(DOCMD_I18N_STRINGS.locales); // [{ id: 'en', label: 'English' }, { id: 'hi', label: 'हिन्दी' }] ``` You can build a custom language switcher using this API: ```html <select onchange="DOCMD_I18N_STRINGS.switchLocale(this.value)"> <option value="en">English</option> <option value="hi">हिन्दी</option> </select> ``` ### Events Listen for the `docmd:i18n-applied` event to run custom logic after strings are applied: ```js document.addEventListener('docmd:i18n-applied', function(e) { console.log('Locale:', e.detail.locale); console.log('Strings:', e.detail.strings); }); ``` ::: callout info "Automatic Detection" The script detects the active locale from the URL path prefix (e.g. `/hi/` → Hindi). For the default locale (rendered at `/`), it checks `localStorage` for a previously saved preference. The `switchLocale()` function handles URL navigation automatically. ::: ### In-Place Mode For single-page sites (like landing pages), you don't want locale switching to navigate to a different URL. Set `inPlace: true` in your i18n config to swap strings without any URL redirect: ```js // docmd.config.js i18n: { defaultLocale: "en", locales: [ { id: "en", label: "English" }, { id: "zh", label: "中文" } ], inPlace: true } ``` With `inPlace: true`, calling `switchLocale()` reloads the JSON for the new locale and replaces all `data-i18n` strings on the current page - no navigation occurs. --- ## [Advanced Markdown Syntax](https://docs.docmd.io/07/content/syntax/advanced/) --- title: "Advanced Markdown Syntax" description: "Use docmd's extended feature set: Custom attributes, GFM extensions, and semantic definitions." --- Beyond standard Markdown, `docmd` supports several high-fidelity extensions derived from GitHub Flavored Markdown (GFM) and custom attribute plugins. These tools provide total control over your document's structure and styling. ## GFM Extensions ### Task Lists Create interactive or read-only checklists for roadmap tracking. ```markdown - [x] Engine Optimisation Complete - [ ] Plugin API Finalisation ``` - [x] Engine Optimisation Complete - [ ] Plugin API Finalisation ### Automatic Link Resolution Standard URLs and email addresses are automatically identified and linked without additional markup: `https://docmd.io` ### Shortcode Emojis `docmd` supports standard shortcodes to inject visual personality into your documentation. > We :heart: high-performance documentation! :rocket: :smile: ## Custom Element Attributes Assign unique IDs and CSS classes directly to headers, images, and links using the curly-brace `{}` syntax. This is the primary method for applying [Custom CSS Styles](../../theming/custom-css-js.md). ### Unique Semantic IDs Useful for deep-linking directly to technical subsections. ```markdown ## Performance Benchmarks {#benchmarks-2026} ``` ### Functional CSS Classes Apply styling utilities to specific elements. ```markdown ## Centre-Aligned Section {.text-centre .text-blue} ``` ### Actionable Button Links Transform any standard markdown link into a styled call-to-action button. ```markdown [Download Latest Release](#download){.docmd-button} ``` ## Citations & Definitions ### Footnote References Add citations or technical deep-dives[^1] that are automatically collected and rendered at the bottom of the page. ```markdown Architectural decisions are documented in the RFC[^1]. [^1]: RFC-42: Isomorphic Rendering Pipeline. ``` ### Definition Lists Perfect for API parameter descriptions and glossaries. ```markdown PropName : The unique identifier for the configuration key. ``` PropName : The unique identifier for the configuration key. ### Technical Abbreviations Define abbreviations globally within a page. Hovering over the term reveals its full definition. ```markdown *[SPA]: Single Page Application The docmd router enables a seamless SPA experience. ``` *[SPA]: Single Page Application The docmd router enables a seamless SPA experience. ::: callout tip "Contextual Precision for AI" Utilising **Definitions** and **Abbreviations** provides high-quality technical signals to AI agents. When an AI processes your `llms-full.txt` context, these explicit definitions prevent lexical ambiguity, ensuring the model generates logically correct explanations for your project's specific terminology. ::: --- ## [Code Blocks](https://docs.docmd.io/07/content/syntax/code/) --- title: "Code Blocks" description: "Document technical implementations with high-fidelity syntax highlighting and interactive copy buttons." --- `docmd` utilises the ultra-fast `lite-hl` engine to provide automatic, context-aware syntax highlighting across hundreds of programming languages and configuration formats. ## Syntax Highlighting Author your technical examples using standard Markdown fenced code blocks. Always specify the language identifier to ensure the highlight engine applies the correct lexical rules. ````markdown ```javascript function initialise() { console.log("docmd engine active."); } ``` ```` **Rendered Result:** ```javascript function initialise() { console.log("docmd engine active."); } ``` ## Block Titles You can provide a descriptive title (like a filename) for your code blocks by following the language identifier with a string in double quotes. This renders a premium header above the code block. ````markdown ```javascript "initialise.js" function initialise() { console.log("docmd engine active."); } ``` ```` **Rendered Result:** ```javascript "initialise.js" function initialise() { console.log("docmd engine active."); } ``` ::: callout tip "One-Click Portability" When `copyCode: true` is enabled in your configuration (default), a subtle copy button automatically appears in the top-right corner of every code block on hover, allowing users to instantly transfer snippets to their IDE. ::: ## Strategy for AI Context When documenting code for consumption by LLMs and AI Agents, adhere to these technical best practices: 1. **Strict Language Labeling**: Explicitly labeling blocks as `typescript`, `bash`, or `json` ensures the AI parser accurately interprets the block's grammar within the `llms-full.txt` stream. 2. **Embedded Intent**: Use inline comments within your code blocks to explain the *why* behind complex logic. This provides the AI with critical reasoning context that simple text outside the block might lack. ## Language Support Reference `docmd` provides out-of-the-box support for the most common technical ecosystems, including: * **Logic**: `javascript`, `typescript`, `python`, `rust`, `go`, `ruby`, `csharp`. * **Web**: `html`, `css`, `markdown`. * **Data & Shell**: `json`, `yaml`, `bash`, `powershell`, `dockerfile`. * **Documentation**: `mermaid`, `changelog`. --- ## [Images & Visual Media](https://docs.docmd.io/07/content/syntax/images/) --- title: "Images & Visual Media" description: "Master media management: Responsive images, styling attributes, and automated Lightbox effects." --- `docmd` utilises standard Markdown syntax for media integration. We recommend centralising your media assets in the `assets/images/` directory within your project source. ```markdown ![Technical Diagram](/assets/images/architecture.png "Optional Tooltip Title") ``` ## Technical Styling Reference Assign specialised CSS classes and attributes directly to your images using the `{ .class }` attribute syntax. ### Dynamic Resizing ```markdown ![Small Scale](/assets/icon.png){ .size-small } ![Standard View](/assets/preview.png){ .size-medium } ![Full Scale](/assets/banner.png){ .size-large } ``` ### Alignment & Layout ```markdown ![Centred Focus](/assets/img.png){ .align-centre } ![Floating Right](/assets/img.png){ .align-right .with-shadow .with-border } ``` ![Advanced Styling Example](/assets/images/docmd-preview.png){.with-border .with-shadow .size-medium .align-centre} ## Structured Media Elements ### Figure Captions For precise, accessible media captioning, use standard HTML5 `<figure>` elements. ```html <figure> <img src="/assets/diagram.png" alt="Cloud Infrastructure Diagram"> <figcaption>Figure 1.1: Core System Infrastructure Architecture.</figcaption> </figure> ``` ### Image Galleries Organise multiple assets into a responsive, balanced grid using the `image-gallery` class. ```html <div class="image-gallery"> <figure> <img src="/assets/screen1.jpg" alt="User Dashboard View"> <figcaption>Live Performance Monitor</figcaption> </figure> <figure> <img src="/assets/screen2.jpg" alt="Configuration Panel View"> <figcaption>Project Global Settings</figcaption> </figure> </div> ``` ## Interactive Lightbox Zoom If the `mainScripts` component is active (default), `docmd` automatically applies a full-screen zoom effect to any image contained within a gallery or any image tagged with the `.lightbox` class. ```markdown ![Deep Texture Analysis](/assets/sample.png){ .lightbox } ``` ::: callout tip "AI Context & Accessibility" Always provide comprehensive **Alt-Text** for visual media. While advanced AI models possess vision capabilities, descriptive text within the Markdown source provides a direct, high-fidelity signal for the model's reasoning engine - enhancing architectural analysis and feature comprehension in the `llms-full.txt` stream. ::: --- ## [Markdown Syntax Foundation](https://docs.docmd.io/07/content/syntax/) --- title: "Markdown Syntax Foundation" description: "Master the fundamental formatting rules of docmd: Headings, typographic styles, and technical blocks." --- `docmd` adheres to standard **GitHub Flavored Markdown (GFM)** specifications. This guide establishes the baseline standards for authoring core content across your documentation site. ## Typographic Styling | Attribute | Markdown Syntax | Visual Outcome | | :--- | :--- | :--- | | **Emphasis** | `**Text**` | **Bold technical terms** | | **Italic** | `*Text*` | *Stylized variables* | | **Strikethrough** | `~~Text~~` | ~~Deprecated logic~~ | | **Inline Logic** | `` `code` `` | `engine.initialise()` | ## Structural Elements ### Semantic Header Hierarchy ```markdown # Level 1 (Automatic via Frontmatter) ## Level 2 (Major Section) ### Level 3 (Feature Detail) ``` ::: callout tip "Logical Integrity for AI" Advanced AI models and search internalizers rely on a strict heading hierarchy to build an accurate mental model of your project. By avoiding "Heading Skipping" (e.g., jumping from H2 directly to H4), you ensure the `llms-full.txt` context stream remains chronologically and logically sound. ::: ### Navigation & Reference Utilise standard link syntax for both internal documentation nodes and global resources. ```markdown [Global Resource](https://docmd.io) [Internal Module](../api/node-api.md) ``` ### Enumeration & Listing * **Unordered Segments**: Utilise `*` or `-` for scannable bullet points. * **Sequential Logic**: Utilise `1.`, `2.`, etc., for ordered instructions. (For tutorials, consider the high-impact **[Steps Container](../containers/steps.md)**). ## Technical Block Elements ### Blockquotes The standard `>` syntax is ideal for highlighting outside quotes or background context. > The docmd engine redefines the boundaries between static site generation and dynamic application delivery. ### Data Schemas (Tables) | Attribute | Data Type | Default | | :--- | :--- | :--- | | `name` | `string` | `undefined` | | `active` | `boolean` | `true` | ## Embedded HTML Support As `docmd` is built with raw HTML parsing enabled, you can inject complex layouts or unique styling directly within your Markdown files for specialised UI requirements. ```html <div style="padding: 2rem; border: 1px solid var(--border-colour); border-radius: 12px; text-align: centre;"> Bespoke UI elements live here. </div> ``` --- ## [Linking & Referencing](https://docs.docmd.io/07/content/syntax/linking/) --- title: "Linking & Referencing" description: "Master internal cross-linking, external resources, and reliable asset referencing with docmd's automatic URL normalisation." --- `docmd` provides a reliable, filesystem-aware linking system. Write links to your source `.md` files naturally - using any format you prefer - and the engine will automatically normalise them into clean, SEO-optimised URLs for production. ::: callout info "Write Naturally, Ship Perfectly" You do not need to follow any special linking conventions. Whether you write `overview.md`, `overview/`, or just `overview`, the build engine produces the same clean, trailing-slash URL. Every internal link is automatically normalised at build time so you can focus on content, not URL formatting. ::: ## How URL Normalisation Works During the build process, the engine applies a consistent set of rules to every internal link - in Markdown text, button containers, tags, and navigation configuration alike: | What You Write | What Gets Rendered | Why | | :--- | :--- | :--- | | `overview.md` | `overview/` | `.md` extension stripped, trailing `/` added | | `overview` | `overview/` | Trailing `/` added automatically | | `overview/` | `overview/` | Already correct - no change | | `api/commands.md` | `api/commands/` | Subdirectory link normalised | | `localisation/index.md` | `localisation/` | `index` stripped - folder is the canonical URL | | `../index.md` | `../` | Parent directory index resolved cleanly | | `overview.md#settings` | `overview/#settings` | Hash fragment preserved through normalisation | | `./guide.md` | `./guide/` | Relative prefix preserved | | `https://example.com` | `https://example.com` | External links pass through untouched | ::: callout tip "SEO Best Practice" All internal pages are served as directory-style URLs ending with a trailing slash (e.g., `/configuration/overview/`). This is the industry standard for static sites, prevents 301 redirect chains, and ensures consistent canonical URLs for search engine indexing. ::: ## Internal Link Resolution Link to other pages in your documentation using relative paths to the source `.md` files. The engine resolves them correctly regardless of directory depth. | Targeting Strategy | Markdown Syntax | | :--- | :--- | | **Sibling Page** | `[System Overview](overview.md)` | | **Subdirectory** | `[API Reference](api/node-api.md)` | | **Subdirectory Index** | `[Localisation](localisation/index.md)` | | **Parent Directory** | `[Back to Home](../index.md)` | ## Section Anchors (Deep Linking) Navigate directly to specific headings using standard URL hash fragments. * **Intra-page Anchor**: `[Jump to Roadmap](#project-roadmap)` * **Cross-page Anchor**: `[Review CLI Flags](../cli-commands.md#available-flags)` Hash fragments are preserved through the normalisation process. The link above renders as `../cli-commands/#available-flags` in production. ## Opening Links in a New Tab Use the `external:` prefix on any link to force it to open in a new tab. This works universally - in standard Markdown links, button containers, tags, and anywhere else you can write a URL. ```markdown <!-- Force any link to open in a new tab --> [Open in New Tab](external:./configuration/overview.md) <!-- External link to GitHub --> [GitHub](external:https://github.com/docmd-io/docmd) ``` By default, all links (including HTTP/HTTPS) open in the same window. Use the `external:` prefix only when you want a new tab. The `external:` prefix is **stripped** from the rendered URL - it is purely a build-time signal. ## Linking to Raw Files By default, the engine strips `.md` extensions and normalises paths. If you genuinely need to link to a raw `.md` file (for example, a downloadable source file), use the `raw:` prefix: ```markdown [View Raw Source](raw:docs/readme.md) ``` The `raw:` prefix bypasses all normalisation - the extension and path are preserved exactly as written. Like `external:`, the prefix itself is stripped from the rendered URL. ## Button Containers The `::: button` container supports the same linking conventions as standard Markdown links - including `external:` and `raw:` prefixes: ```markdown ::: button "Get Started" ./getting-started/quick-start.md icon:rocket ::: button "View on GitHub" https://github.com/docmd-io/docmd icon:github ::: button "Download Source" raw:docs/readme.md icon:download ``` ## Tag Links Tags with `link:` values also benefit from the unified normaliser: ```markdown ::: tag "v0.7.6" link:release-notes/0-7-6.md icon:tag color:#22c55e ::: tag "GitHub" link:https://github.com/docmd-io/docmd icon:github ::: tag "Open Externally" link:external:./configuration/overview.md icon:external-link ``` ## Navigation Configuration Paths defined in `navigation.json` and `docmd.config.js` are also normalised at build time. You can write them in any format: ```json "navigation.json" [ { "title": "Overview", "path": "configuration/overview" }, { "title": "Overview", "path": "configuration/overview.md" }, { "title": "Overview", "path": "configuration/overview/" } ] ``` All three entries above produce the same canonical URL: `/configuration/overview/`. For navigation items that should open in a new tab, use the `external` flag: ```json "navigation.json" [ { "title": "GitHub", "path": "https://github.com/docmd-io/docmd", "external": true } ] ``` ::: callout warning "Index Pages in Navigation" When linking to a directory's index page, use the folder path rather than explicitly referencing `index.md`. Both work identically, but the folder path is cleaner: ```markdown <!-- Preferred --> [Localisation](localisation/) <!-- Also works (auto-normalised) --> [Localisation](localisation/index.md) ``` ::: ## Protocols & External Resources The engine respects standard browser protocols for external resources. These links are never modified. * **Global HTTPS**: `[docmd Homepage](https://docmd.io)` - opens in same tab (use `external:` prefix for new tab) * **Mail Protocol**: `[Support Channel](mailto:help@docmd.io)` - not opened in a new tab * **Asset Protocol**: `[Download CLI Binary](/assets/bin/docmd-mac.zip)` - not normalised ## Static Asset Referencing To provide downloads or reference raw source files, place them within the `assets/` directory of your project. The `docmd` builder ensures these files are moved to the production root without path modifications. ```markdown [Download Documentation PDF](/assets/pdf/handbook.pdf) [View Raw Global Config](/assets/config/docmd.config.js) ``` ::: callout tip "Semantic Linkage for AI" When cross-linking technical modules, prioritise **Descriptive Anchors** (e.g., `[Optimise PWA caching](../plugins/pwa.md)`) over generic text (e.g., `[Read more](../plugins/pwa.md)`). Detailed link labels provide AI agents with a high-fidelity map of the semantic relationships between different documentation nodes in the `llms-full.txt` context. ::: --- ## [Contributing](https://docs.docmd.io/07/contributing/) --- title: "Contributing" description: "Guidelines and setup instructions for contributing to docmd." --- Thank you for your interest in contributing to `docmd`. We appreciate bug fixes, documentation improvements, new features, and design suggestions. ## Development Environment `docmd` is a monorepo managed with [pnpm](https://pnpm.io/). ### Prerequisites - **Node.js**: v22.x or later (LTS recommended) - **pnpm**: v10.x or later ### Project Setup Clone the repository and run the initial setup to install dependencies and build the monorepo: ```bash git clone https://github.com/docmd-io/docmd.git cd docmd pnpm install pnpm build ``` To link the local `docmd` command globally for testing in other projects: ```bash pnpm verify --link ``` ### Local Development We provide a master proxy command to run any `docmd` command against our internal `_playground` directory. This makes development identical to the user CLI experience: ```bash pnpm docmd dev # Starts playground dev server (also: pnpm dev) pnpm docmd build # Builds playground documentation ``` To watch internal source files (engine, templates, and plugins) with hot-reload, set the `DOCMD_DEV` environment variable: ```bash DOCMD_DEV=true pnpm dev ``` ## Quality Standards ### Linting Ensure your code complies with our ESLint configuration. To automatically fix formatting issues, run: ```bash pnpm lint --fix ``` ### Verification Before submitting a Pull Request, you **MUST** ensure the entire monorepo passes our intensive verification pipeline. This simulates a fresh release environment, audits for security vulnerabilities, and verifies monorepo integrity: ```bash pnpm prep ``` *(This chains `pnpm reset`, dependency installation, lint checks, 7-pillar E2E tests, and the final release dry-run.)* ## GitHub Workflow 1. **Fork and Branch**: Create a feature branch from the latest `main`. 2. **Verify**: Ensure `pnpm prep` returns `🛡️ docmd is ready for production!`. 3. **Pull Request**: Open a PR with a clear description of the problem solved or the feature added. ### Commit Guidelines We use [Conventional Commits](https://www.conventionalcommits.org/). Please prefix your commit messages with: - `feat:` (New features) - `fix:` (Bug fixes) - `docs:` (Documentation changes) - `refactor:` (Internal refactorings) ### Source Headers All new files within the `packages/` directory MUST include the standard project copyright header: ```javascript /** * -------------------------------------------------------------------- * docmd : the zero-config documentation engine. * * @package @docmd/core (and ecosystem) * @website https://docmd.io * @repository https://github.com/docmd-io/docmd * @licence MIT * @copyright Copyright (c) 2025-present docmd.io * * [docmd-source] - Please do not remove this header. * -------------------------------------------------------------------- */ ``` --- ## [Caddy](https://docs.docmd.io/07/deployment/caddy/) --- title: "Caddy" description: "Deploy docmd with a production-ready Caddyfile." --- [Caddy](https://caddyserver.com/) is a modern web server that handles HTTPS provisioning and certificate renewals automatically. ## Generate a Caddyfile ```bash docmd deploy --caddy ``` This generates a `Caddyfile` personalised to your project: - **Site address** is set to the hostname from your `url` config - Caddy will automatically provision an SSL certificate for it. Falls back to `:80` if no URL is configured. - **Root directory** uses your configured `out` directory (not hardcoded) - **SPA fallback** is only included when `layout.spa` is `true` in your config ### What Gets Generated ```caddy docs.example.com { root * ./site file_server # SPA Routing Fallback (only when layout.spa is true) try_files {path} {path}/ /index.html # Security Headers header { X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" -Server } # Custom 404 handle_errors { rewrite * /404.html file_server } # Cache Static Assets (6 months) @static { file path *.ico *.css *.js *.gif *.jpg *.jpeg *.png *.webp *.avif *.svg *.woff *.woff2 *.eot *.ttf *.otf } header @static Cache-Control "public, max-age=15552000, immutable" } ``` When you use a real domain as the site address (e.g., `docs.example.com` instead of `:80`), Caddy automatically provisions a free SSL certificate via Let's Encrypt - zero HTTPS configuration needed. ## Deployment Steps 1. Build your site: `docmd build` 2. Transfer your output folder and the generated `Caddyfile` to your server. 3. Run `caddy start` or `caddy run` in the directory containing your Caddyfile. ### Re-Generating Changed your site URL or output directory? Run `docmd deploy --caddy` again - the Caddyfile is regenerated to match your current `docmd.config.js`. --- ## [CI/CD Pipelines](https://docs.docmd.io/07/deployment/ci-cd/) --- title: "CI/CD Pipelines" description: "Automate documentation builds and deployments with CI/CD pipelines for GitHub Pages, Vercel, Netlify, and more." --- Use CI/CD workflows to automatically build and deploy your `docmd` site every time you push changes. Below are ready-to-use configurations for popular cloud platforms. ## Cloud Platforms ::: tabs == tab "GitHub Pages" The recommended method is using **GitHub Actions** to automate your deployments on every push. **Create `.github/workflows/deploy.yml`:** ```yaml name: Deploy docmd on: push: branches: ["main"] permissions: contents: read pages: write id-token: write jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '22' } - run: npx @docmd/core build - uses: actions/upload-pages-artifact@v3 with: { path: ./site } - uses: actions/deploy-pages@v4 ``` == tab "Vercel" 1. Connect your repository to Vercel. 2. In the project **Build Settings**: - **Framework Preset**: `Other` - **Build Command**: `npx @docmd/core build` - **Output Directory**: `site` 3. Deploy. Vercel automatically detects the static output and serves it globally. == tab "Netlify" 1. Import your project from GitHub/GitLab/Bitbucket. 2. Configure your build settings: - **Build command**: `npx @docmd/core build` - **Publish directory**: `site` 3. Click **Deploy site**. Netlify's CDN will handle the routing and asset delivery. == tab "Cloudflare Pages" 1. Create a new project in the Cloudflare Dashboard under **Pages**. 2. Connect your git provider and select your repository. 3. Configure the build settings: - **Framework preset**: `None` - **Build command**: `npx @docmd/core build` - **Build output directory**: `site` 4. Save and Deploy. == tab "Firebase" 1. Install the Firebase CLI: `npm install -g firebase-tools`. 2. Build your site: `npx @docmd/core build`. 3. Run `firebase init hosting` and select your project. 4. Set the public directory to `site`. 5. Configure as a single-page app: `Yes` (this handles the 404 behaviour). 6. Deploy using `firebase deploy`. ::: ::: callout info "Why npx @docmd/core?" In CI/CD environments where `docmd` is not globally installed, use `npx @docmd/core` to run the scoped package directly. If your project has `@docmd/core` listed as a `devDependency`, simply using `docmd build` after `npm install` will also work. ::: ## Manual / Static Server For traditional web servers (Apache, IIS, etc): 1. Generate the site: `npx @docmd/core build`. 2. Upload the contents of the `site/` folder to your server via SFTP, SCP, or your preferred deployment tool. 3. Ensure your server is configured to serve `index.html` for directories (the default for most). --- ## [Docker](https://docs.docmd.io/07/deployment/docker/) --- title: "Docker" description: "Deploy docmd in a Docker container with a single command." --- `docmd` generates static HTML - perfect for lightweight, reproducible Docker containers. ## Generate a Dockerfile ```bash docmd deploy --docker ``` This creates a `Dockerfile` and `.dockerignore` in your project root, personalised to your configuration: - **Your output directory** is used in the `COPY` path (not a hardcoded `site/`) - **Your exact `@docmd/core` version** is pinned in the install step for reproducible builds - **Your config file** is passed to `docmd build` if you use a non-default name ### What Gets Generated The Dockerfile uses an optimised multi-stage build: 1. **Stage 1 - Build**: Installs dependencies with layer caching (`package.json` copied first), installs the pinned `@docmd/core` version, and runs `docmd build`. 2. **Stage 2 - Serve**: Copies the built output into a minimal `nginx:alpine` container. ```dockerfile # Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN if [ -f package.json ]; then npm install --ignore-scripts; fi COPY . . RUN npm install -g @docmd/core@0.7.2 RUN docmd build # Stage 2: Serve FROM nginx:alpine COPY --from=builder /app/site /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ::: callout tip "Custom Nginx with Docker" If you generate an `nginx.conf` (via `docmd deploy --nginx`) before generating the Dockerfile, it will be detected and automatically configured inside the container. ::: ### The `.dockerignore` A `.dockerignore` is generated alongside the Dockerfile to keep the build context lean: ``` node_modules site dist .git .env *.md !docs/**/*.md ``` ## Build and Run ```bash docker build -t my-docs . docker run -p 8080:80 my-docs ``` Your documentation is now live at `http://localhost:8080`. ### Re-Generating Changed your config? Just run `docmd deploy --docker` again - the files are always regenerated to match your current `docmd.config.js`. --- ## [Deployment](https://docs.docmd.io/07/deployment/) --- title: "Deployment" description: "Deploy your docmd documentation to Docker, Nginx, Caddy, or any cloud platform with a single command." --- `docmd` generates a high-performance static website. Run the build command to generate the output directory: ```bash docmd build ``` The output is a self-contained `site/` folder (or whatever you've configured as `out` in your config) that can be hosted anywhere. ## One-Command Deployment ::: callout tip "New in v0.7.2" `docmd deploy` reads your `docmd.config.js` and generates deployment files personalised to your project - no generic templates. ::: Instead of manually writing Dockerfiles and server configs, let docmd generate them for you: ```bash docmd deploy --docker # Dockerfile + .dockerignore docmd deploy --nginx # Production nginx.conf docmd deploy --caddy # Production Caddyfile ``` ### What Gets Personalised The deploy command reads your configuration (or zero-config defaults) and injects: | Config Field | Used In | |:--|:--| | `title` | Comment headers in every generated file | | `out` | `COPY` paths in Dockerfile, `root` directives in Nginx/Caddy | | `url` | `server_name` in Nginx, site address in Caddy | | `layout.spa` | Controls whether SPA routing fallback is included | | Config file path | Dockerfile build step uses `--config` when non-default | No `docmd.config.js`? No problem - the command uses the same zero-config defaults as `docmd dev` and `docmd build`. ### Always In Sync Every run regenerates your deployment files to match your current config. Changed your site URL or output directory? Just re-run the deploy command - no need to manually track what changed. Use `--force` only if you intentionally want to suppress any future confirmation prompts. By default, files are silently regenerated. ### Supported Targets * [`docmd deploy --docker`](docker.md) - Optimised multi-stage Dockerfile with layer caching and version pinning. * [`docmd deploy --nginx`](nginx.md) - Security-hardened nginx.conf with GZIP and immutable asset caching. * [`docmd deploy --caddy`](caddy.md) - HTTPS-ready Caddyfile with automatic routing. Click each target above for detailed, service-specific documentation. *(Cloud deployment targets like `--vercel` and `--netlify` are planned for a future release.)* ## Cloud Hosting & CI/CD If you prefer managed hosting over self-hosted servers, deploy your output folder directly to GitHub Pages, Vercel, Netlify, or Cloudflare Pages. See the [CI/CD Deployment Guide](ci-cd.md) for automated workflows. ## SPA Routing `docmd` implements a micro-SPA router for smooth internal navigation. Every page is generated as its own `index.html` file, so: - **No rewrite rules needed** - direct URL access works because `/guide/setup` resolves to `/guide/setup/index.html`. - **Deep linking works** - out of the box, on every hosting platform. When `layout.spa` is set to `false` in your config, the deploy command omits SPA fallback routing from generated server configs. ## Production Checklist 1. **Site URL**: Set the `url` property in `docmd.config.js` - this drives canonical tags, sitemaps, social previews, and deployment file generation. 2. **Redirects**: Migrating from another tool? Use the `redirects` config to preserve SEO rankings. 3. **Analytics**: Enable the `analytics` plugin to track engagement and search queries. 4. **AI Context**: Enable the `llms` plugin to generate `llms.txt` for AI agent ingestion. ::: callout tip "Custom 404 Pages" `docmd` generates a `404.html` in your output directory. Most hosting providers automatically serve this for missing routes. ::: --- ## [NGINX](https://docs.docmd.io/07/deployment/nginx/) --- title: "NGINX" description: "Deploy docmd with a production-ready NGINX configuration." --- NGINX is one of the most reliable web servers available. Because `docmd` output is entirely static, NGINX can serve it with near-zero latency. ## Generate nginx.conf ```bash docmd deploy --nginx ``` This generates an `nginx.conf` personalised to your project: - **`server_name`** is set to the hostname extracted from your `url` config (falls back to `localhost` if not set) - **SPA fallback** (`try_files ... /index.html`) is only included when `layout.spa` is `true` in your config - **Security headers**, GZIP compression, and immutable asset caching are included by default ### What Gets Generated ```nginx server { listen 80; server_name docs.example.com; root /usr/share/nginx/html; index index.html; # Security server_tokens off; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; # GZIP Compression gzip on; gzip_vary on; gzip_min_length 256; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; # SPA Routing Fallback (only when layout.spa is true) location / { try_files $uri $uri/ /index.html; } # Custom 404 error_page 404 /404.html; # Cache Static Assets (6 months, immutable) location ~* \.(?:ico|css|js|gif|jpe?g|png|webp|avif|woff2?|eot|ttf|otf|svg)$ { expires 6M; access_log off; add_header Cache-Control "public, immutable"; } } ``` ## Deployment Steps 1. Build your site: `docmd build` 2. Upload the contents of your output directory to your server's web root (e.g., `/var/www/html/` or `/usr/share/nginx/html/`). 3. Place the generated `nginx.conf` into your server's configuration (e.g., `/etc/nginx/conf.d/default.conf`). 4. Restart NGINX: `sudo systemctl restart nginx` ### Re-Generating Changed your site URL or switched off SPA mode? Just run `docmd deploy --nginx` again - the config file is regenerated to match your current `docmd.config.js`. --- ## [Installation](https://docs.docmd.io/07/getting-started/installation/) --- title: "Installation" description: "Install docmd globally, locally, or run it instantly with npx. Requires Node.js 18+." --- Choose the installation method that fits your workflow. ## Install as a project dependency (recommended) ::: tabs == tab "npm" icon:package ```bash npm install -D @docmd/core npx @docmd/core init ``` == tab "pnpm" icon:boxes ```bash pnpm add -D @docmd/core pnpm dlx @docmd/core init ``` == tab "yarn" icon:scroll ```bash yarn add -D @docmd/core yarn dlx @docmd/core init ``` == tab "Bun" icon:zap ```bash bun add -D @docmd/core bunx @docmd/core init ``` ::: This pins the version across your team and CI/CD pipeline. ::: callout tip "After local install" Once `@docmd/core` is a project dependency, use `docmd` (or `npm docmd`, `yarn docmd`, `bun docmd`) instead of `npx @docmd/core` for all commands. ::: ## Install globally ::: tabs == tab "npm" icon:package ```bash npm install -g @docmd/core ``` == tab "pnpm" icon:boxes ```bash pnpm add -g @docmd/core ``` == tab "yarn" icon:scroll ```bash yarn global add @docmd/core ``` == tab "Bun" icon:zap ```bash bun add -g @docmd/core ``` ::: ```bash # Use the 'docmd' command anywhere docmd dev docmd build ``` ## Browser-only integration ::: callout info "Library use only" This method embeds the docmd rendering engine into another web application. It is not the standard way to build documentation sites. ::: ```html <!-- Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- Processing Engine --> <script src="https://unpkg.com/@docmd/live/dist/docmd-live.js"></script> ``` See the [Browser API](../api/browser-api.md) guide for integration details. ## Troubleshooting ::: callout warning "Permission denied (EACCES)" If you encounter `EACCES` errors during global installation on macOS or Linux, switch to a Node version manager like [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm) instead of using `sudo`. ::: ::: callout info "PowerShell script execution (Windows)" If PowerShell blocks script execution, run as Administrator: `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` ::: --- ## [Project Structure](https://docs.docmd.io/07/getting-started/project-structure/) --- title: "Project Structure" description: "Learn how docmd maps physical folders and Markdown files to dynamic URLs and clean navigation." --- The compiler uses your local filesystem as the source of truth. Folders become navigation sections. Markdown files become content pages. Your directory hierarchy translates directly into web URLs. ## 1. Standard Project Scaffold Scaffolding a default project establishes a minimal workspace layout. This structure keeps source content separated from assets and production builds. ```text my-docs/ ├── docs/ ← Source directory containing your Markdown (.md) pages │ └── index.md ← The landing page (resolves to /) ├── assets/ ← Static web assets loaded directly by the engine │ ├── css/ ← Custom stylesheets for customising page layout │ ├── js/ ← Custom scripts to extend browser-side logic │ └── images/ ← Brand logos, icons, and inline illustrations ├── docmd.config.json ← Central configuration script ├── package.json ← Node dependency manifest and scripts └── site/ ← Generated production build output folder ``` ::: callout info "Configuration File Resolution" icon:settings `docmd.config.json` (or `docmd.config.ts`) is the recommended, primary configuration format. The legacy `docmd.config.js` format remains supported but acts strictly as a fallback when `.json` or `.ts` configuration files are missing. ::: ## 2. Directory and URL Mapping The compiler maps files within your source folder directly to public URLs. There are no trailing `.html` extensions or complex routing rules. | Source File | Resolved URL Path | Purpose | | :--- | :--- | :--- | | `docs/index.md` | `/` | Home Landing Page | | `docs/api.md` | `/api` | Main API Reference | | `docs/guides/setup.md` | `/guides/setup` | Sub-section Technical Guide | ::: callout tip "Automatic Header Parsing" If a file lacks a `title` in its YAML frontmatter, the engine extracts the first `H1` tag (`# Heading`). This title represents the page in breadcrumb navigation and search. ::: ## 3. Workspace Monorepo Structure For complex layouts or large projects with multiple distinct products (such as a core platform, an SDK, and a CLI tool), `docmd` natively supports a **Workspace Monorepo** directory structure. This allows you to manage multiple independent documentation sites from a single root repository while maintaining unified branding. ```text my-docs-monorepo/ ├── docmd.config.json ← Root configuration (defines global settings) ├── assets/ ← Shared global assets (inherited by all projects) │ ├── css/ ← Shared global stylesheets │ └── images/ ← Shared logos and icons ├── package.json ← Root dependency manifest ├── main-site/ ← Root project directory │ ├── docmd.config.json ← Project-specific config overrides │ └── docs/ ← Content for main-site (resolves to /) │ └── index.md └── sdk-reference/ ← Secondary project directory ├── docmd.config.json ← Project-specific config overrides └── docs/ ← Content for sdk-reference (resolves to /sdk) └── index.md ``` ### Key Workspace Directory Patterns * **Global Configuration Cascading:** Any configuration defined in the root `docmd.config.json` (such as `theme` or `menubar`) acts as a fallback default. Individual projects can selectively override these defaults in their own local config files. * **Asset Sharing and Priority:** Shared logos, global custom styles, and common scripts are placed in the root `assets/` directory. Projects can also define their own local `assets/` directories; in the event of filename conflicts, project-specific assets always take precedence. * **Output Consolidation:** During the build process (`npx @docmd/core build`), the engine automatically merges all projects into a single consolidated production output directory (e.g. `./site/` and `./site/sdk/`), negating the need for complex reverse proxy setups or isolated build pipeline configuration. --- ## [Quick Start](https://docs.docmd.io/07/getting-started/quick-start/) --- title: "Quick Start" description: "Go from an empty folder to a running documentation site in under a minute." --- Run docmd inside any folder containing Markdown files. No config file, no setup, no framework knowledge required. ## Start a dev server ::: tabs == tab "npm" icon:box ```bash npx @docmd/core dev ``` == tab "Bun" icon:zap ```bash bunx @docmd/core dev ``` ::: Opens `http://localhost:3000`. Your documentation is live. ## What happens automatically docmd scans your project and sets everything up: 1. **Directory detection** - looks for `docs/`, `src/docs/`, `documentation/`, or any `.md` files 2. **Navigation generation** - builds a nested sidebar from your folder structure 3. **Metadata extraction** - reads `package.json` for the site title if available 4. **Theme activation** - applies the default theme with system-aware light/dark mode 5. **Search indexing** - enables built-in full-text search No `docmd.config.js` is needed. Add one later when you need versioning, plugins, or custom navigation. ## Build for production ::: tabs == tab "npm" icon:box ```bash npx @docmd/core build ``` == tab "Bun" icon:zap ```bash bunx @docmd/core build ``` ::: Outputs a static site to `./site/`, ready to deploy anywhere. --- ## [Context Preservation for AI-Friendly Documentation](https://docs.docmd.io/07/guides/ai-optimisation/context-preservation/) --- title: "Context Preservation for AI-Friendly Documentation" description: "How to ensure that AI models can understand and utilise the relationships between different parts of your documentation." --- ## Problem While human readers can easily click a hyperlink to learn more about a term, AI models often process documentation in isolated "chunks." When an AI encounters a hyperlink, it cannot "click" it to fetch more context. If critical information is hidden behind a link rather than explained in context, the AI may fail to provide accurate answers, leading to hallucinations. ## Why it matters AI models rely on the immediate surrounding text to determine the meaning and relevance of information. If your documentation is highly fragmented with poor context preservation, AI-driven search tools (like those powered by RAG) will struggle to provide high-quality responses. ## Approach Use **Inline Context Unrolling** to provide the minimum viable context alongside every major link. Additionally, use `docmd`'s specific features, such as the [LLMs Plugin](../../plugins/llms.md), to provide a unified, machine-readable view of your entire documentation set. ## Implementation ### 1. Descriptive Linking and Summaries Avoid generic link text. Instead, provide a brief, one-sentence summary of the linked concept before or after the link itself. - **❌ Poor (Context Lost)**: To configure the timeout, refer to the [General Configuration](../../configuration/overview.md). - **✅ Better (Context Preserved)**: You can configure the `timeoutMs` parameter within the [General Configuration](../../configuration/overview.md), which defines how long the engine waits before failing a network request. ### 2. Using Collapsible Sections for Detail [Collapsible Containers](../../content/containers/collapsible.md) are excellent for AI optimisation. The content remains part of the raw Markdown source (which the AI can read), but it is visually tucked away for human readers. ```markdown ### Database Connection Connect using the primary URI. ::: collapsible "What is the URI format?" The URI follows the standard PostgreSQL format: `postgresql://user:password@host:port/database`. ::: ``` ### 3. Enabling the LLMs Plugin Enable the [LLMs Plugin](../../plugins/llms.md) in your `docmd.config.js`. This plugin automatically generates a `llms-full.txt` file after every build, which concatenates your entire documentation set into a single, high-context file that can be easily consumed by Large Language Models. ## Trade-offs Inline context unrolling makes your documentation slightly more verbose and introduces minor redundancy. However, this redundancy is a small price to pay for ensuring that your documentation is "AI-ready" and capable of powering high-quality automated support and search experiences. --- ## [Creating Deterministic and Chunkable Documentation](https://docs.docmd.io/07/guides/ai-optimisation/deterministic-chunkable-docs/) --- title: "Creating Deterministic and Chunkable Documentation" description: "How to structure your documentation to optimise it for Retrieval-Augmented Generation (RAG) and AI ingestion." --- ## Problem When AI pipelines (such as RAG architectures) ingest documentation, they slice the Markdown source into smaller "chunks" (e.g., 500 tokens each). If a document consists of long, meandering paragraphs with unclear boundaries, the slicing algorithm may split the context mid-thought, destroying the utility of the chunk and leading to incomplete or incorrect AI responses. ## Why it matters If an AI retrieves a chunk containing a code block but misses the preceding paragraph explaining *when* to use that code, the generated answer will lack necessary conditionality. Structuring your documentation for chunkability ensures that each segment of text contains enough context to be useful on its own. ## Approach Structure your pages as a hierarchy of deterministic, atomic blocks. Use Markdown headers to clearly delineate concepts and ensure that related information (like a warning and the code it applies to) is kept physically close together in the source file. ## Implementation ### 1. Atomic Header Sections Ensure that every `##` or `###` header encapsulates a single, atomic concept. A well-structured section should be able to stand alone as a useful chunk for an AI model. - **✅ Good**: A header "Authentication via OAuth" followed by a brief explanation and a code example. - **❌ Poor**: A massive "Getting Started" page with 15 different concepts and no sub-headers. ### 2. Tight Proximity for Critical Information Do not separate a critical warning from the code it applies to with long paragraphs. Use [Callouts](../../content/containers/callouts.md) to bind them together vertically. This increases the probability that they will remain in the same vector chunk during ingestion. ```markdown ::: callout warning "Destructive Action" Running this command will permanently delete all logs. ::: `docmd logs --clear` ``` ### 3. Automated Concatenation The [LLMs Plugin](../../plugins/llms.md) facilitates chunking by generating a `llms-full.txt` file. This file uses standard separators (`---`) between pages, helping ingestion pipelines recognise natural document boundaries while preserving the global context of your project. ## Trade-offs This approach favours a modular, segmented writing style over long, flowing narratives. While this may feel more repetitive to a human reader, it significantly improves the performance of AI-powered search and automated support agents that rely on your documentation. --- ## [Generating AI-Ready Documentation with docmd](https://docs.docmd.io/07/guides/ai-optimisation/generating-ai-ready-docs/) --- title: "Generating AI-Ready Documentation with docmd" description: "How to use the llms.txt standard and docmd's built-in tools to provide optimised context for AI assistants." --- ## Problem Developers increasingly rely on AI coding assistants (like Cursor, GitHub Copilot, and ChatGPT) to read and interpret documentation on their behalf. If your documentation is only accessible via a web browser and is cluttered with navigation elements, trackers, and complex HTML, AI agents will consume excessive tokens on irrelevant data, quickly exhausting their context windows. ## Why it matters Providing a clean, token-optimised text version of your documentation is the modern equivalent of providing a high-quality REST API. It ensures that AI agents can quickly ingest your entire documentation set, resulting in more accurate code suggestions and better support for developers using your product. ## Approach Use `docmd`'s built-in **LLMs Plugin**. This plugin natively implements the emerging `llms.txt` standard, automatically generating token-optimised summaries and full-context files during every build process. ## Implementation The `llms` plugin is available in `docmd >= 0.7.0` and can be configured in your [Plugin Configuration](../../plugins/llms.md). ### 1. Configure the Site URL Ensure that the `url` property is correctly set in your `docmd.config.js`. This allows the plugin to generate absolute URLs for all pages in the `llms.txt` file. ```javascript // docmd.config.js export default { title: 'My Project Docs', url: 'https://docs.example.com', plugins: ['llms'] }; ``` ### 2. Output Files During the build process, `docmd` generates two key files in your site root: - **`llms.txt`**: A concise, structured Markdown summary of all your pages, including their titles, descriptions, and full URLs. - **`llms-full.txt`**: A comprehensive file containing the raw Markdown content of your entire site, concatenated with standard separators (`---`). This provides the ultimate "source of truth" for AI models. ### 3. Controlling Ingestion You can exclude specific pages from the AI-ready output by using the `llms` property in the [Page Frontmatter](../../content/frontmatter.md). ```yaml --- title: "Internal Debugging Guide" llms: false --- ``` ## Trade-offs Generating `llms-full.txt` creates a large single file. For exceptionally large documentation sites, this file could exceed several megabytes. While this is ideal for modern LLMs with large context windows (like Gemini 1.5 Pro or Claude 3.5 Sonnet), it may be too large for smaller models. Ensure you organise your [Navigation](../../configuration/navigation.md) logically so that the AI can prioritise the most important sections. --- ## [Minimising AI Hallucinations via Documentation](https://docs.docmd.io/07/guides/ai-optimisation/minimising-ai-hallucinations/) --- title: "Minimising AI Hallucinations via Documentation" description: "How to write explicit, self-contained documentation that prevents AI models from inventing incorrect information." --- ## Problem AI models are predictive engines, not reasoning engines. If an API usage example is incomplete, uses ambiguous placeholders, or relies on implicit knowledge, the AI will often "hallucinate" - it will invent the missing pieces based on general patterns it learned during training. These inventions are frequently incorrect for your specific software, leading to developer frustration. ## Why it matters Hallucinated code destroys user trust. When a developer asks an AI for help and receives code that throws a syntax error or uses non-existent parameters, they often blame the software itself for being "buggy" or "poorly documented." Minimising hallucinations is critical for maintaining the professional reputation of your project. ## Approach Practice **Defensive Documentation**. This involves writing extremely explicit, fully instantiated code blocks that leave no room for ambiguity. Never assume that the reader (or the AI) knows the necessary imports, environment variables, or prerequisite configurations. ## Implementation ### 1. Fully-Qualified Code Blocks Always include the necessary imports or setup code in every snippet. This ensures that when an AI chunks your documentation, the code block remains a self-contained unit of truth. - **❌ Hallucination Risk**: ```javascript const config = loadConfig(); // Where does loadConfig come from? ``` - **✅ Hallucination Proof**: ```javascript import { loadConfig } from '@docmd/core'; const config = loadConfig(); ``` ### 2. Concrete Examples Over Placeholders Avoid using vague placeholders like `your-api-key` or `env-name`. Instead, provide concrete, valid examples or use comments to specify strict enum requirements. ```javascript // Valid environments: "development", "staging", "production" const app = init({ env: "production" }); ``` ### 3. Inline Code Comments Place critical requirements *inside* the code block as comments, rather than only in the surrounding Markdown text. AI models weigh comments within code highly when generating similar snippets. ```javascript export default { // CRITICAL: The outputPath must be an absolute filesystem path. outputPath: '/var/www/html/docs' }; ``` ### 4. Categorised Warnings Use [Callouts](../../content/containers/callouts.md) to clearly mark deprecated features or breaking changes. AI models are more likely to respect a `::: callout warning` block than a simple sentence in a paragraph. ## Trade-offs Defensive documentation makes code blocks longer and more repetitive. Human readers may find seeing the same `import` statements in every snippet slightly tedious. However, the benefit of having "AI-proof" documentation that significantly reduces support tickets and user errors far outweighs the minor cost of verbosity. --- ## [Designing for Semantic Search and RAG](https://docs.docmd.io/07/guides/ai-optimisation/semantic-search-design/) --- title: "Designing for Semantic Search and RAG" description: "How to structure your documentation to optimise it for vector-based search and Retrieval-Augmented Generation." --- ## Problem Traditional keyword search (like [docmd's built-in search](../../plugins/search.md)) relies on exact text matches. If a user searches for "authentication," a basic keyword engine might fail to find a page titled "Integrating OAuth2" if that specific word doesn't appear frequently enough. Semantic search, which uses vector embeddings to understand the *meaning* of a query, solves this problem but requires specific documentation structures to be effective. ## Why it matters Modern developers expect intuitive, intent-based search experiences. If your documentation fails to surface relevant content because of minor terminology differences, users will quickly abandon your site and seek help elsewhere. Designing for semantic search ensures that your documentation remains discoverable even when users use varied terminology. ## Approach Structure your documentation to be easily consumed by Retrieval-Augmented Generation (RAG) pipelines. This involves creating "semantically dense" content where concepts are clearly defined, and pronouns are replaced with explicit entities to preserve context during the chunking and vectorization process. ## Implementation ### 1. Rich Frontmatter Metadata Use [Frontmatter](../../content/frontmatter.md) to provide explicit keywords and descriptions that might not be used naturally in the body text. This gives the search engine extra "hooks" into your content. ```yaml --- title: "Integrating OAuth2" description: "Learn how to implement secure user authentication and SSO." keywords: ["login", "authentication", "sso", "security", "identity"] --- ``` ### 2. The "Semantic Density" Strategy RAG systems slice documents into small chunks (vectors). The first paragraph of every section should contain the highest density of relevant nouns and verbs related to that topic. This ensures the primary "meaning" of the section is captured in the initial vector. - **✅ Good**: "This guide explains how to implement **OAuth2 Single Sign-On (SSO)** to provide secure **authentication** for your documentation site." - **❌ Poor**: "In this section, we'll talk about how it works and how you can set it up easily." ### 3. Avoiding Pronoun Ambiguity In a chunked database, a sentence like "It works with any provider" is useless if the preceding paragraph defining "It" was sliced into a different chunk. Be explicit. - **❌ Ambiguous**: "It is highly scalable." - **✅ Explicit**: "The **docmd Search Engine** is designed to be highly scalable." ## Trade-offs Writing for semantic density can sometimes feel slightly more formal or repetitive than traditional narrative writing. However, the resulting improvement in discoverability and the accuracy of AI-generated responses makes this a vital practice for modern, enterprise-grade documentation. --- ## [Structuring Documentation for AI Agents](https://docs.docmd.io/07/guides/ai-optimisation/structure-for-llms/) --- title: "Structuring Documentation for AI Agents" description: "How to move from visual formatting to semantic structuring to improve the accuracy of AI coding assistants." --- ## Problem Human readers rely on visual cues, sidebar navigation, and inferred context to understand documentation. AI agents and Large Language Models (LLMs), however, primarily consume raw text streams. When documentation lacks a rigorous semantic structure, these models struggle to map relationships between concepts, leading to poor reasoning and inaccurate coding suggestions. ## Why it matters If your documentation is not optimised for LLMs, developers using tools like GitHub Copilot, Cursor, or ChatGPT will receive more hallucinations when working with your software. This directly degrades the developer experience, as users often blame the product itself for the errors generated by their AI assistants. ## Approach Transition from a "visual-first" mindset to a **"semantic-first"** mindset. Use standard Markdown features - such as strict header hierarchies, explicit code block language tags, and descriptive alt text - to provide a clear, machine-readable roadmap of your content. `docmd` processes this structure into optimised outputs via the [LLMs Plugin](../../plugins/llms.md). ## Implementation ### 1. Strict Header Hierarchy Avoid skipping header levels for purely visual effects. A consistent hierarchy allows LLMs to understand the scope and relationship of different sections. - **`#` Title**: The primary subject of the page. - **`##` Major Concept**: An atomic, high-level topic. - **`###` Detail**: A specific sub-task or property of that concept. * **❌ Poor**: Using `###` immediately after `#` because you like the smaller font size. * **✅ Good**: `# Installation` followed by `## Prerequisites` and then `### System Requirements`. ### 2. Descriptive Metadata for Media Since LLMs cannot "see" images or diagrams, you must provide the architectural context in the alternative text or an adjacent paragraph. ```markdown ![System Architecture: The frontend React application communicates with the Node.js API via REST, which then queries a Redis cache and a PostgreSQL database.](../../static/img/architecture.png) ``` ### 3. Explicit Code Block Labeling Always specify the language for every fenced code block using [Syntax Highlighting](../../content/syntax/index.md). This allows LLMs to parse the code's Abstract Syntax Tree (AST) correctly. ```javascript // docmd.config.js export default { plugins: ['llms'] }; ``` ### 4. Semantic Containers Use [Callouts](../../content/containers/callouts.md) rather than generic blockquotes to provide intent. `docmd`'s semantic containers help AI models distinguish between core instructions and supplementary tips or warnings. ## Trade-offs Semantic rigor requires authors to be disciplined. You can no longer use Markdown features (like blockquotes or headers) as purely decorative elements. However, this discipline results in documentation that is significantly more accessible to both AI agents and human readers using assistive technologies. --- ## [Avoiding Anti-Patterns](https://docs.docmd.io/07/guides/content-ux/avoiding-anti-patterns/) --- title: "Avoiding Anti-Patterns" description: "How to identify and eliminate common documentation mistakes that degrade the user experience and increase content debt." --- ## Problem Over time, documentation repositories often accumulate "quick fixes" to content problems that inadvertently erode the user experience. These anti-patterns - such as vague link text or bloated code samples - become entrenched in the project, making the documentation harder to maintain and less useful for developers. ## Why it matters Anti-patterns contribute to "content debt." They degrade search engine rankings (SEO), reduce accessibility for users with disabilities, and significantly increase the cognitive load on readers who are simply trying to find a quick solution to a technical problem. High-quality documentation requires constant vigilance to keep it clean, concise, and professional. ## Approach Identify and ruthlessly eliminate common anti-patterns during the [Peer Review process](../workflows-teams/git-based-workflows.md). Use automated prose linters like Vale and manual reviews to ensure your content remains high-quality, accessible, and consistent across all pages. ## Implementation ### 1. Non-Descriptive Hyperlinks Avoid using generic text like "click here" or "read more" for links. This is harmful to SEO and makes the documentation inaccessible for screen reader users who often navigate by skipping between links. * **❌ Bad**: To configure your server, [click here](../../configuration/overview.md). * **✅ Good**: Review the [General Configuration](../../configuration/overview.md) to set up your production server. ### 2. The "Wall of Boilerplate" In code examples, including dozens of lines of standard imports and boilerplate configuration before the core logic distracts the reader from the actual point of the example. * **Solution**: Focus on the relevant code snippet. If boilerplate is necessary for context, use comments to indicate that standard imports are omitted for brevity, or use [Callouts](../../content/containers/callouts.md) to explain the required setup. ### 3. Using FAQs as "Dumping Grounds" "Frequently Asked Questions" (FAQ) pages often become a repository for information that was too difficult to integrate into the main guides. If a question is truly "frequently asked," it is a clear sign that your core documentation has failed to explain that concept effectively. * **Solution**: Instead of adding to an FAQ, refactor the relevant tutorial or conceptual guide to address the confusion directly where the user first encounters it. Use an [Important Callout](../../content/containers/callouts.md) if the information is critical for success. ## Trade-offs Eliminating FAQs requires writers to constantly refactor and improve existing documentation hierarchies as new support issues are discovered. While this adds more initial maintenance overhead than simply appending a bullet point to an FAQ list, it results in a significantly more cohesive, professional, and useful documentation site for your users. --- ## [Improving Readability](https://docs.docmd.io/07/guides/content-ux/improving-readability/) --- title: "Improving Readability" description: "How to use visual rhythm, information hierarchy, and docmd's structural tools to create highly readable documentation." --- ## Problem Technical documentation is often dense, jargon-heavy, and difficult to scan. When readers encounter "walls of text" without visual relief, they tend to skim over important details or miss critical safety warnings entirely. Dense formatting increases cognitive friction and leads to user frustration and potential errors. ## Why it matters Readability is not just an aesthetic choice - it is a functional requirement. If a developer misses a warning because it was buried in a long paragraph, the consequences can be severe. A clear information hierarchy ensures that users can find the information they need quickly, understand it accurately, and act upon it safely. ## Approach Establish a predictable visual rhythm by breaking up long sections of text and using [Thematic Containers](../../content/containers/index.md) to highlight critical information. By utilising `docmd`'s built-in structural tools, you can create a hierarchy that guides the reader's eye naturally toward the most important parts of the page. ## Implementation ### 1. The "Power of Brevity" Try to limit paragraphs to no more than three or four sentences. Shorter paragraphs are easier to digest on screens and provide natural "breathing room" for complex technical concepts. If a paragraph feels too long, consider breaking it into a list or using a sub-heading to re-categorise the information. ### 2. Categorising with Callouts Use [Callouts](../../content/containers/callouts.md) consistently to categorise information. This allows users who are skimming to instantly recognise the intent of a block based on its visual style: * **Info**: Background context or supplementary details that provide deeper understanding. * **Tip**: Best practices, shortcuts, and "pro-tips" for efficiency. * **Warning/Danger**: Critical actions that could lead to errors, data loss, or security vulnerabilities. ```markdown ::: callout warning "Production Safety" Never execute this command on a live database without verifying your backups first. ::: ``` ### 3. Sequential Instruction with Steps For tutorials and step-by-step guides, avoid narrative descriptions of actions. Instead, use the [Steps Container](../../content/containers/steps.md) to create a clear, numbered progression that is easy to follow. ```markdown ::: steps 1. **Initialise**: Run `npx @docmd/core init` in your project root. 2. **Configure**: Update your `docmd.config.js` with your site title and navigation. 3. **Build**: Run `npx @docmd/core build` to generate your production-ready static files. ::: ``` ## Trade-offs Using specialised containers like `::: steps` or `::: callout` requires contributors to learn `docmd`-specific Markdown extensions. While this adds a small learning curve, the significant improvement in information density, clarity, and professional presentation far outweighs the minimal effort of learning these powerful structural tags. --- ## [Navigation for Large Sites](https://docs.docmd.io/07/guides/content-ux/navigation-large-sites/) --- title: "Navigation for Large Sites" description: "How to organise complex documentation sets into an intuitive, scalable navigation structure using docmd's layout tools." --- ## Problem As a documentation site grows from a few dozen pages to hundreds or thousands, a simple sidebar often transforms into a confusing labyrinth of deeply nested folders. When users are forced to expand multiple levels of hierarchy just to find a specific reference, they lose context, become frustrated, and often abandon the documentation in favour of trial-and-error. ## Why it matters Navigation is the "map" of your product's capabilities. If navigation is difficult to use, users will rely exclusively on the search bar, which can lead to fragmented knowledge. A well-structured navigation system teaches the user the logic and taxonomy of your product as they browse, helping them become more proficient and self-sufficient over time. ## Approach Prioritise **Top-Level Context Switching** over deep nesting. Aim to keep your left sidebar limited to no more than two or three levels of depth. Use the horizontal [Menubar](../../configuration/menubar.md) to separate distinct documentation "domains" (e.g., Guides, API Reference, and Community), which allows each individual sidebar to remain focused, relevant, and manageable. ## Implementation ### 1. Domain-Based Separation In your `docmd.config.js`, use the [Menubar](../../configuration/menubar.md) to divide your content into high-level categories. This approach allows you to present a completely different sidebar for each domain, preventing a single navigation tree from becoming overwhelmed. ### 2. Flattening the Hierarchy Instead of splitting a single concept across many tiny Markdown pages, consolidate related information into comprehensive parent pages. Use clear [Heading Hierarchy](../../content/syntax/index.md) to allow users to navigate within the page using the auto-generated right-side Table of Contents (TOC). * **❌ Poor IA**: A folder named "Security" containing ten separate, one-paragraph files for different protocols. * **✅ Better IA**: A single, well-structured "Security Overview" page that covers all protocols, using headings to provide a clean TOC. ### 3. Using Collapsible Sections For large groups of related content that aren't accessed constantly, use the `collapsible` property in your [Navigation Configuration](../../configuration/navigation.md). This keeps the interface clean by hiding secondary information until it is explicitly requested by the user. ```json // navigation.json { "title": "API Reference", "collapsible": true, "collapsed": true, "children": [ { "title": "Authentication", "path": "api/auth" }, { "title": "Endpoints", "path": "api/endpoints" } ] } ``` ## Trade-offs Consolidating content into fewer, longer pages requires authors to be disciplined about structural clarity and heading use. If a page becomes too long without proper internal navigation (TOC), it can become its own "wall of text." However, the significant reduction in "click-fatigue" and the improved discovery of related content make a flatter, domain-based hierarchy far better for large documentation sets. --- ## [Scalable Technical Writing](https://docs.docmd.io/07/guides/content-ux/scalable-technical-writing/) --- title: "Scalable Technical Writing" description: "How to use Progressive Disclosure and structural containers to manage growing documentation complexity without overwhelming your users." --- ## Problem In the early stages of a product, documenting a feature might only take a few paragraphs. However, as the product evolves into an enterprise platform, those paragraphs can explode into a sea of edge cases, platform-specific variations (Docker, Kubernetes, Cloud), and complex configuration options. This results in "vertical bloat," where a single page becomes an unreadable wall of text that is difficult to navigate and maintain. ## Why it matters Vertical bloat destroys comprehension and increases cognitive load. When users are forced to scroll through pages of content that is irrelevant to their specific environment or use case, they become overwhelmed and often assume the product is more complex than it actually is. Scalable writing ensures that users only see the information they need at any given moment, maintaining a clear path to success. ## Approach Implement **Progressive Disclosure**. This technique involves presenting only the most critical information upfront (the "Happy Path") and hiding more complex, technical, or specific details behind interactive UI structures. `docmd` provides several built-in containers specifically designed to help you manage this complexity effectively and elegantly. ## Implementation ### 1. Handling Variations with Tabs Instead of listing instructions for multiple package managers, operating systems, or cloud providers sequentially, use the [Tabs Container](../../content/containers/tabs.md). This allows the user to select their specific environment, instantly hiding irrelevant commands and reducing visual noise. ````markdown ::: tabs == tab "npm" ```bash npm install docmd ``` == tab "pnpm" ```bash pnpm add docmd ``` ::: ```` ### 2. Managing Edge Cases with Collapsibles If a troubleshooting step or a specific edge case only applies to a small percentage of users, do not let it interrupt the logical flow of your main tutorial. Use the [Collapsible Container](../../content/containers/collapsible.md) to bury these details while keeping them easily accessible when needed. ```markdown 1. Start the development server by running `npx @docmd/core dev`. ::: collapsible "Troubleshooting: Port already in use" If you receive an `EADDRINUSE` error, you can specify a custom port using the `--port` flag: `npx @docmd/core dev --port 4000`. ::: ``` ### 3. Progressive Detail with Callouts Use [Callouts](../../content/containers/callouts.md) to provide supplementary information that isn't required for the primary task but offers valuable context for advanced users. ## Trade-offs Hiding content inside tabs or collapsibles can occasionally make it harder for users to find information using the browser's native `Ctrl+F` search. However, `docmd`'s integrated [Search Engine](../../plugins/search.md) indexes all content within these containers, ensuring that users can still find exactly what they need through the site's primary search interface while enjoying a much cleaner reading experience. --- ## [Task vs. Concept](https://docs.docmd.io/07/guides/content-ux/task-vs-concept/) --- title: "Task vs. Concept" description: "How to apply the Diátaxis framework to separate 'How-To' guides from conceptual explanations for a more effective documentation structure." --- ## Problem A frequent mistake in technical writing is mixing the *Why* something works with the *How* to actually do it. A tutorial on "Configuring SSO," for example, can easily become bogged down with pages explaining the history of the SAML protocol, distracting the user from their immediate goal of getting the feature running. ## Why it matters User intent varies significantly depending on their current context. An engineer trying to fix a production issue at 2 AM is looking for specific, actionable steps, not architectural philosophy. Conversely, a technical leader evaluating your platform needs to understand the underlying logic before committing to an implementation. Separating these concerns ensures that both personas find the information they need without unnecessary friction. ## Approach Adopt the **Diátaxis framework**, which categorizes documentation into four distinct quadrants: Tutorials, How-to Guides, Explanation (Concepts), and Technical Reference. For this guide, we focus on the critical separation between **Task-oriented content** (actionable steps) and **Concept-oriented content** (deeper understanding). ## Implementation ### 1. The Task-Oriented Guide (How-To) Focus entirely on a specific, narrow objective. Strip out lengthy theoretical explanations and focus on the minimum steps required to achieve the goal. Use the [Steps Container](../../content/containers/steps.md) to provide a clear, unambiguous path forward. * **Title Example**: "How to Configure Webhooks" * **Structure**: * Prerequisites * Direct, actionable instructions * Verification steps (how to know it worked) ### 2. The Concept-Oriented Guide (Explanation) Focus on the "Big Picture," including architecture, design philosophy, and the "why" behind specific decisions. Avoid giving direct instructions or commands in these sections. * **Title Example**: "Understanding Webhook Delivery Architecture" * **Structure**: * High-level architecture diagrams * Retry logic and reliability philosophy * Security considerations ### 3. Effective Cross-Referencing Instead of merging the two types of content, use `docmd`'s linking tools to provide a bridge for users who need more context or are ready to implement. * **In a How-To guide**: "For a deeper explore our retry logic, see [Webhook Architecture](../../guides/performance-delivery/caching-strategies.md)." * **In a Conceptual guide**: "Ready to get started? Follow our [Webhook Configuration Guide](../../guides/integrations/alongside-other-tools.md)." ## Trade-offs Separating tasks and concepts increases the number of pages in your navigation and requires more rigorous cross-linking. However, this modular structure significantly improves the long-term maintainability, searchability, and overall professionalism of your documentation suite. --- ## [Customising Favicons and Metadata](https://docs.docmd.io/07/guides/customisation/custom-favicons-metadata/) --- title: "Customising Favicons and Metadata" description: "How to configure your site's visual identity in the browser and optimise social media previews." --- ## Problem A default documentation site often lacks a distinct visual identity in the browser (using a generic favicon) and provides poor previews when links are shared on social media or communication tools like Slack and Discord. This reduces brand recognition and click-through rates. ## Why it matters Your favicon is the primary visual anchor in a crowded browser window. High-quality OpenGraph and Twitter metadata ensure that your documentation looks professional and trustworthy when shared, providing context through titles, descriptions, and hero images. ## Approach `docmd` provides a built-in `favicon` property for easy icon configuration. For advanced SEO and social metadata, use the [SEO Plugin](../../plugins/seo.md), which automates the generation of meta tags based on your project configuration and page frontmatter. ## Implementation ### 1. Configuring the Favicon Place your favicon file (e.g., `favicon.svg` or `favicon.ico`) in your source directory and reference it in your `docmd.config.js`. `docmd` will automatically handle the relative pathing and cache-busting. ```javascript // docmd.config.js export default { title: 'My Project', favicon: '/favicon.svg' // Relative to source directory }; ``` ### 2. Global SEO Configuration Enable and configure the [SEO Plugin](../../plugins/seo.md) to set default social media previews for your entire site. ```javascript // docmd.config.js export default { url: 'https://docs.example.com', plugins: { seo: { defaultDescription: 'The ultimate guide to our amazing software.', openGraph: { defaultImage: '/static/og-banner.png' }, twitter: { siteUsername: '@myproject', cardType: 'summary_large_image' } } } }; ``` ### 3. Page-Specific Overrides You can override SEO settings for individual pages using the `seo` property in the [Frontmatter](../../content/frontmatter.md). ```yaml --- title: "Major Release v2.0" description: "Everything you need to know about our new engine." seo: image: "/assets/v2-hero-banner.png" keywords: ["release", "v2", "update", "performance"] --- ``` ## Trade-offs While the `favicon` property is convenient, it only supports a single file. For complex multi-size favicon sets (Apple Touch Icons, Android manifests, etc.), you may need to use a custom plugin to inject additional `<link>` tags into the `<head>`. --- ## [Custom Fonts and Branding](https://docs.docmd.io/07/guides/customisation/custom-fonts-branding/) --- title: "Custom Fonts and Branding" description: "How to match your documentation's appearance to your corporate identity using CSS variables." --- ## Problem Ensuring that your documentation platform easily matches your corporate identity is critical for maintaining a professional appearance. The default font stack and colour palette are designed for general readability but may not reflect your specific brand personality. ## Why it matters Documentation is a key brand touchpoint. If your main product uses a specific typography (like "Outfit") and a distinct primary colour, your documentation should reflect those same choices. Consistency across all your web properties builds trust and provides a more cohesive user experience. ## Approach `docmd` uses a system of CSS custom properties (variables) that define the layout's visual tokens. You can easily override these variables in a custom stylesheet without needing to modify the core engine. ## Implementation ### 1. Create a Custom Stylesheet Create a file named `custom.css` in your source directory (or any subdirectory) and override the `:root` variables. ```css /* Import your brand font */ @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;700&display=swap'); :root { /* Brand Typography */ --font-family-sans: "Outfit", system-ui, -apple-system, sans-serif; /* Brand Colours (Light Mode) */ --link-color: #8a2be2; /* Your primary brand colour */ --link-colour-hover: #7b1fa2; --bg-color: #fcfcfd; /* Subtle background tint */ } /* Dark Mode Overrides */ :root[data-theme="dark"] { --bg-color: #0d1117; --link-color: #a855f7; } ``` ### 2. Register the Stylesheet Add your custom CSS file to the `theme.customCss` array in your `docmd.config.js`. ```javascript // docmd.config.js export default { theme: { customCss: ['/custom.css'] } }; ``` ## Trade-offs Importing external fonts (like those from Google Fonts) adds a small amount of latency to the initial page load. To optimise performance, consider hosting your font files locally within your project and using `font-display: swap` to prevent "Flash of Unstyled Text" (FOUT) while the custom font is loading. --- ## [Designing Custom Landing Pages](https://docs.docmd.io/07/guides/customisation/custom-landing-pages/) --- title: "Designing Custom Landing Pages" description: "How to use docmd's hero and grid containers to create premium landing pages for your documentation." --- ## Problem By default, the `index.md` file in most documentation generators looks like a standard technical page. Creating a high-impact, marketing-grade landing page usually requires a separate web framework (like Next.js or Astro), which adds complexity to your documentation workflow. ## Why it matters Your documentation homepage is often the first interaction a developer has with your product. A generic Markdown-parsed page may fail to inspire confidence in your project's polish and professional quality. A custom landing page can better guide users to the most important sections while reinforcing your brand's visual identity. ## Approach `docmd` provides specialised [Hero](../../content/containers/hero.md) and [Grids](../../content/containers/grids.md) containers designed specifically for building premium landing pages. For total creative freedom, you can also use the `noStyle` frontmatter property to take complete control over a page's HTML and styling. ## Implementation ### 1. Using the Hero Container The `hero` container supports several layouts, including `split` (for side-by-side content) and `glow` (for a modern aesthetic). ```markdown ::: hero layout:split glow:true # Build Faster with docmd The zero-config documentation engine for modern developer teams. [Get Started](/docs/start) [View on GitHub](https://github.com/docmd-io/docmd) == side ![Dashboard Preview](../../static/img/hero-preview.png) ::: ``` ### 2. Organising Content with Grids Use [Grids and Cards](../../content/containers/grids.md) to create high-level navigation sections that help users find what they need quickly. ```markdown ::: grids ::: grid ::: card "Quick Start" icon:rocket Get up and running in less than 5 minutes. [Learn More](/docs/start.md) ::: ::: ::: grid ::: card "API Reference" icon:code Comprehensive documentation for all our endpoints. [Explore API](/api) ::: ::: ::: ``` ### 3. Full Customisation with noStyle If you need a completely custom design that ignores the standard documentation layout (no sidebar or header), use the `noStyle` property in the [Page Frontmatter](../../content/frontmatter.md). ```yaml --- title: "Custom Dashboard" noStyle: true --- ``` When `noStyle: true` is set, `docmd` will render only the raw HTML/Markdown content you provide, allowing you to inject your own CSS and JavaScript for a pixel-perfect experience. ## Trade-offs Using `noStyle: true` means you forfeit the native navigation, search, and theme-switching features provided by `docmd`. You are responsible for ensuring that the custom page is mobile-responsive and accessible. For most use cases, combining the `hero` and `grid` containers within the standard layout provides the best balance of aesthetics and functionality. --- ## [Extending docmd with Custom Plugins](https://docs.docmd.io/07/guides/customisation/extending-custom-plugins/) --- title: "Extending docmd with Custom Plugins" description: "How to use docmd's lifecycle hooks to build custom functionality and extend the documentation engine." --- ## Problem Sometimes you have a highly specific requirement that isn't covered by built-in features or existing plugins. For example, you might need to fetch data from an internal API during the build process or perform complex transformations on the generated HTML that go beyond simple CSS. ## Why it matters Extensibility is what separates a static tool from a professional documentation framework. Without a clean way to inject custom logic, teams are often forced to maintain fragile shell scripts or post-processing wrappers that make the build process difficult to manage and debug. ## Approach `docmd` features a reliable, hook-based [Plugin API](../../plugins/building-plugins.md). You can write simple Node.js modules that intercept the documentation lifecycle at various stages - from initial configuration to final HTML generation - allowing you to arbitrarily modify content and behaviour. ## Implementation ### 1. Create a Local Plugin A plugin is a standard JavaScript module that exports a descriptor and several lifecycle hooks. ```javascript // plugins/version-injector.js export default { // Plugin Metadata plugin: { name: 'version-injector', version: '1.0.0', capabilities: ['build'] // Required to use 'build' hooks }, // State shared across hooks latestVersion: '0.0.0', // Runs once the configuration is resolved async onConfigResolved(config) { // Fetch data from an internal API const response = await fetch('https://api.internal.com/version'); this.latestVersion = await response.text(); console.log(`[Plugin] Fetched version: ${this.latestVersion}`); }, // Intercepts page context before template rendering async onBeforeRender(page) { if (!page.html) return; // Replace placeholders with dynamic data in both HTML and frontmatter page.html = page.html.replace(/\{\{VERSION\}\}/g, this.latestVersion); page.frontmatter.computedVersion = this.latestVersion; } }; ``` ### 2. Register the Plugin You can register your local plugin by importing it into your `docmd.config.js`. ```javascript // docmd.config.js import VersionInjector from './plugins/version-injector.js'; export default { title: 'My Project Docs', plugins: { // Register by providing the imported module 'version-injector': VersionInjector } }; ``` ## Trade-offs Custom plugins run in the Node.js environment during build time. While powerful, they can impact build performance if not optimised. 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. --- ## [Alongside Other Tools](https://docs.docmd.io/07/guides/integrations/alongside-other-tools/) --- title: "Alongside Other Tools" description: "Strategies for integrating docmd into a multi-tool documentation ecosystem to create a seamless user experience." --- ## Problem Large organisations rarely use a single tool for all their documentation needs. Your company might use Confluence for internal specifications, Stoplight for API design, and GitHub for code examples. Integrating these disparate sources into a unified user journey is a significant challenge, as users often find themselves jumping between disconnected portals with different styles and navigation. ## Why it matters A fragmented documentation experience ruins developer trust and increases cognitive load. If a user is forced to switch between completely different interfaces just to follow a single tutorial, they are more likely to lose context or abandon your product. Unifying your tools ensures a professional, cohesive experience that encourages exploration and learning. ## Approach Use `docmd` as your primary documentation hub or "Single Pane of Glass." By using the [Menubar](../../configuration/menubar.md) for unified navigation and [Embed Containers](../../content/containers/embed.md) for third-party content, you can create a seamless interface that hides the complexity of your multi-tool infrastructure. ## Implementation ### 1. Unified Global Navigation Use the `menubar` configuration to link your various documentation portals together. This ensures that users can always find their way back to the main guides, regardless of which subdomain they are currently on. ```javascript // docmd.config.js export default { layout: { menubar: { left: [ { text: 'Guides', url: '/' }, // docmd site { text: 'API Reference', url: 'https://api.example.com' }, // External tool { text: 'Community', url: 'https://forum.example.com', external: true } ] } } }; ``` ### 2. Seamless Embedding For tools that provide a web interface (like interactive API explorers or dashboard previews), use the `::: embed` container to display them directly within your `docmd` pages. This keeps users within your branded environment. ```markdown # Interactive API Explorer ::: embed "https://api.example.com/v1/explorer" ::: ``` For more information, see the [Embed Reference](../../content/containers/embed.md). ### 3. Content Aggregation For external content that must be searchable alongside your core documentation, consider a build step that fetches data from other sources and converts it into Markdown. This allows `docmd` to index all your information in a single, unified [Search Index](../../plugins/search.md). ## Trade-offs While embedding provides a unified look, it can occasionally introduce performance overhead or "scroll-nesting" issues on mobile devices. In addition, content within an iframe is not natively indexed by `docmd`'s search engine. If search parity is critical, prioritising [OpenAPI Generation](openapi-generation.md) or other Markdown-based ingestion methods is recommended. --- ## [Existing Markdown Repos](https://docs.docmd.io/07/guides/integrations/existing-markdown-repos/) --- title: "Existing Markdown Repos" description: "How to instantly generate a professional documentation site from your existing Markdown files with zero configuration." --- ## Problem You have an established repository with hundreds or thousands of raw Markdown files - perhaps a legacy wiki, an Obsidian vault, or a collection of technical notes. Manually converting frontmatter, fixing broken links, and restructuring files to fit a new engine is a difficult task that often prevents teams from modernising their documentation. ## Why it matters Your content should remain portable and tool-agnostic. A high-quality documentation engine should adapt to your existing files, not force your files to adapt to the engine. Avoiding vendor lock-in ensures that your intellectual property remains standard, readable, and future-proof. ## Approach `docmd` adheres to strict CommonMark specifications and is designed to be **zero-config** by default. You can point the `docmd` CLI at any directory containing Markdown files, and it will intelligently bootstrap a full-featured documentation site without modifying a single line of your source content. ## Implementation ### 1. Instant Bootstrapping Navigate to your existing Markdown folder and run the development server. `docmd` will scan your directory structure and build a functional site in memory instantly. ```bash cd my-existing-docs/ npx @docmd/core dev ``` ### 2. Automatic Navigation (Auto-Router) If no `navigation.json` or `docmd.config.js` is found, `docmd` triggers its [Auto-Router](../../configuration/navigation.md#automatic-sidebar-generation). It recursively maps your folder structure, prettifies directory names (e.g., `getting-started` becomes `Getting Started`), and generates a logical sidebar taxonomy automatically. ### 3. Intelligent Title Inference You don't need to add `title` frontmatter to every file. `docmd` uses a cascading resolution strategy to determine page titles: 1. **Frontmatter**: Checks for a `title` or `h1` key. 2. **First Heading**: Extracts the first `# Heading` found in the file content. 3. **Filename**: Prettifies the filename as a fallback (e.g., `install-guide.md` becomes `Install Guide`). ### 4. Resilient Syntax Handling `docmd` is built to be resilient. If your existing files contain proprietary syntax or legacy shortcodes from other engines, they are safely rendered as raw text or skipped, ensuring that your build never fails due to content you haven't yet migrated. ## Trade-offs Automatic sidebars are typically sorted alphabetically by filename. While naming files like `01-intro.md` and `02-setup.md` works well, more descriptive filenames may appear in an unintuitive order. For production-ready sites, we recommend transitioning to a manual [Navigation Configuration](../../configuration/navigation.md) to gain full control over the user journey. --- ## [GitHub Actions CI/CD](https://docs.docmd.io/07/guides/integrations/github-actions-cicd/) --- title: "GitHub Actions CI/CD" description: "How to automate your documentation builds and deployments using GitHub Actions and docmd for a high-velocity documentation workflow." --- ## Problem Building and deploying documentation manually from a local machine is prone to errors, environment inconsistencies (e.g., differing Node.js versions), and security risks. It also creates a bottleneck, as deployments depend on a single individual's availability and local setup. ## Why it matters Continuous Deployment (CD) ensures that your documentation is always in sync with your software. When a technical update is merged, it should reach your users within minutes, not days. Automation guarantees that every build happens in a clean, reproducible environment, maintaining high standards of quality and reliability. ## Approach Use GitHub Actions to run the `docmd` build pipeline on every push or Pull Request. The resulting static assets can then be automatically deployed to hosting providers like GitHub Pages, Cloudflare Pages, or containerised environments using Docker. ## Implementation ### 1. Standard GitHub Pages Workflow Create `.github/workflows/docs.yml` to automate the build and deployment process. ```yaml name: Deploy Docs on: push: branches: [main] permissions: contents: read pages: write id-token: write jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'npm' - run: npm install # Build the site into the 'site/' directory - run: npx @docmd/core build - name: Upload Artifact uses: actions/upload-pages-artifact@v3 with: path: site/ - name: Deploy to GitHub Pages uses: actions/deploy-pages@v4 ``` ### 2. Containerised Deployment (Docker) If you host your own documentation, use the [Deploy Command](../../deployment/index.md) to generate a production-ready `Dockerfile` and server configurations. ```bash # Generate Docker and Nginx configs locally npx @docmd/core deploy --docker --nginx ``` You can then update your GitHub Action to build and push this Docker image to a registry (like Docker Hub or GitHub Container Registry) whenever you release a new version. ### 3. Pull Request Previews Enhance your workflow by generating ephemeral preview environments for every Pull Request. This allows reviewers to see the rendered documentation before it is merged into the main branch. See the [Previewing Changes Guide](../workflows-teams/previewing-changes.md) for more details. ## Trade-offs Automated CI/CD requires initial setup time and management of secrets (e.g., API tokens). However, the long-term benefits of a "hands-off" deployment process - including reduced human error and faster update cycles - far outweigh the initial investment. For large sites, ensure your workflow only triggers when files in your documentation directory are changed to save on CI minutes. --- ## [OpenAPI Generation](https://docs.docmd.io/07/guides/integrations/openapi-generation/) --- title: "OpenAPI Generation" description: "How to integrate OpenAPI/Swagger schemas into your docmd workflow for automated and synchronised API reference documentation." --- ## Problem Manually maintaining REST API documentation is a major operational risk. The moment an engineer modifies an endpoint or updates a schema in the code, the documentation becomes obsolete. Keeping these in sync manually is tedious, error-prone, and frequently leads to integration failures for your API consumers. ## Why it matters Inaccurate API references are a primary cause of developer frustration and increased support tickets. Automation ensures that your documentation remains the "source of truth," reflecting the actual state of your API in real-time (or at every build). This allows engineers to focus on building features rather than manually updating documentation tables. ## Approach Implement an asynchronous build pipeline that converts your `openapi.json` or `swagger.yaml` schema into standard Markdown files. Because `docmd` excels at rendering Markdown with complex [Containers](../../content/containers/index.md), the resulting API reference feels integrated and visually consistent with the rest of your documentation. ## Implementation ### 1. Build Pipeline Integration You can use a tool like `widdershins` or a custom script to generate Markdown from your OpenAPI schema as a pre-build step in your CI/CD pipeline. ```json // package.json { "scripts": { "docs:generate-api": "npx widdershins --search false openapi.yaml -o docs/api/reference.md", "docs:build": "npm run docs:generate-api && npx @docmd/core build" } } ``` ### 2. Optimising API Layouts API references are often content-dense, with large tables for parameters and nested schemas. Use [Frontmatter](../../content/frontmatter.md) to optimise the page layout for readability. ```markdown --- title: "REST API Reference" layout: "full" # Maximises horizontal space for dense tables --- ``` Setting `layout: "full"` removes the right-hand Table of Contents sidebar, providing more room for wide code blocks and response examples. ### 3. Enhancing with docmd Containers You can post-process the generated Markdown to inject `docmd` features like [Tabs](../../content/containers/tabs.md) for multi-language code samples or [Callouts](../../content/containers/callouts.md) for authentication warnings. ````markdown ::: tabs == tab "cURL" ```bash curl -X GET "https://api.example.com/v1/users" ``` == tab "Node.js" ```javascript const users = await client.getUsers(); ``` ::: ```` ## Trade-offs Machine-generated documentation is excellent for technical accuracy but often lacks the "human touch" required for effective learning. We recommend using OpenAPI generation for the **Technical Reference** (endpoints, parameters, schemas) while providing handwritten **Tutorials** and **Conceptual Guides** to explain the context and use cases for your API. --- ## [Caching Strategies](https://docs.docmd.io/07/guides/performance-delivery/caching-strategies/) --- title: "Caching Strategies" description: "How to optimise your documentation site's performance using immutable caching, Etag revalidation, and production-ready server configurations." --- ## Problem When a documentation site is served without proper cache-control headers, browsers will unnecessarily re-download images, CSS, and JavaScript bundles on every visit. This results in visual stuttering, increased bandwidth consumption, and a poor experience for returning users who expect the documentation to load instantaneously. ## Why it matters Effective caching is one of the most impactful ways to improve the "perceived performance" of your site. By ensuring that static assets are stored locally in the user's browser, you eliminate the latency of repeated network requests. This makes navigating your documentation feel fluid and reliable, even on unstable network connections. ## Approach Implement a two-tier caching strategy: **Immutable Caching** for static assets (CSS, JS, images) and **Etag Revalidation** for dynamic content (HTML, JSON). `docmd` facilitates this by generating production-ready configurations that handle cache-busting automatically through version hashes. ## Implementation ### 1. Production-Ready Server Configs The easiest way to implement optimal caching is by using the [Deploy Command](../../deployment/index.md) to generate your server configuration. ```bash # Generate an optimised Nginx configuration npx @docmd/core deploy --nginx ``` ### 2. Immutable Assets For assets that don't change frequently (like theme styles and core scripts), use long-term caching. `docmd` appends version hashes to these assets to ensure that users only download new versions when you update your documentation. ```nginx # Example Nginx rule for immutable assets location ~* \.(?:css|js|webp|png|svg|woff2)$ { expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; } ``` ### 3. HTML & Navigation Revalidation Your HTML files and `navigation.json` should always be checked for updates to ensure users see the latest content and structure immediately. Use the `no-cache` directive to force the browser to revalidate with the server using Etags. ```nginx # Example Nginx rule for HTML files location ~* \.html$ { add_header Cache-Control "no-cache, must-revalidate"; } ``` ## Trade-offs ### Stale Content vs. Performance Setting long cache times for assets is highly performant but requires a reliable "cache-busting" strategy. `docmd` handles this automatically for its core files, but if you manually add assets to your `static/` directory, you must ensure you update their references (e.g., by changing the filename or adding a query parameter) when the content changes. ### CDN Integration If you are using a CDN (like Cloudflare or AWS CloudFront), ensure that it is configured to honour your server's `Cache-Control` headers. Most modern CDNs provide "instant purge" capabilities, which we recommend triggering as part of your CI/CD pipeline whenever you deploy a new version of your documentation. --- ## [CDN & Edge Deployment](https://docs.docmd.io/07/guides/performance-delivery/deploying-cdn-edge/) --- title: "CDN & Edge Deployment" description: "How to minimise global latency by deploying your static documentation to a Content Delivery Network (CDN) or Edge Network." --- ## Problem Hosting your documentation on a single server in one geographic region (e.g., US-East) means that users in other parts of the world (e.g., Europe or Asia) will experience significant network latency. Every page load, image, and script must travel thousands of miles, making your documentation feel sluggish and unresponsive for a global audience. ## Why it matters High latency directly harms the developer experience. Even if your documentation is well-written and lightweight, the "Time to First Byte" (TTFB) is limited by the laws of physics. If your site feels slow, developers are more likely to lose focus or abandon your tool entirely in favour of one with faster, more accessible documentation. ## Approach The optimal solution is to deploy your site to an Edge CDN. Because `docmd` generates pure static assets (HTML, CSS, JS), it is perfectly suited for edge distribution. CDNs replicate your files across hundreds of globally distributed "Edge Nodes," serving your users from the data centre closest to them. ## Implementation ### 1. Choose a Platform `docmd` is natively compatible with all modern static hosting and edge platforms. We recommend the following for their global performance and ease of use: * **Cloudflare Pages**: Extremely fast global edge network with built-in DDoS protection. * **Vercel**: Optimised for performance with excellent developer workflow integration. * **Netlify**: Powerful automation features and a reliable global CDN. ### 2. Automate the Build Use a CI/CD pipeline to build and deploy your site automatically whenever you push changes. See the [GitHub Actions Guide](../../guides/integrations/github-actions-cicd.md) for detailed examples. ```yaml # .github/workflows/deploy.yml jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 # Build the site into the default 'site/' directory - run: npm install && npx @docmd/core build # Example: Deploying to Cloudflare Pages - name: Deploy uses: cloudflare/pages-action@v1 with: apiToken: ${{ secrets.CF_API_TOKEN }} accountId: ${{ secrets.CF_ACCOUNT_ID }} projectName: my-docs directory: site ``` ### 3. Verification Once deployed, you can verify your global performance using tools like PageSpeed Insights or global ping tests. You should see sub-100ms response times from almost any location worldwide. ## Trade-offs Global edge networks abstract away server management, which is a major advantage for documentation teams. However, debugging regional caching issues can occasionally be more complex than reviewing a single server log. Using platforms with reliable "instant cache invalidation" ensures that your users always see the latest version of your documentation immediately after a deployment. --- ## [Low-End Device Optimisation](https://docs.docmd.io/07/guides/performance-delivery/low-end-devices/) --- title: "Low-End Device Optimisation" description: "How to build high-performance, accessible documentation that works easily on low-powered hardware and slow network connections." --- ## Problem Modern documentation sites often rely on heavy JavaScript runtimes just to display static text. For users on older mobile phones, budget laptops, or slow 3G/4G connections, these sites can take several seconds to load. The device's processor struggles to parse large JS bundles, resulting in "input lag," stuttering animations, and a poor overall reading experience. ## Why it matters Technical documentation should be universally accessible. Forcing users in emerging markets or those on constrained hardware to download and execute a heavy framework just to read a tutorial creates an unnecessary barrier to learning. A lightweight site ensures your product information is available to everyone, regardless of their hardware or internet speed. ## Approach Adopt an **HTML-First** strategy. `docmd` is designed with a zero-framework architecture, ensuring that the primary content is rendered into standard HTML during the build process. This keeps the browser's main thread unblocked, ensuring smooth scrolling and snappy navigation even on budget devices. ## Implementation ### 1. Minimal Runtime Footprint By default, `docmd` does not use React, Vue, or any other heavy client-side framework for its core UI. This pre-rendered approach ensures that the initial "First Contentful Paint" happens almost immediately. To maintain this performance: * **Limit Custom Scripts**: Avoid adding large third-party libraries to your `customJs` configuration. * **Use Native Browser Features**: Rely on standard CSS and HTML5 elements which are highly optimised by all modern browsers. ### 2. Strategic Plugin Management While [Plugins](../../plugins/usage.md) add powerful features, they can introduce significant performance overhead. For example, the [Mermaid Plugin](../../plugins/mermaid.md) requires a large engine to render diagrams. If your users are primarily on low-end devices, consider using static images for diagrams instead of client-side rendering. ### 3. Responsive and Optimised Media Avoid serving oversized images to mobile users. Use modern formats like WebP and consider the `<picture>` tag for more granular control over responsive assets. ```html <picture> <source srcset="/assets/mobile-hero.webp" media="(max-width: 600px)"> <img src="/assets/desktop-hero.webp" alt="Feature Overview" loading="lazy"> </picture> ``` Using the `loading="lazy"` attribute ensures that images are only downloaded as they enter the user's viewport, saving bandwidth on slow connections. ### 4. Efficient Search Indexing `docmd` generates scoped search indices to keep the memory footprint low. However, for extremely large sites, the [Search Plugin](../../plugins/search.md) can still be memory-intensive. Encourage users on mobile to use the search bar only when necessary, or optimise your index as described in the [Local-First Search Guide](../search/local-first-search.md). ## Trade-offs Prioritising performance for low-end devices often means avoiding "heavy" interactive features like complex 3D visualizations or large client-side data processing. This is a deliberate design choice that values **inclusivity and speed** over visual complexity, ensuring your documentation remains a useful resource for the widest possible audience. --- ## [Reducing JS Payload](https://docs.docmd.io/07/guides/performance-delivery/reducing-javascript-payload/) --- title: "Reducing JS Payload" description: "How to maintain a high-performance documentation site by optimising your JavaScript dependencies and using docmd's zero-framework architecture." --- ## Problem Many modern documentation tools rely on heavy JavaScript frameworks (like React or Vue) just to render static text. These frameworks can add several hundred kilobytes to your initial page load, forcing the browser to download, parse, and execute large amounts of code before the site becomes fully interactive. This leads to slow loading times and "ghost clicks" on low-end devices. ## Why it matters A large JavaScript payload directly impacts "Time to Interactive" (TTI). In technical documentation, where users need answers quickly, any delay caused by heavy framework initialisation is a significant usability barrier. Keeping your payload small ensures that search, navigation, and theme switching are instantaneous from the moment the page appears. ## Approach `docmd` uses a **zero-framework** architecture for its core client-side logic. By utilising Vanilla JavaScript and native browser APIs instead of a heavy Virtual DOM, we keep the total JS payload for a standard site under **20KB**. This lightweight foundation ensures maximum performance across all devices and network conditions. ## Implementation ### 1. Use Native Browser APIs Avoid importing heavy libraries like jQuery or Lodash for simple tasks. Modern browsers have reliable native APIs that can handle almost any documentation-related requirement with zero overhead. ```javascript // docmd.config.js export default { // ✅ Use a small, purpose-built script instead of a heavy library customJs: ['/static/js/my-custom-logic.js'] }; ``` ### 2. Strategic Plugin Management While [Plugins](../../plugins/usage.md) add powerful features, some can significantly increase your JavaScript payload. For example, the [Mermaid Plugin](../../plugins/mermaid.md) requires a large client-side library to render diagrams. Only enable heavy plugins if they are essential to your content, and consider their impact on overall page weight. ### 3. Defer Non-Critical Scripts If you need to include third-party services like analytics or feedback widgets, ensure they are loaded asynchronously or deferred so they don't block the rendering of your documentation. ```html <!-- In your custom head injection --> <script src="https://analytics.com/script.js" async defer></script> ``` ### 4. Optimise Assets Ensure that any custom JavaScript you provide is minified and compressed. `docmd` handles the minification of its core assets, but you are responsible for the optimisation of any files you add to your `static/` directory. ## Trade-offs Building complex interactive features with Vanilla JavaScript can require more manual effort than using a declarative framework. However, for documentation - where 95% of the content is static text and images - the performance gains of a zero-framework approach far outweigh the developer convenience of a heavy framework. --- ## [Sub-100ms Navigation](https://docs.docmd.io/07/guides/performance-delivery/sub-100ms-navigation/) --- title: "Sub-100ms Navigation" description: "How docmd's native SPA router and intent-based prefetching deliver instant page transitions for an optimal reading experience." --- ## Problem Traditional multi-page navigation, where every link click triggers a full browser reload, creates a disruptive "white flash" and breaks the reader's flow. The browser must discard the current state, request new HTML, and re-parse CSS and JavaScript - even if only the central content area has changed. ## Why it matters Documentation users frequently jump between different sections, such as tutorials, API references, and conceptual guides. If every transition takes a second or more, it creates cognitive friction and discourages thorough exploration. Instant navigation makes the documentation feel like a native application, significantly improving user satisfaction and engagement. ## Approach `docmd` utilizes a high-performance **Single Page Application (SPA) Router** built on top of pre-generated static files. This allows the browser to intercept link clicks, fetch only the necessary content in the background, and update the page dynamically without a full reload. This approach preserves the state of the sidebar, table of contents, and theme settings, resulting in near-instant transitions. ## Implementation The `docmd` SPA router is enabled by default and uses several advanced techniques to achieve sub-100ms navigation speeds: ### 1. Intent-Based Prefetching When a user hovers over a navigation link, `docmd` detects the intent to navigate and initiates a background fetch for the target page's content. By the time the user actually clicks the link, the data is often already available in the browser's cache, making the transition feel instantaneous. ### 2. Partial DOM Updates Instead of re-rendering the entire page, `docmd` intelligently updates only the necessary functional zones: * **Main Content**: The primary Markdown-rendered body. * **Table of Contents**: Refreshed to match the new page's headers. * **Navigation State**: Updates the active and expanded states in the sidebar. ### 3. Lifecycle Events for Custom Logic Because the browser doesn't perform a full reload, standard events like `DOMContentLoaded` only fire once. To execute custom JavaScript after every navigation - such as re-initialising a third-party widget or tracking page views - you should listen for the `docmd:page-mounted` event. ```javascript // Example: Re-initialising a custom component after navigation document.addEventListener('docmd:page-mounted', (event) => { const currentPath = event.detail.path; console.log(`Successfully navigated to: ${currentPath}`); // Custom logic here if (currentPath.includes('/api/')) { initApiConsole(); } }); ``` For more details, see the [Client-Side Events](../../api/client-side-events.md) documentation. ## Trade-offs ### Script Execution The SPA router automatically re-executes `<script>` tags found within the Markdown body of the new page. However, global scripts defined in your theme or layout only run once during the initial load. Always use the `docmd:page-mounted` event for logic that must execute on every page. ### SEO and Accessibility Despite the SPA-like behaviour, `docmd` still generates a complete, standalone `.html` file for every page. This ensures that search engine crawlers see the full content and that the site remains functional for users with JavaScript disabled, maintaining excellent SEO and accessibility standards. --- ## [Breaking Changes & Deprecations](https://docs.docmd.io/07/guides/scaling-architecture/breaking-changes-deprecations/) --- title: "Breaking Changes & Deprecations" description: "How to communicate API changes and migration paths effectively using versioned documentation and contextual callouts." --- ## Problem When a product introduces a major version change, certain APIs, features, or configurations are inevitably deprecated or removed. Users browsing the latest documentation must be clearly warned if they are using outdated patterns, yet the documentation should remain focused on the modern implementation to avoid confusion. ## Why it matters Failure to explicitly surface breaking changes leads to developers wasting hours debugging code that the engine no longer supports. Contextual warnings and clear migration paths are essential for maintaining user trust, reducing support requests, and ensuring a smooth transition to the latest version of your software. ## Approach Combine `docmd`'s [Versioning Engine](../../configuration/versioning.md) with [Callout Containers](../../content/containers/callouts.md) to create a clear distinction between legacy and modern content. The strategy is to move full legacy documentation to an archived version while providing "migration anchors" in the current version that link back to the archived content. ## Implementation ### 1. Archiving Legacy Content When releasing a new major version (e.g., v2.0), move your existing documentation to an archived directory (e.g., `docs-v1/`). This ensures that the full context of the previous version is preserved for users who haven't migrated yet. ### 2. Contextual Migration Callouts In your latest documentation, use `warning` or `important` callouts at the top of pages where significant changes have occurred. This provides immediate value to users who are attempting to use legacy patterns. ```markdown # Configuration API ::: callout warning "Migration: Breaking Change in v2.0" The `siteTitle` property has been removed. It has been replaced by the global `title` property. * **Migrating from v1.x?** Please update your `docmd.config.js`. * **Need latest docs?** Refer to the [Configuration Guide](../../configuration/overview.md). ::: ``` ### 3. Maintaining AI Accuracy By strictly separating deprecated content from the active version, you significantly improve the accuracy of AI tools. `docmd`'s [LLMs Plugin](../../plugins/llms.md) generates context files based on the active version. Archiving legacy content prevents AI models from "hallucinating" and recommending outdated APIs to users who are looking for modern solutions. ## Trade-offs Actively managing migration callouts adds maintenance overhead. If left indefinitely, pages can become cluttered with old warnings. We recommend a policy of removing migration callouts once the legacy version reaches its End-of-Life (EOL) or after one full major release cycle to keep the documentation lean and focused. --- ## [Multi-Team Collaboration](https://docs.docmd.io/07/guides/scaling-architecture/multi-team-collaboration/) --- title: "Multi-Team Collaboration" description: "How to use decentralized navigation and global menubars to allow multiple teams to contribute to a unified documentation project without friction." --- ## Problem When multiple independent teams (e.g., Frontend, Backend, DevOps, and Product) contribute to a single documentation repository, organizational friction often occurs. Teams may accidentally overwrite global navigation settings, create conflicting styling paradigms, or break links across domain boundaries during concurrent updates. ## Why it matters Friction in the authoring experience leads to "documentation silos," where teams create independent, isolated wikis to avoid the complexity of a shared repository. This destroys the unified user experience of a single documentation portal and makes it significantly harder for users to find comprehensive information about the entire system. ## Approach Use `docmd`'s decentralized [Navigation Resolution](../../configuration/navigation.md#navigation-resolution-priority) system. This allows individual teams to have full autonomy over their specific domains using local `navigation.json` files, while a central team governs the global [Menubar](../../configuration/menubar.md) and visual design system. ## Implementation ### 1. Domain-Based Ownership Divide your documentation into top-level directories assigned to specific teams. Each team completely owns the content and internal structure of their assigned folder. ```text my-project/ ├── docs/ │ ├── frontend/ # Owned by the UI Team │ │ ├── navigation.json # Team-specific sidebar │ │ └── components.md │ ├── backend/ # Owned by the API Team │ │ ├── navigation.json │ │ └── database.md │ └── docmd.config.js # Owned by the Platform/Core Team ``` ### 2. Global Context Switching (The Menubar) The central platform team controls the [Menubar](../../configuration/menubar.md), which serves as the primary navigation layer to switch between different team domains. ```javascript // docmd.config.js export default { menubar: { enabled: true, items: [ { text: 'Frontend', url: '/frontend/components' }, { text: 'Backend', url: '/backend/database' }, { text: 'Infrastructure', url: '/devops/setup' } ] } }; ``` ### 3. Local Autonomy with navigation.json When a user is browsing content within the `/frontend/` directory, `docmd` automatically prioritises the `frontend/navigation.json` file. The sidebar updates dynamically to reflect only the frontend-specific hierarchy, preventing the navigation from becoming cluttered with unrelated information from other teams. ```json // docs/frontend/navigation.json [ { "title": "Design System", "path": "/frontend/design-system" }, { "title": "Component Library", "path": "/frontend/components" } ] ``` ## Trade-offs Decentralized navigation requires teams to be mindful of cross-domain links. While `docmd` handles relative links effectively, moving an entire team directory will break links in other teams' files. We recommend using root-relative paths (starting with `/`) for links between different team domains to ensure stability. --- ## [Managing Multi-Version Documentation](https://docs.docmd.io/07/guides/scaling-architecture/multi-version-documentation/) --- title: "Managing Multi-Version Documentation" description: "How to maintain multiple versions of your documentation (v1, v2, legacy) with a unified switcher and path preservation." --- ## Problem As software products evolve, enterprise users often remain on older LTS (Long Term Support) versions. Dropping documentation for v1 when v2 is released leaves those users stranded, while maintaining completely separate sites for each version leads to a fragmented user experience and SEO cannibalization. ## Why it matters Without a seamless way to switch versions, developers often mistakenly apply instructions from the latest documentation to legacy environments, leading to errors and increased support overhead. A unified versioning system ensures that users always know which context they are in and can easily jump between versions of the same page. ## Approach `docmd` features a native [Versioning Engine](../../configuration/versioning.md) that treats versions as first-class citizens. It isolates builds into version-prefixed directories, provides a "Sticky Switching" mechanism that preserves the current page path, and correctly scopes search results to the active version context. ## Implementation ### 1. Organise Source Directories Keep your latest documentation in a standard directory (e.g., `docs/`) and place legacy versions in sibling directories (e.g., `docs-v1/`). ```text my-project/ ├── docs/ # v2.x (Current) ├── docs-v1/ # v1.x (Legacy LTS) └── docmd.config.js ``` ### 2. Configure the Version Map Define your version structure in `docmd.config.js`. The `current` version is served at the root URL, while others are served at `/{id}/`. ```javascript // docmd.config.js export default { versions: { current: 'v2', // Served at / position: 'sidebar-top', // Switcher location all: [ { id: 'v2', dir: 'docs', label: 'v2.x (Latest)' }, { id: 'v1', dir: 'docs-v1', label: 'v1.x (LTS)' } ] } }; ``` ### 3. Per-Version Navigation If the navigation structure differs between versions, you can place a `navigation.json` file inside each version's source directory. `docmd` will automatically detect and use it for that specific version. ```json // docs-v1/navigation.json [ { "title": "Legacy Setup", "path": "/legacy-setup" }, { "title": "Migration to v2", "path": "/migration" } ] ``` ### 4. Path Preservation (Sticky Switching) `docmd` automatically attempts to preserve the user's current path when they switch versions. If a user is at `/api/auth` on the `v2` site and switches to `v1`, the engine will attempt to route them to `/v1/api/auth`. If the page doesn't exist in the target version, it falls back to the version's homepage. ## Trade-offs Storing multiple versions in a single repository increases the repository size over time. For very large documentation sets, consider using CI/CD to pull in legacy documentation directories dynamically during the build process instead of committing them to the main branch. --- ## [Organising Large Repositories](https://docs.docmd.io/07/guides/scaling-architecture/organising-large-repositories/) --- title: "Organising Large Repositories" description: "How to maintain navigation clarity and usability in complex documentation structures using hub pages and hierarchical navigation." --- ## Problem As a documentation repository grows to hundreds of pages, displaying every topic in a single, massive sidebar makes the site unusable. Users suffer from "choice paralysis," where finding a specific module requires scrolling through dozens of irrelevant, expanded categories. ## Why it matters Navigation is a critical component of user experience. A cluttered interface diminishes the perceived quality of your product and makes it harder for developers to find the answers they need. If the navigation feels chaotic, users often assume the software itself is equally difficult to use. ## Approach Implement a hierarchical grouping strategy using `docmd`'s [Navigation Configuration](../../configuration/navigation.md). The core principle is to hide complexity until it is needed. Use collapsible groups and "Hub Pages" to maintain a clean sidebar, ensuring that users can focus on their current task without being overwhelmed. ## Implementation ### 1. Hierarchical Grouping Use the `collapsible` property in your `navigation.json` or config file to group related pages. This keeps the sidebar clean and allows users to expand only the sections they are interested in. ```json // docs/navigation.json [ { "title": "Advanced API", "icon": "braces", "collapsible": true, "children": [ { "title": "Authentication", "path": "/api/auth" }, { "title": "Webhooks", "path": "/api/webhooks" }, { "title": "Rate Limiting", "path": "/api/rate-limiting" } ] } ] ``` ### 2. Implementing Hub Pages Instead of exposing every individual page in the sidebar, create central "Hub Pages" that act as directories for specific sub-systems. Use [Grids and Cards](../../content/containers/grids.md) to provide a visual, high-level overview of the available content. ```markdown # Integrations Hub ::: grids ::: grid ::: card "Database Integrations" icon:database Connect your application to popular databases like Postgres and MongoDB. [View Database Guides](/integrations/databases) ::: ::: ::: grid ::: card "Payment Gateways" icon:credit-card Learn how to implement Stripe, PayPal, and more. [View Payment Guides](/integrations/payments) ::: ::: ::: ``` ### 3. Using Breadcrumbs `docmd` automatically generates [Breadcrumbs](../../content/syntax/advanced.md#breadcrumbs) for every page based on your folder structure and navigation hierarchy. By using Hub Pages, you can keep the sidebar focused while breadcrumbs provide the necessary context and an easy way for users to navigate back up the hierarchy. ## Trade-offs Using Hub Pages can add an extra "click" for users to reach deep content. However, this is usually preferable to a cluttered sidebar that makes discovery difficult. The trade-off is a cleaner, more professional interface that significantly improves the overall searchability and focus of your documentation. --- ## [Scalable Folder Structure](https://docs.docmd.io/07/guides/scaling-architecture/scalable-folder-structure/) --- title: "Scalable Folder Structure" description: "How to organise large-scale documentation projects using the Diátaxis framework and docmd's resolution system." --- ## Problem Small documentation sites often start with a flat `docs/` folder. However, as the project grows to include multiple modules, tutorials, APIs, and conceptual deep-dives, a disorganised folder structure becomes a significant maintenance burden. Files become difficult to locate, and the navigation sidebar becomes an overwhelming "wall of links." ## Why it matters A disorganised folder structure directly results in a confusing user experience, as `docmd`'s routing and default navigation are derived from your file system. For authors, a lack of clear structure leads to content duplication and inconsistent naming, making the documentation harder to manage as more contributors join the project. ## Approach We recommend adopting an information architecture framework like [Diátaxis](external:https://diataxis.fr/), which separates content into four distinct categories: Tutorials, How-To Guides, Reference, and Explanation. Mapping these categories strictly to your physical file system provides a clear roadmap for both readers and authors. ## Implementation ### 1. The Diátaxis Hierarchy Organise your source directory into semantic subfolders. This physical isolation makes it easier to manage large sets of files and ensures a clean URL structure. ```text my-project/ ├── docs/ │ ├── tutorials/ (Learning-oriented: step-by-step lessons) │ │ └── getting-started.md │ ├── guides/ (Task-oriented: solving specific problems) │ │ └── deployment.md │ ├── reference/ (Information-oriented: technical descriptions) │ │ └── api-spec.md │ ├── explanation/ (Understanding-oriented: theoretical background) │ │ └── architecture.md │ └── navigation.json (Main navigation definition) └── docmd.config.js ``` ### 2. Strategic Use of navigation.json Instead of defining a massive navigation tree in your global configuration, use `navigation.json` files within your source directories. `docmd` follows a [Resolution Priority](../../configuration/navigation#navigation-resolution-priority) system, allowing you to define distinct sidebar hierarchies for different sections of your site. ```json // docs/navigation.json [ { "title": "Tutorials", "icon": "book-open", "children": [ { "title": "Get Started", "path": "/tutorials/getting-started" } ] }, { "title": "Reference", "icon": "braces", "children": [ { "title": "API Specification", "path": "/reference/api-spec" } ] } ] ``` ### 3. File-Based Routing Remember that every Markdown file's location in the folder structure determines its final URL. For example, `docs/guides/auth.md` becomes `your-site.com/guides/auth`. Use this to your advantage to create intuitive, memorable URLs for your users. ## Trade-offs Strict organizational frameworks like Diátaxis require a clear understanding of content types. Technical writers may occasionally find it difficult to categorise a specific document (e.g., "Is this a guide or a tutorial?"). Establishing clear internal contribution guidelines is essential to maintain consistency as your team and documentation grow. --- ## [Scaling to 1000+ Pages](https://docs.docmd.io/07/guides/scaling-architecture/scaling/) --- title: "Scaling to 1000+ Pages" description: "How to maintain high performance and usability in massive documentation projects with docmd." --- ## Problem As a software product matures, its documentation naturally expands. When a project grows to hundreds or thousands of Markdown files, many documentation generators suffer from sluggish build times, slow development server hot-reloading, and navigation structures that overwhelm both maintainers and users. ## Why it matters If documentation generation takes minutes instead of seconds, authors are discouraged from making small corrections, leading to stale and inaccurate content. For users, a massive, unorganised sidebar menu makes finding information frustrating, leading to increased support tickets and a poor developer experience. ## Approach `docmd` is architected for speed and scalability. By utilising a high-performance parsing engine and a granular file-based build strategy, it can process thousands of pages in seconds. Its optimised SPA (Single Page Application) delivery ensures that navigating through a large site remains instantaneous for the end user. ## Implementation ### 1. Granular Project Structure Avoid placing all files in a single flat directory. Use a deeply nested folder structure that mirrors your product's architecture. This makes the project easier to maintain and allows `docmd` to efficiently track changes during development. ### 2. Optimised Search Indexing For large sites, the [Search Plugin](../../plugins/search) is essential. `docmd` generates a highly compressed search index that is loaded on demand. This ensures that even with thousands of pages, the initial page load remains fast while providing full-text search capabilities across the entire site. ### 3. Versioning and Archiving Use the [Versioning Engine](../../configuration/versioning) to separate legacy content from active documentation. By isolating older versions into their own build contexts, you reduce the number of pages that need to be re-processed during daily updates, significantly improving development velocity. ```javascript // docmd.config.js export default { versions: { current: 'v3', all: [ { id: 'v3', dir: 'docs/current', label: 'v3.x (Latest)' }, { id: 'v2', dir: 'docs/v2', label: 'v2.x (Legacy)' } ] } }; ``` ### 4. Component-Based Navigation Break down your navigation into logical segments using `navigation.json` files. This allows you to define distinct sidebar hierarchies for different sections of your site, preventing the main navigation from becoming cluttered. ## Trade-offs A large site naturally consumes more disk space and memory during the build process. To maintain sub-second build times at extreme scales (10,000+ pages), consider using a high-performance CI/CD environment with SSD storage and ample RAM to handle the parallel processing of files. --- ## [Fast & Accurate Search](https://docs.docmd.io/07/guides/search/fast-accurate-search/) --- title: "Fast & Accurate Search" description: "How docmd optimises search indexing for speed and accuracy, even in large-scale documentation projects." --- ## Problem As documentation grows to hundreds or thousands of pages, the compiled search index can become quite large. A monolithic index file can block the browser's main thread during download and parsing, delaying the "Time to Interactive" and causing the search interface to feel sluggish or unresponsive. ## Why it matters The primary goal of documentation search is "Time to Answer." If a user triggers the search modal and has to wait several seconds for the index to load, the utility of the search tool is lost. Fast, accurate search results are essential for providing a professional developer experience and helping users find information without friction. ## Approach `docmd` utilizes an optimised indexing strategy powered by a high-performance search library. It employs **Scoping**, **Incremental Loading**, and **Field Optimisation** to ensure that search results are delivered almost instantaneously, regardless of the size of the documentation site. ## Implementation ### 1. Scoped Search Indices `docmd` automatically generates separate search indices for every [Locale](../../configuration/localisation/index.md) and [Version](../../configuration/versioning.md). This ensures that a user only downloads the index relevant to their current context. For example, a user browsing the Chinese version of your documentation only downloads the Chinese search index, significantly reducing the payload size. ### 2. Intelligent Field Stripping The [Search Plugin](../../plugins/search.md) allows you to control exactly what content is indexed. By default, it prioritises headers and frontmatter metadata while stripping out common "stop words" and unnecessary code symbols that bloat the index without adding value. You can also exclude specific pages from the index using the `search` property in your [Frontmatter](../../content/frontmatter.md). ```yaml --- title: "Internal Developer Guide" search: false # This page will not appear in search results --- ``` ### 3. Lazy Loading & Prefetching To keep the initial page load fast, `docmd` does not load the search index immediately. Instead, it is fetched lazily in the background or triggered the moment a user interacts with the search UI (e.g., by clicking the search bar or using the `Cmd+K` / `Ctrl+K` shortcut). ### 4. Result Ranking Results are ranked based on a weighted scoring system. Keywords found in the page `title` or `h1` headers are weighted significantly higher than those found in the body text. This ensures that the most relevant pages appear at the top of the results list. ## Trade-offs Excluding utility or internal pages from the search index makes them harder to discover. You should use the `search: false` property sparingly to ensure that valuable information remains findable. While lazy loading improves initial performance, users on extremely slow connections may experience a brief delay the first time they trigger a search. --- ## [Search Relevance & Structure](https://docs.docmd.io/07/guides/search/improving-search-relevance/) --- title: "Search Relevance & Structure" description: "How to structure your Markdown content to improve search relevance and help users find information faster." --- ## Problem Search engines prioritise content based on structure. If a high-quality guide uses generic headers like "Introduction" or "Step 1," the search engine may not assign enough weight to the core keywords buried within the paragraphs. This results in relevant pages being buried deep in search results, frustrating users who expect instant answers. ## Why it matters Users typically search for specific technical terms (e.g., "authentication token" or "deployment limit") rather than full sentences. If your documentation structure doesn't emphasise these terms, the search engine cannot confidently rank your content. High search relevance is the difference between a self-service documentation portal and a high volume of support tickets. ## Approach Structure your Markdown so the search indexer can automatically identify and prioritise core concepts. `docmd`'s search engine assigns higher weights to the page `title`, `description`, and `headers` compared to the body text. By optimising these structural elements, you significantly improve the discoverability of your content. ## Implementation ### 1. Optimise Frontmatter Metadata Use the [Frontmatter](../../content/frontmatter.md) block to provide explicit keywords and a descriptive summary. The [Search Plugin](../../plugins/search.md) indexes these fields to provide better results and more useful snippets in the search UI. ```yaml --- title: "AWS S3 Storage Configuration" description: "How to configure IAM roles and bucket permissions for AWS S3 integration." keywords: ["aws", "s3", "storage", "iam", "cloud"] --- ``` ### 2. Use Semantic Headers Avoid generic header names. Instead, include relevant keywords in your headers to provide context for both the user and the search engine. * **Low Relevance:** `## Step 1: Configuration` * **High Relevance:** `## Step 1: Configuring AWS IAM Roles` ### 3. Use Callouts for Key Information Using [Callout Containers](../../content/containers/callouts.md) for critical warnings or "Pro Tips" can also help search relevance. Content within callouts is often semantically isolated and can be weighted differently by the indexer to highlight important troubleshooting steps. ## Trade-offs Optimising for search relevance requires disciplined writing. As your product evolves, keywords in frontmatter can become outdated if not regularly reviewed. In addition, including too many keywords in headers (keyword stuffing) can make the documentation feel repetitive and less natural to read. Aim for a balance between SEO and readability. --- ## [Local-First Search Optimisation](https://docs.docmd.io/07/guides/search/local-first-search/) --- title: "Local-First Search Optimisation" description: "How to optimise your documentation content for docmd's high-performance, client-side search engine." --- ## Problem Local-first search engines run entirely in the browser, providing instant results without a server round-trip. However, this means they are constrained by the browser's memory and processing limits. If a search index is not properly optimised, it can consume excessive RAM, causing the browser tab to stutter or even crash, especially on mobile devices. ## Why it matters A seamless search experience is essential for developer productivity. If the search tool causes performance issues or consumes too much memory, users will avoid using it. Optimising your content for local-first search ensures that your documentation remains fast, responsive, and reliable across all devices and network conditions. ## Approach `docmd`'s [Search Plugin](../../plugins/search.md) uses a build-time extraction pipeline to create a highly optimised index. By pruning unnecessary data and focusing on high-value semantic fields, it ensures that the resulting index is both comprehensive and lightweight. ## Implementation ### 1. Build-Time Extraction During the build process, `docmd` processes your Markdown files to extract only the most relevant text for indexing. It automatically strips out: * HTML tags and structural boilerplate. * Markdown syntax characters that don't add semantic value. * Formatting-only elements that would otherwise bloat the index. This ensures that the indexer only receives clean, meaningful text, which significantly reduces the final index size. ### 2. Strategic Indexing with Frontmatter You can use [Frontmatter](../../content/frontmatter.md) to explicitly control how a page is indexed. For example, if a page contains large amounts of repetitive data (like raw JSON logs) that aren't useful for search, you can choose to index only the headers and metadata. ```yaml --- title: "API Log Reference" search: indexBody: false # Only index the title and headers --- ``` ### 3. Client-Side Memory Management `docmd` manages the search index lifecycle carefully in the browser. It uses an on-demand loading strategy, meaning the search engine is only initialised when the user first interacts with it. This keeps the initial page load footprint small and ensures that system resources are only used when needed. ## Trade-offs Aggressively pruning content from the search index (e.g., excluding large code blocks) can sometimes result in missing niche results. You must balance the need for a lightweight, fast index with the requirement for thorough search coverage. We recommend prioritising headers and conceptual descriptions, as these are the most common search targets for developers. --- ## [Git-Based Workflows](https://docs.docmd.io/07/guides/workflows-teams/git-based-workflows/) --- title: "Git-Based Workflows" description: "How to manage documentation contributions effectively using Git, Pull Requests, and automated CI/CD checks." --- ## Problem Allowing direct pushes to the main documentation branch often leads to broken links, inconsistent formatting, and unverified technical information. However, imposing too much friction - such as requiring separate CMS accounts - discourages community members and internal developers from contributing valuable updates. ## Why it matters Collaboration is the lifeblood of great documentation. If a developer finds a typo or an outdated example, they should be able to submit a fix in minutes. A Git-based workflow provides a familiar, transparent, and secure environment for contributions, ensuring that every change is reviewed and validated before it goes live. ## Approach Implement a "Pull Request" (PR) model supported by automated validation and preview environments. `docmd` is designed for this workflow, as it operates on standard Markdown files that are easy to diff, review, and merge using familiar Git tools. ## Implementation ### 1. Enable "Edit this Page" Links You can configure `docmd` to automatically generate "Edit this page" links in the footer or sidebar. This allows users to jump directly from a documentation page to the corresponding source file in your repository. ```javascript // docmd.config.js export default { editLink: { enabled: true, baseUrl: 'https://github.com/my-org/my-docs/edit/main/docs', text: 'Suggest an edit' } }; ``` For more details, see the [Edit Link Configuration](../../configuration/overview.md#editlink). ### 2. Contextual Reviews with Threads For complex updates that require detailed feedback, use the [Threads Plugin](../../plugins/usage.md). This allows authors and reviewers to leave inline comments directly within the Markdown content during the review phase, keeping discussions contextualised. ```markdown ::: thread "Reviewer Name" Should we include a code example for the new authentication flow here? ::: ``` ### 3. Automated Validation in CI Integrate `docmd` into your CI/CD pipeline (e.g., [GitHub Actions](../../guides/integrations/github-actions-cicd.md)) to validate every PR. At a minimum, your pipeline should run the build command to ensure no syntax errors or broken configurations are introduced. ```bash # In your CI pipeline npm install npx @docmd/core build ``` ## Trade-offs Strict Git workflows can occasionally slow down minor updates, such as fixing a critical typo or updating a service status notice. For high-velocity teams, we recommend designating "Documentation Owners" who have the authority to fast-track small changes while maintaining rigorous review standards for significant technical updates. --- ## [Maintaining Consistency](https://docs.docmd.io/07/guides/workflows-teams/maintaining-consistency/) --- title: "Maintaining Consistency" description: "How to ensure a unified voice and professional quality across large documentation teams using linting and standardised patterns." --- ## Problem In large teams, every technical writer has a different style and preference. Some might use bold text for emphasis, while others use italics. Some may prefer "Click the button," while others use "Select the option." Over time, your documentation can become a "patchwork quilt" of conflicting styles, making it harder for users to parse information quickly and reducing the professional trust of your product. ## Why it matters Consistency breeds familiarity. When users are learning complex APIs or workflows, they rely on consistent vocabulary and structural patterns to navigate the content effectively. A unified voice makes your documentation feel like a cohesive, high-quality product, which in turn builds confidence in the software itself. ## Approach Enforce consistency mechanically using [Standardised Containers](../../content/containers/index.md) and automated linting tools. By automating low-level style and syntax checks, you free up your human editors to focus on the high-level quality, accuracy, and clarity of the content. ## Implementation ### 1. Use Standardised docmd Patterns Encourage all contributors to use `docmd`'s built-in thematic containers instead of improvising with manual Markdown formatting. This ensures that every warning, tip, or note looks and behaves identically across the entire site. ```markdown <!-- ❌ Avoid: inconsistent and unstyled --> **Note:** Please restart the service. <!-- ✅ Use: consistent, accessible, and thematic --> ::: callout info Please restart the service. ::: ``` Using [Callouts](../../content/containers/callouts.md) ensures that your documentation maintains a professional appearance and meets accessibility standards without extra effort from the writer. ### 2. Implement Prose Linting Integrate tools like **Vale** or **Markdownlint** to enforce brand terminology, tone, and grammar. These tools can be configured to check for passive voice, biased language, or incorrect product spelling automatically. ```ini # .vale.ini example MinAlertLevel = suggestion Packages = Google, Microsoft [*] BasedOnStyles = Vale, Google ``` ### 3. Automated Enforcement in CI/CD Include consistency checks in your [GitHub Actions](../../guides/integrations/github-actions-cicd.md) or other CI/CD pipelines. This ensures that every Pull Request is automatically audited for style and structural consistency before it can be merged. ```bash # Example CI step for linting - name: Lint Documentation run: vale docs/ ``` ## Trade-offs Strict linting can sometimes discourage community contributors if they are met with multiple "style errors" for a simple typo fix. We recommend setting your linter's sensitivity to `warning` for external contributions and reserving `error` status for internal team updates to balance consistency with inclusivity. --- ## [Previewing Changes](https://docs.docmd.io/07/guides/workflows-teams/previewing-changes/) --- title: "Previewing Changes" description: "How to set up local and cloud-based preview environments to ensure your documentation renders perfectly before it goes live." --- ## Problem Writing Markdown without a live preview often leads to formatting errors, broken containers, and incorrect image paths that only become visible once the content is in production. This results in a frustrating experience for users and extra work for maintainers who must constantly push hotfixes for simple rendering issues. ## Why it matters High-quality documentation is essential for developer trust. A broken warning box or unrendered syntax looks unprofessional and can even mislead users about how your software works. Seeing the "real" documentation before it goes live is the most effective way to catch errors, improve readability, and ensure a seamless user experience. ## Approach Implement a multi-stage preview strategy: use `docmd`'s [Local Development](../../getting-started/quick-start.md#local-development) server for immediate feedback while writing, and use ephemeral cloud environments (like Vercel or Cloudflare Pages) for final reviews within your Pull Requests. ## Implementation ### 1. Instant Local Previews The fastest way to see your changes is by running the `docmd dev` server. It features Hot Module Replacement (HMR), which automatically refreshes your browser the moment you save a Markdown file. ```bash # Start the local development server npx @docmd/core dev ``` ### 2. Cloud-Based Preview Environments For collaborative reviews, configure your CI/CD platform to generate unique "Preview URLs" for every Pull Request. Since `docmd` outputs standard static files, it is compatible with all major hosting providers. * **Build Command**: `npx @docmd/core build` * **Output Directory**: `site` This allows reviewers to see exactly how the changes will look and behave in a production-like environment before they are merged into the main branch. ### 3. Collaborative Reviews with Threads Combine your cloud previews with the [Threads Plugin](../../plugins/usage.md). This allows team members to leave feedback directly on the rendered preview page, bridging the gap between the source Markdown and the final user experience. ## Trade-offs Building a full static site for every commit in a massive repository (thousands of pages) can be time-consuming and costly in terms of CI/CD resources. To optimise this, configure your CI pipeline to only trigger a documentation build when files within your source directory (e.g., `/docs`) have been modified. --- ## [Setting Up a Workflow](https://docs.docmd.io/07/guides/workflows-teams/setting-up-workflow/) --- title: "Setting Up a Workflow" description: "How to establish a high-velocity, multi-author documentation workflow using docmd and docs-as-code principles." --- ## Problem When teams lack a structured documentation workflow, updates are often delayed, forgotten, or shared as ad-hoc messages. Without a clear process, content becomes fragmented, formatting becomes inconsistent, and technical writers spend more time resolving merge conflicts than writing high-quality content. ## Why it matters Without a formal process, documentation quickly becomes outdated and loses its value. If updating documentation requires waiting on a slow software release cycle, your guides will perpetually remain out of sync with your actual product features, leading to user frustration and increased support volume. ## Approach Decouple documentation deployments from software release cycles while adopting the same reliable processes used in software engineering (Branches → Pull Requests → CI/CD Previews). `docmd`'s lightweight nature allows teams to treat "documentation as code" with minimal overhead, ensuring that your guides are as reliable and up-to-date as your software. ## Implementation ### 1. Repository Strategy Choose the strategy that best fits your organizational structure: * **Monorepo Strategy**: Keep a `/docs` folder within your main application repository. This is ideal for ensuring that documentation changes are merged in the same Pull Request as the code they describe, maintaining perfect synchronisation. * **Separate Repository Strategy**: Best for large organisations or open-source projects where a dedicated team manages the documentation independently of the main application's build pipeline. ### 2. Validation with CI/CD Integrate `docmd` into your CI/CD pipeline to ensure that every update is technically sound. At a minimum, your pipeline should run the build command to check for syntax errors and configuration issues. ```bash # Example validation step in GitHub Actions - name: Validate Documentation run: npm install && npx @docmd/core build ``` See the [GitHub Actions Guide](../../guides/integrations/github-actions-cicd.md) for detailed setup instructions. ### 3. Collaborative Review Process Establish a culture of peer review for all documentation updates. Use Pull Requests to discuss changes, verify formatting, and ensure technical accuracy. You can use the [Threads Plugin](../../plugins/usage.md) to facilitate detailed discussions directly on the rendered content. ## Trade-offs Adopting a "docs-as-code" workflow can create a barrier for non-technical contributors (e.g., Product Managers or Legal teams) who may find Git and Markdown intimidating. To mitigate this, consider using GitHub's built-in web editor for minor fixes or using the [Live Preview](../../content/live-preview.md) feature to provide a more visual and intuitive authoring experience. --- ## [Versioning Workflows](https://docs.docmd.io/07/guides/workflows-teams/versioning-release-workflows/) --- title: "Versioning Workflows" description: "How to synchronise documentation releases with software deployment using docmd's versioning engine and promotion strategies." --- ## Problem Synchronising software releases with corresponding documentation updates is a significant coordination challenge. Frequently, documentation is updated on the live site before the new code is deployed (confusing current users) or delayed several days after the release (frustrating early adopters). ## Why it matters Desynchronisation between software behaviour and its documentation is a major source of developer friction. For documentation to be effective, it must strictly map to the specific version of the software the user is currently running. Providing the correct context for every version ensures a smooth onboarding and troubleshooting experience. ## Approach Isolate active development documentation using `docmd`'s [Versioning Engine](../../configuration/versioning.md). This allows your team to draft content for upcoming features asynchronously in a separate directory (e.g., `docs-next/`), promoting it to the "Stable" or "Current" status only when the official software release occurs. ## Implementation ### 1. Structure Your Directories Maintain your stable documentation in the primary `docs/` folder and create a dedicated directory for the upcoming release. ```text project-root/ ├── docs/ # Current Stable (v1.x) ├── docs-v2/ # Upcoming Release (v2.0) └── docmd.config.js ``` ### 2. Configure Versions Register both versions in your configuration. You can label the upcoming version as "Beta" or "Next" to signal its status to users through the version switcher. ```javascript // docmd.config.js export default { versions: { current: 'v1.0', all: [ { id: 'v1.0', dir: 'docs', label: 'v1.x (Stable)' }, { id: 'v2.0', dir: 'docs-v2', label: 'v2.0 (Beta)' } ] } }; ``` ### 3. The Promotion Process When you are ready to release the new version officially: 1. **Update Config**: Change the `current` version ID in `docmd.config.js` to `v2.0`. 2. **Update Labels**: Remove the "(Beta)" tag from the `label` in the `all` array. 3. **Archive Old Docs**: Keep the `v1.0` entry in the `all` array so users on older versions can still access their relevant documentation. ## Trade-offs ### Maintenance Overhead Maintaining multiple versions of documentation requires discipline. If a critical typo or security warning is fixed in the stable version, ensure it is also applied to the upcoming version directory to prevent "regressions" in clarity. ### SEO and Search Multiple versions can occasionally lead to search results pointing to older documentation. Use the `seo` plugin and proper canonical tags to ensure that the "Current" version is always prioritised by search engines. See [Handling Breaking Changes](../scaling-architecture/breaking-changes-deprecations.md) for more on managing transitions. --- ## [docmd docs: deploy production-ready docs from Markdown](https://docs.docmd.io/07/) --- title: "docmd docs: deploy production-ready docs from Markdown" description: "Build production-ready documentation from Markdown in seconds. Zero setup, fast by default, SEO-friendly, and AI-ready." titleAppend: false --- ::: hero # docmd Markdown to production docs in one command. Static HTML for SEO. SPA for speed. AI-ready by default. ::: button "Get Started" ./getting-started/quick-start.md icon:rocket ::: button "GitHub" external:https://github.com/docmd-io/docmd color:#333 icon:github ::: ## Start Get a production documentation site running in seconds - no boilerplate, no config files. ```bash npx @docmd/core dev ``` That's it. Write Markdown in a `docs/` folder and docmd builds a full documentation site with navigation, search, SEO, sitemap, and more - all out of the box. ## Core Capabilities Everything you need ships built-in. No plugins to install for the essentials. ::: grids ::: grid ::: card "Instant Setup" icon:rocket One command to go from Markdown files to a production documentation site. No config files required. ::: ::: ::: grid ::: card "AI Optimised" icon:brain-circuit Auto-generates `llms.txt` and `llms-full.txt` for LLM consumption. Your docs are AI-ready by default. ::: ::: ::: grid ::: card "Built-in Search" icon:search Client-side full-text search powered by MiniSearch. Works across versions and locales with zero setup. ::: ::: ::: grid ::: card "Live Previews" icon:monitor Embed docmd live, editable code sandboxes directly in your documentation pages. ::: ::: ::: grid ::: card "Theming Engine" icon:palette Switch between built-in themes or create your own. Supports light, dark, and system-preference modes. ::: ::: ::: grid ::: card "Native i18n" icon:globe First-class multi-language support with locale-first URLs, per-locale search, and translated UI strings. ::: ::: ::: ## Extending Markdown Go beyond static text. docmd provides rich container syntax directly in Markdown - callouts, tabs, cards, grids, hero sections, collapsible sections, and more. ::: button "Explore Containers" ./content/containers/index.md icon:blocks ::: grids ::: grid ::: card "Interactive Sandboxes" Embed live, editable preview windows naturally into your pages using the [Live Preview](./content/live-preview.md) API. ::: ::: ::: grid ::: card "Inline Collaboration" Select text in dev mode to open [Threads](./plugins/threads.md) and leave comments alongside your documentation team. ::: ::: ::: --- ## [Migrating from Docusaurus](https://docs.docmd.io/07/migration/docusaurus/) --- title: "Migrating from Docusaurus" description: "A comprehensive guide on moving your Docusaurus v2/v3 project to docmd." --- # Migrating from Docusaurus to docmd Docusaurus is a popular documentation framework built on React. `docmd` provides a fast, zero-config alternative that compiles significantly faster and doesn't require React components to render rich features. ## Step 1: Run the Migration Engine Run the following command at the root of your existing Docusaurus project (where your `docusaurus.config.js` or `docusaurus.config.ts` is located): ```bash npx @docmd/core migrate --docusaurus ``` ### What Happens Automatically 1. **Backup**: Your entire project (excluding `node_modules` and `.git`) is safely moved into a new `docusaurus-backup/` directory. 2. **Content Migration**: Your `docs/` folder is restored to the root directory for `docmd` to use. 3. **Config Generation**: A `docmd.config.js` is generated, extracting your site `title` from your Docusaurus configuration. ## Step 2: Test the Setup Once the command finishes, you can immediately preview your Markdown content in `docmd`: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration Docusaurus has complex programmatic configurations that `docmd` does not try to guess. You will need to map these manually. ### 1. Navigation Setup Docusaurus sidebars are often auto-generated or configured in `sidebars.js`. **Action required:** Create a `navigation.json` inside your new `docs/` directory to structure your `docmd` sidebar. See the [Navigation Guide](../configuration/navigation.md). ### 2. Replacing MDX Components Docusaurus relies heavily on MDX (`.mdx`) to render custom React components (like Tabs, Admonitions, or custom UI elements). `docmd` is purely Markdown-driven and does not use React. **Action required:** You must convert any custom `<MyReactComponent />` tags into standard Markdown or use `docmd`'s native [Containers](../content/containers/callouts.md). #### Example: Converting Admonitions **Docusaurus:** ```markdown :::tip My Tip This is a helpful tip. ::: ``` ::: callout success "Zero Changes Required" As of `docmd` 0.7.8, Docusaurus admonition syntax works **without any modification**. The following aliases are fully supported: - `:::note` → renders as `callout info` - `:::tip` → renders as `callout tip` - `:::info` → renders as `callout info` - `:::caution` → renders as `callout warning` - `:::danger` → renders as `callout danger` Spaceless syntax is also supported. Your existing Docusaurus admonitions will render correctly in `docmd` without changes. ::: **docmd native syntax** (optional, provides more features like custom icons): ```markdown ::: callout tip "My Tip" This is a helpful tip. ::: ``` #### Example: Converting Tabs **Docusaurus:** ```jsx import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; <Tabs> <TabItem value="apple" label="Apple" default> This is an apple. </TabItem> <TabItem value="orange" label="Orange"> This is an orange. </TabItem> </Tabs> ``` **docmd:** (Convert to the native `docmd` tabs container syntax) ```markdown ::: tabs == tab "Apple" This is an apple. == tab "Orange" This is an orange. ::: ``` ### 3. Localisation (i18n) If you used Docusaurus's `i18n` features, your translated files were likely in `i18n/locale/docusaurus-plugin-content-docs/current/`. **Action required:** Move these files into `docmd`'s directory structure (`docs/en/`, `docs/es/`, etc.) and configure the locales in `docmd.config.js`. See the [Localisation Guide](../configuration/localisation/index.md). ## Next Steps - Explore the [Layout & UI](../configuration/layout-ui.md) settings to match your Docusaurus theme. - Convert React-based hero headers into `docmd` [Hero Containers](../content/containers/hero.md). --- ## [Migrating from MkDocs](https://docs.docmd.io/07/migration/mkdocs/) --- title: "Migrating from MkDocs" description: "A comprehensive guide on moving your MkDocs (or Material for MkDocs) project to docmd." --- # Migrating from MkDocs to docmd MkDocs, particularly with the Material theme, is a popular Python-based documentation generator. `docmd` provides a similar Markdown-first experience, but relies on Node.js/Bun for incredibly fast builds and rich interactive features without the need for complex Python extensions. ## Step 1: Run the Migration Engine Run the following command at the root of your existing MkDocs project (where your `mkdocs.yml` is located): ```bash npx @docmd/core migrate --mkdocs ``` ### What Happens Automatically 1. **Backup**: Your entire project is safely moved into a new `mkdocs-backup/` directory. 2. **Content Migration**: Your `docs/` folder is restored to the root directory for `docmd` to use. 3. **Config Generation**: A `docmd.config.js` is generated, extracting your site `site_name` from your `mkdocs.yml`. ## Step 2: Test the Setup Once the command finishes, preview your content in `docmd`: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration MkDocs uses `mkdocs.yml` to define site navigation and extensions. You'll need to translate this setup to `docmd`. ### 1. Navigation Setup In MkDocs, navigation is strictly defined in the `nav` key of `mkdocs.yml`. **Action required:** You must create a `navigation.json` inside your `docs/` folder. **MkDocs (`mkdocs.yml`):** ```yaml nav: - Home: index.md - Guide: - Setup: setup.md - Usage: usage.md ``` **docmd (`navigation.json`):** ```json [ { "title": "Home", "path": "/" }, { "title": "Guide", "collapsible": true, "children": [ { "title": "Setup", "path": "/setup" }, { "title": "Usage", "path": "/usage" } ] } ] ``` ### 2. Replacing Python Markdown Extensions If you used "Material for MkDocs", you likely relied on Python Markdown extensions like PyMdown Extensions for tabs, admonitions, or task lists. **Action required:** Convert MkDocs-specific extension syntax to `docmd`'s native [Containers](../content/containers/callouts.md). #### Example: Converting Admonitions **MkDocs (PyMdown):** ```markdown !!! note "Optional Title" This is an admonition content block. ``` ::: callout warning "Manual Conversion Required" MkDocs uses `!!!` syntax for admonitions, which differs from the `:::` syntax used by `docmd`, VitePress, and Docusaurus. You will need to convert these manually or use a find-and-replace tool. **Mapping:** - `!!! note` → `::: callout info` or `:::note` - `!!! tip` → `::: callout tip` or `:::tip` - `!!! warning` → `::: callout warning` or `:::warning` - `!!! danger` → `::: callout danger` or `:::danger` - `!!! example` → `::: callout info` ::: **docmd:** ```markdown ::: callout info "Optional Title" This is an admonition content block. ::: ``` #### Example: Converting Tabs **MkDocs (SuperFences):** ```markdown === "Tab 1" Content for tab 1. === "Tab 2" Content for tab 2. ``` **docmd:** ```markdown ::: tabs == tab "Tab 1" Content for tab 1. == tab "Tab 2" Content for tab 2. ::: ``` ## Next Steps - `docmd` has native search. You do not need to configure a search plugin. - Explore the [Theming options](../theming/customisation.md) to customise your site's colours to match your old Material theme. --- ## [Migration Overview](https://docs.docmd.io/07/migration/overview/) --- title: "Migration Overview" description: "Learn how to easily migrate your existing documentation to docmd." --- # Migrating to docmd `docmd` provides a fully automated **migration engine** to help you transition from legacy or competing documentation platforms with a single command. The goal of the migration engine is to eliminate the tedious work of moving your markdown files and restructuring your project directory. ## How It Works The migration command will: 1. **Detect** your existing configuration file (e.g. `docusaurus.config.js`, `mkdocs.yml`). 2. **Extract** core metadata like your site's `title`. 3. **Backup** your existing files and directories safely into a `*-backup/` directory (e.g., `docusaurus-backup/`). 4. **Copy** your Markdown content into the standard `docmd` `docs/` directory. 5. **Generate** a fresh `docmd.config.js` tailored for your content. You can then run `npx @docmd/core dev` immediately to see your content rendered in the `docmd` engine. ## What is Migrated | Feature | Migrated Automatically? | | :--- | :--- | | **Markdown Files** | ✅ Yes, all `.md` and `.mdx` files are moved to `docs/` | | **Directory Structure** | ✅ Yes, your folder nesting is preserved | | **Site Title** | ✅ Yes, extracted from your config | | **Container Syntax** | ✅ Yes, VitePress/Docusaurus containers work without changes | | **Navigation / Sidebar** | ⚠️ **No**, requires manual mapping | | **Localisation (i18n)** | ⚠️ **No**, requires manual mapping | | **Versioning** | ⚠️ **No**, requires manual mapping | | **Custom React/Vue Components** | ❌ No, these must be replaced with `docmd` Containers | ::: callout success "Container Syntax Compatibility" As of `docmd` 0.7.8, container syntax from **VitePress** (`:::tip`, `:::warning`, `:::danger`, `:::info`, `:::details`) and **Docusaurus** (`:::note`, `:::caution`) works without modification. Your existing admonitions and collapsible sections will render correctly in `docmd`. **MkDocs** uses `!!!` syntax which requires manual conversion to `:::` format. ::: ## Why Navigation and i18n Aren't Automatically Migrated Every documentation platform handles navigation sidebars, translations, and multi-versioning differently. For example, Docusaurus uses complex JavaScript objects or autogenerated sidebars, while MkDocs relies on strictly indented YAML structures. Rather than risking an incorrect, broken migration by guessing complex configurations, `docmd` moves your content safely and asks you to configure navigation, localisation, and versioning natively using `docmd`'s simple JSON-based APIs. - **Navigation:** Learn how to create a `navigation.json` in the [Navigation Setup](../configuration/navigation.md). - **Localisation:** See the [Localisation Guide](../configuration/localisation/index.md) for setting up multi-language docs. - **Versioning:** Refer to the [Versioning Setup](../configuration/versioning.md). ## Supported Platforms Select your current platform for specific migration instructions: - [Migrating from Docusaurus](./docusaurus.md) - [Migrating from MkDocs](./mkdocs.md) - [Migrating from VitePress](./vitepress.md) - [Migrating from Astro Starlight](./starlight.md) --- ## [Migrating from Astro Starlight](https://docs.docmd.io/07/migration/starlight/) --- title: "Migrating from Astro Starlight" description: "A comprehensive guide on moving your Astro Starlight project to docmd." --- # Migrating from Astro Starlight to docmd Starlight is an excellent documentation theme built on the Astro framework. `docmd` provides a similar zero-JavaScript-by-default experience, but eliminates the need to configure a full web framework (Astro), dramatically reducing the learning curve for technical writers. ## Step 1: Run the Migration Engine Run the following command at the root of your existing Starlight project (where your `astro.config.mjs` is located): ```bash npx @docmd/core migrate --starlight ``` ### What Happens Automatically 1. **Backup**: Your entire project is safely moved into a new `starlight-backup/` directory. 2. **Content Migration**: Starlight keeps documentation in `src/content/docs/`. The migration engine automatically extracts this specific directory and moves its contents to the root `docs/` folder for `docmd` to use. 3. **Config Generation**: A `docmd.config.js` is generated, extracting your site `title` from the Starlight integration inside `astro.config.mjs`. ## Step 2: Test the Setup Once the command finishes, preview your content in `docmd`: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration ### 1. Navigation Setup Starlight defines navigation in `astro.config.mjs` via the `sidebar` array. **Action required:** You must create a `navigation.json` inside your new `docs/` folder. **Starlight (`astro.config.mjs`):** ```js sidebar: [ { label: 'Guides', items: [ { label: 'Setup', link: '/guides/setup/' } ], }, ] ``` **docmd (`navigation.json`):** ```json [ { "title": "Guides", "collapsible": true, "children": [ { "title": "Setup", "path": "/guides/setup" } ] } ] ``` ### 2. Replacing Astro Components (MDX/Markdoc) Starlight uses Astro components (`<Tabs>`, `<Card>`, etc.) embedded via MDX or Markdoc. Because `docmd` relies on pure Markdown syntax instead of UI components, these must be converted. **Action required:** Replace Astro components with `docmd` [Containers](../content/containers/callouts.md). #### Example: Converting Tabs **Starlight:** ```mdx import { Tabs, TabItem } from '@astrojs/starlight/components'; <Tabs> <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> <TabItem label="Moons">Io, Europa, Ganymede</TabItem> </Tabs> ``` **docmd:** ```markdown ::: tabs == tab "Stars" Sirius, Vega, Betelgeuse == tab "Moons" Io, Europa, Ganymede ::: ``` #### Example: Converting Asides (Admonitions) **Starlight:** ```mdx :::note[Optional Title] Some note content. ::: ``` **docmd:** ```markdown ::: note "Optional Title" Some note content. ::: ``` ### 3. Frontmatter Mapping Starlight has strict frontmatter typing via Astro content collections. `docmd` frontmatter is simpler. If you used `hero` or `banner` frontmatter properties in Starlight for landing pages, you will need to replace them with `docmd`'s [Hero Sections](../content/containers/hero.md) written directly in the Markdown body. ## Next Steps - Explore `docmd`'s built-in [Search plugin](../plugins/search.md) (Starlight uses Pagefind, while `docmd` ships with a highly optimised local search indexer natively). --- ## [Migrating from VitePress](https://docs.docmd.io/07/migration/vitepress/) --- title: "Migrating from VitePress" description: "A comprehensive guide on moving your VitePress project to docmd." --- # Migrating from VitePress to docmd VitePress is a fast Vue-powered SSG framework. Like VitePress, `docmd` is exceptionally fast, but it achieves this by shipping absolutely zero JavaScript framework logic to the client (no Vue hydration overhead). ## Step 1: Run the Migration Engine Run the following command at the root of your existing VitePress project: ```bash npx @docmd/core migrate --vitepress ``` ### What Happens Automatically 1. **Backup**: Your entire project is safely moved into a new `vitepress-backup/` directory. 2. **Content Migration**: Your `docs/` folder is restored to the root directory for `docmd` to use. The `.vitepress` hidden configuration folder is completely stripped from the new `docs/` directory to prevent conflicts. 3. **Config Generation**: A `docmd.config.js` is generated, extracting your site `title` from your `.vitepress/config.js` or `.ts`. ## Step 2: Test the Setup Once the command finishes, preview your content in `docmd`: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration VitePress configures navigation in its config file and uses Vue components inside Markdown. You will need to translate these to `docmd`. ### 1. Navigation Setup VitePress uses an array of objects in `themeConfig.sidebar`. **Action required:** Create a `navigation.json` inside your `docs/` directory. **VitePress (`.vitepress/config.js`):** ```js themeConfig: { sidebar: [ { text: 'Guide', items: [ { text: 'Introduction', link: '/introduction' }, { text: 'Getting Started', link: '/getting-started' } ] } ] } ``` **docmd (`navigation.json`):** ```json [ { "title": "Guide", "collapsible": true, "children": [ { "title": "Introduction", "path": "/introduction" }, { "title": "Getting Started", "path": "/getting-started" } ] } ] ``` ### 2. Replacing Vue Components VitePress allows authors to embed Vue components directly in Markdown files (e.g., `<MyComponent />`). Because `docmd` does not run Vue on the client, you must remove these custom components or replace them with native Markdown. **Action required:** Replace Vue-specific UI components with `docmd` [Containers](../content/containers/callouts.md). #### Example: Admonitions (Custom Containers) VitePress uses a markdown-it custom block syntax that looks very similar to `docmd`. **VitePress:** ```markdown ::: info This is an info box. ::: ``` **docmd:** ```markdown ::: info This is an info box. ::: ``` ::: callout success "Zero Changes Required" As of `docmd` 0.7.8, VitePress container syntax works **without any modification**. The following aliases are fully supported: - `:::tip` → renders as `callout tip` - `:::warning` → renders as `callout warning` - `:::danger` → renders as `callout danger` - `:::info` → renders as `callout info` - `:::details` → renders as `collapsible` Spaceless syntax (e.g., `:::tip` instead of `::: tip`) is also supported. Your existing VitePress content will render correctly in `docmd` without changes. ::: ## Next Steps - Explore `docmd`'s [Build & Deploy](../deployment/index.md) guide since `docmd` does not rely on Vite's build pipeline. - Review the full list of [docmd Containers](../content/containers/index.md) for additional UI components. --- ## [Analytics Plugin](https://docs.docmd.io/07/plugins/analytics/) --- title: "Analytics Plugin" description: "Integrate Google Analytics 4 or legacy Universal Analytics and track user interactions automatically." --- The `@docmd/plugin-analytics` plugin allows you to easily integrate Google Analytics into your documentation. It supports the modern Google Analytics 4 (GA4) standard, legacy Universal Analytics (UA), and includes native event tracking for interaction-heavy documentation sites. ## Configuration Enable analytics by adding your tracking credentials to the `plugins` section of your `docmd.config.js`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `googleV4` | `object` | `null` | Google Analytics 4 configuration (requires `measurementId`). | | `googleUA` | `object` | `null` | Universal Analytics configuration (requires `trackingId`). | | `autoEvents` | `boolean` | `true` | Automatically track clicks, downloads, and TOC interactions. | | `trackSearch` | `boolean` | `true` | Track search keywords used by readers. | ### Usage ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { analytics: { googleV4: { measurementId: 'G-XXXXXXX' }, autoEvents: true, trackSearch: true } } }); ``` ## Tracked Events When `autoEvents` is enabled, the plugin automatically captures the following user interactions: - **External Links**: Track when users depart for external resources. - **File Downloads**: Log clicks on links with the `download` attribute or common file extensions. - **Table of Contents (TOC)**: Monitor section engagement by tracking clicks in the right-hand navigation. - **Heading Anchors**: Log when users click on "permalinks" to share specific sections. - **Search Queries**: Capture keywords used in the search bar (with a 1-second debounce). ::: callout info "Privacy & GDPR" By default, this plugin does not anonymise IP addresses as that is now handled natively by GA4. If you require advanced cookie consent management, you can manually inject scripts using a custom plugin hook. ::: --- ## [Building Plugins](https://docs.docmd.io/07/plugins/building-plugins/) --- title: "Building Plugins" description: "A comprehensive guide to extending docmd with custom logic, data injection, and interactive features." --- Plugins are the primary extension mechanism for `docmd`. They allow you to inject custom HTML, modify the Markdown parsing logic, inject build-time data before template rendering, and automate post-build tasks. This guide outlines the plugin API and best practices for creating shareable components. ## Plugin Descriptor Every plugin should export a `plugin` descriptor declaring its identity and capabilities. This enables the engine to validate, isolate, and enforce capability boundaries at load time. ```javascript export default { plugin: { name: 'my-analytics', version: '1.0.0', capabilities: ['head', 'body', 'post-build'] }, generateScripts: (config, opts) => { ... }, onPostBuild: async (ctx) => { ... } }; ``` > **Note:** The descriptor is currently optional (soft deprecation warning). It will be **required starting 0.8.0**. ## Core Capabilities The `capabilities` array dictates which hooks your plugin is allowed to use. | Capability | Allowed Hooks | Phase | | :--- | :--- | :--- | | `init` | `onConfigResolved` | Init | | `markdown` | `markdownSetup` | Setup | | `head` | `generateMetaTags`, `generateScripts` (head) | Render | | `body` | `generateScripts` (body) | Render | | `build` | `onBeforeParse`, `onAfterParse`, `onBeforeRender`, `onPageReady` | Build | | `post-build`| `onPostBuild` | Post-Build | | `dev` | `onDevServerReady` | Dev Server | | `assets` | `getAssets` | Output | | `actions` | `actions` | Interactive | | `events` | `events` | Interactive | | `translations`| `translations` | i18n | Legacy plugins without a descriptor get full access to all hooks, so nothing breaks during the transition. ## Plugin API Reference A `docmd` plugin is a standard JavaScript object (or a module that exports one as default) that implements one or more of the following hooks. | Hook | Description | | :--- | :--- | | `markdownSetup(md, opts)` | Extend the `markdown-it` instance. Synchronous. | | `generateMetaTags(config, page, root)` | Inject `<meta>` or `<link>` tags into the `<head>`. | | `generateScripts(config, opts)` | Return an object containing `headScriptsHtml` and `bodyScriptsHtml`. | | `getAssets(opts)` | Define external files or CDN scripts to be injected. | | `onPostBuild(ctx)` | Run logic after the generation of all HTML files. | | `translations(localeId)` | Return an object of translated strings for the given locale. | | `actions` | An object of named action handlers for WebSocket RPC calls from the browser. | | `events` | An object of named event handlers for fire-and-forget messages from the browser. | ## Creating a Local Plugin Creating a plugin is as simple as defining a JavaScript file. For example, `my-plugin.js`: ```javascript // my-plugin.js import path from 'path'; export default { // Plugin descriptor (recommended) plugin: { name: 'my-plugin', version: '1.0.0', capabilities: ['head', 'post-build'] }, // 1. Extend the Markdown Parser markdownSetup: (md, options) => { // Example: Add a rule or use a markdown-it plugin }, // 2. Inject Page Metadata generateMetaTags: async (config, page, relativePathToRoot) => { return `<meta name="x-build-id" content="${config._buildHash}">`; }, // 3. Post-Build Automation onPostBuild: async ({ config, pages, outputDir, log, options }) => { log(`Custom Plugin: Verified ${pages.length} pages.`); // Example: Generate a custom manifest or notification } }; ``` To enable your plugin, reference its **full package name** in your `docmd.config.js`: ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { 'my-awesome-plugin': { // Your custom options go here } } }); ``` > **Note:** Shorthand names (e.g. `math`, `search`) are reserved exclusively for official `@docmd/plugin-*` packages. Third-party plugins must always be referenced by their full npm package name. ### Plugin Resolution The `docmd` engine resolves plugin names as follows: - **Official shorthands** (`math`, `search`, `seo`, etc.) automatically expand to `@docmd/plugin-<name>`. Since the `@docmd` npm scope is owned by the project, only official packages can exist under it. - **Third-party plugins** must use their full package name (e.g. `my-awesome-plugin`, `@myorg/docmd-extras`). There is no alias or shorthand system for external plugins - this prevents confusion and eliminates supply-chain attack vectors entirely. ### Plugin Isolation Every hook invocation is wrapped in a try/catch boundary. A broken plugin cannot crash the build or interfere with other plugins. Errors are logged and collected into a summary at the end of the build. ### Scoping Plugins (`noStyle`) By default, plugins inject their CSS/JS universally. However, developers can explicitly prevent their plugin from rendering on `noStyle` pages (like minimal landing templates) by exporting a `noStyle` boolean: ```javascript export default { noStyle: false, // Prevents generateMetaTags and generateScripts from running on noStyle pages generateScripts: () => { ... } } ``` Users can also override this behaviour through their configuration (`plugins: { math: { noStyle: false } }`) or dynamically via Markdown frontmatter (`plugins: { math: true }`). ## Lifecycle Hooks Docmd provides deep integration hooks that allow plugins to manipulate configuration, raw sources, and page data throughout the build pipeline. | Hook | Description | Expected Return | | :--- | :--- | :--- | | **`onConfigResolved(config)`** | Reads or modifies the active normalised `config` right after initialisation. | `void` or `Promise<void>` | | **`onDevServerReady(server, wss)`** | Exposes the raw Node.js `http.Server` and `WebSocketServer` during development mode (`docmd dev`). | `void` or `Promise<void>` | | **`onBeforeParse(src, frontmatter)`** | Pre-processes raw markdown string data immediately before it is passed to markdown-it for parsing. | `string` or `Promise<string>` | | **`onAfterParse(html, frontmatter)`** | Post-processes generated HTML representing the markdown body segment. | `string` or `Promise<string>` | | **`onBeforeRender(page)`** | Called before template rendering. Receives the full `PageContext`. Mutations to `frontmatter` and `html` are reflected in the rendered output. | `void` or `Promise<void>` | | **`onPageReady(page)`** | Accesses the fully assembled page metadata (`page.html`, `page.outputPath`, `page.frontmatter`) just before it is written to the destination file. | `void` or `Promise<void>` | ### `onBeforeRender` and `PageContext` The `onBeforeRender` hook is the right place for plugins that need to inject build-time data derived from the source file - reading file metadata, computing custom frontmatter fields, or loading data from external sources. ```typescript interface PageContext { sourcePath: string; // Absolute path to the .md source file. Always set. frontmatter: Record<string, any>; // Mutable - changes reflected in template output html: string; // Mutable - rendered markdown body localeId?: string; versionId?: string; relativePathToRoot?: string; } ``` ```javascript export default { plugin: { name: 'my-metadata-plugin', version: '1.0.0', capabilities: ['build'] }, onBeforeRender: async (page) => { // sourcePath is always available - no guessing or path construction needed const stats = fs.statSync(page.sourcePath); page.frontmatter.wordCount = page.html.split(/\s+/).length; page.frontmatter.fileSize = stats.size; } }; ``` ```javascript export default { plugin: { name: "my-advanced-plugin", version: "1.0.0", capabilities: ["init", "build", "dev"] }, onConfigResolved: (config) => { config.siteTitle = config.siteTitle + " (Modified)"; }, onBeforeParse: (src, frontmatter) => { return src.replace(/foo/gi, 'bar'); }, onBeforeRender: async (page) => { // Inject data before template rendering page.frontmatter.customField = 'value'; }, onPageReady: (page) => { // Append custom tracking script into the final HTML page.html = page.html.replace('</body>', '<script>/* tracker */</script></body>'); } } ``` ## Deep Dive: Asset Injection The `getAssets()` hook allows your plugin to bundle client-side logic securely. ```javascript getAssets: (options) => { return [ { url: 'https://cdn.example.com/lib.js', // External CDN script type: 'js', location: 'head' }, { src: path.join(__dirname, 'plugin-init.js'), // Local source dest: 'assets/js/plugin-init.js', // Destination in build/ type: 'js', location: 'body' } ]; } ``` ## Translating Plugins (i18n) Plugins that render client-side UI should expose translatable strings via the `translations(localeId)` hook. The docmd engine will call this hook during the build process, merge the results with core system strings and user overrides, and pass them down. The standard pattern is to store a JSON file for each language in an `i18n/` directory inside your plugin: ```javascript // my-plugin.js import fs from 'fs'; import path from 'path'; export default { plugin: { name: 'my-plugin', version: '1.0.0', capabilities: ['translations', 'body'] }, translations: (localeId) => { // 1. Try loading the specific locale try { const p = path.join(__dirname, 'i18n', `${localeId}.json`); return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { } // 2. Fall back to English try { const p = path.join(__dirname, 'i18n', 'en.json'); return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { } return {}; } } ``` You can then inject these strings via `generateScripts` (using `config._activeLocale.id` to determine the current language), or rely on the engine to merge them into a global registry. ## WebSocket RPC Actions Starting in `0.6.8`, plugins can register **action handlers** and **event handlers** that run on the dev server and are callable from the browser via the `window.docmd` API. ```javascript // my-live-plugin.js export default { plugin: { name: 'my-live-plugin', version: '1.0.0', capabilities: ['actions', 'events'] }, // Server-side action - browser calls via docmd.call() actions: { 'my-plugin:save-note': async (payload, ctx) => { const content = await ctx.readFile(payload.file); const updated = content + '\n\n> ' + payload.note; await ctx.writeFile(payload.file, updated); return { saved: true }; } }, // Server-side event - browser sends via docmd.send() events: { 'my-plugin:page-viewed': (data, ctx) => { console.log(`Page viewed: ${data.path}`); } } }; ``` The `ctx` (ActionContext) object provides: | Method | Description | | :--- | :--- | | `ctx.readFile(path)` | Read a file relative to the project root. | | `ctx.writeFile(path, content)` | Write a file (triggers rebuild + reload). | | `ctx.readFileLines(path)` | Read a file as an array of lines. | | `ctx.broadcast(event, data)` | Push an event to all connected browsers. | | `ctx.source` | Source editing tools for block-level markdown manipulation. | | `ctx.projectRoot` | Absolute path to the project root. | | `ctx.config` | Current docmd site configuration. | All file operations are sandboxed to the project root - path traversal attempts are rejected automatically. ::: callout info "Dev Mode Only 🛡️" The WebSocket RPC system is only active during `docmd dev`. Production builds do not include the API client or any server-side action handling. ::: ## Best Practices 1. **Declare Capabilities**: Always export a `plugin` descriptor with your declared capabilities. This enables the engine to enforce boundaries and will be required in `0.8.0`. 2. **Use `onBeforeRender` for data injection**: If your plugin reads the source file or computes frontmatter fields, use `onBeforeRender` - not `generateMetaTags`. The `sourcePath` is always available in `PageContext`. 3. **Async/Await**: Always use `async` functions for `onPostBuild`, `onBeforeRender`, and action handlers to prevent blocking the build engine during I/O operations. 4. **Statelessness**: Avoid maintaining state within the plugin object, as `docmd` may re-initialise plugins during development rebuilds. 5. **Naming Convention**: For community plugins, prefix your package name with `docmd-plugin-` (e.g., `docmd-plugin-analytics`). 6. **Action Namespacing**: Prefix your action names with your plugin name (e.g., `my-plugin:save-note`) to avoid collisions. 7. **Action Validation**: Always define and require an explicit payload schema in your actions. This ensures a secure plugin ecosystem where unknown payload properties are stripped or rejected. 8. **Logging**: Use the provided `log()` helper in `onPostBuild` to ensure your messages respect the user's `--verbose` settings. ::: callout tip "AI-Ready Design 🤖" The `docmd` plugin API is designed to be **LLM-Optimal**. Because the hooks use standard JavaScript objects and types without hidden complex class hierarchies, AI agents can generate bug-free custom plugins for you with minimal instruction. ::: --- ## [Git Plugin](https://docs.docmd.io/07/plugins/git/) --- title: "Git Plugin" description: "Repository-aware metadata, last-updated timestamps, and automated edit links derived from Git history." --- The `@docmd/plugin-git` plugin adds repository intelligence to your documentation. It automatically displays when each page was last modified, who contributed to it, and provides an optional "Edit this page" link - all extracted directly from your Git history at build-time. ## Configuration | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `repo` | `string` | `null` | Repository URL (e.g. `https://github.com/org/repo`). Required for edit links. | | `branch` | `string` | `'main'` | Branch name for edit links. | | `editLink` | `boolean` | `true` | Show "Edit this page" link when `repo` is set. | | `lastUpdated` | `boolean` | `true` | Show last updated timestamp. | | `commitHistory` | `boolean` | `true` | Show commit history tooltip on hover. | | `maxCommits` | `number` | `6` | Maximum commits to show in the tooltip. | | `dateFormat` | `string` | `'relative'` | Timestamp format: `relative` (default), `iso`, or `locale-aware`. | ### Usage ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { git: { repo: 'https://github.com/docmd-io/docs', branch: 'main', editLink: true, lastUpdated: true, commitHistory: true, maxCommits: 5 } } }); ``` ## Features - **Last Updated Timestamps**: Automatically shows when a page was last modified in the footer. - **Commit History Tooltip**: Hovering over the timestamp reveals a list of recent commits for that specific page. - **Automated Edit Links**: Provides a link to edit the source file on GitHub, GitLab, or Bitbucket. - **Performance-First**: Git history is queried once and cached at build-time, ensuring zero impact on site performance. ## Usage Once configured, the plugin works automatically. Timestamps and edit links appear in the page footer. ### Footer Example ::: callout info "Rendering Result" The footer of this page (and all others in this documentation) is rendered by the Git plugin. Scroll to the bottom to see it in action - hover over the **Last updated** date to see the commit history. ::: ## Per-Page Control Disable Git features for specific pages via frontmatter: ```markdown --- title: "Internal Notes" plugins: git: false --- ``` ## CI/CD Integration The Git plugin reads your repository history at build-time using local Git commands. Many CI/CD providers use "shallow clones" by default (fetching only the last commit), which will cause the plugin to only show the most recent change across all pages. To ensure accurate timestamps and history, you must configure your CI environment to perform a full fetch. ::: tabs == tab "GitHub Actions" Add `fetch-depth: 0` to your checkout step: ```yaml - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 ``` == tab "GitLab CI" Set the `GIT_DEPTH` variable to `0`: ```yaml variables: GIT_DEPTH: 0 ``` == tab "Netlify" Netlify fetches the full history by default. However, if you have issues, ensure your build command has access to the `.git` directory. No additional configuration is usually required. ::: ::: callout warning "Git Data Requirement" The `.git` directory must be present in the build environment for the plugin to function. If you are building inside a Docker container or a restricted CI environment, ensure the Git history is preserved and that the `git` binary is installed. ::: ## Localisation The plugin includes built-in translations for English, German, and Chinese. Custom strings can be provided through the [UI Localisation](../configuration/localisation/ui-strings.md) system. --- ## [LLM Context Plugin](https://docs.docmd.io/07/plugins/llms/) --- title: "LLM Context Plugin" description: "Optimise your documentation for AI consumption with automated llms.txt and llms-full.txt generation." --- The `@docmd/plugin-llms` plugin ensures your documentation is perfectly optimised for Large Language Models (LLMs) and AI Agents. It follows the growing industry standard of providing a high-level summary and a comprehensive context file that AI tools can ingest to understand your project with minimal hallucination. ## Configuration The LLM plugin is enabled by default. To function correctly, you must provide a `url` in your `docmd.config.js`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable the LLM context generation. | | `fullContext` | `boolean` | `true` | If true, generates a `llms-full.txt` file containing the content of all pages. | | `maxTokenLimit` | `number` | `null` | Optional limit on the total characters/tokens for context files. | ### Usage ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ url: 'https://docs.example.com', plugins: { llms: { fullContext: true } } }); ``` ## Usage Once configured, the plugin automatically generates `llms.txt` and `llms-full.txt` in your site root during every build. These files are linked in the page `<head>` for automatic discovery by AI tools. ### Excluding a Page If a page contains sensitive information or internal notes you don't want AI models to learn, use the `llms: false` flag in your frontmatter: ```markdown --- title: "Internal Dev Secrets" llms: false --- ``` ::: callout tip "Maximising AI Accuracy" For detailed best practices on structuring your markdown (semantic headings, alt-text, etc.), see our [Optimising for AI Agents](../guides/ai-optimisation/generating-ai-ready-docs.md) guide. ::: --- ## [Math Plugin](https://docs.docmd.io/07/plugins/math/) --- title: "Math Plugin" description: "Native KaTeX/LaTeX mathematics integration for docmd." --- The **Math plugin** adds native LaTeX and KaTeX support to your docmd sites. It utilises `markdown-it-texmath` as securely integrated with the `katex` computation engine to render both inline and block-level mathematical equations smoothly without requiring complex client-side javascript libraries. ## Setup ```bash docmd add math ``` ```javascript plugins: { math: {} } ``` ## How It Works 1. Enable the plugin via your `docmd.config.js`. 2. Wrap your standard LaTeX mathematics in `$` (inline) or `$$` (block) indicators. 3. The server intelligently processes these math rules during the static-site build exactly as raw static HTML tags. 4. Minimal injected CSS automatically scopes these classes directly, yielding immediate visualisation the moment the user views the page! ## Usage ### Inline Mathematics You can inject standard equations flawlessly within a paragraph utilising single dollar signs `$`: ```markdown Here is an inline equation: $E = mc^2$ ``` Here is an inline equation: $E = mc^2$ ### Block Mathematics For wider mathematical proofs or distinct formulations, use double dollar signs `$$` for block level formatting: ```markdown $$ \sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$ ``` $$ \sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$ --- ## [Mermaid Diagrams](https://docs.docmd.io/07/plugins/mermaid/) --- title: "Mermaid Diagrams" description: "Create professional architectural diagrams, flowcharts, and sequence diagrams directly in your Markdown files using Mermaid.js syntax." --- The `@docmd/plugin-mermaid` plugin integrates the powerful [Mermaid.js](external:https://mermaid.js.org/) engine into your documentation pipeline. It allows you to transform plain-text descriptions into high-fidelity, interactive diagrams with built-in support for themes, panning, and zooming. ## Configuration The Mermaid plugin is bundled with `@docmd/core` and enabled by default. No mandatory configuration is required. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable Mermaid diagram rendering globally. | ### Example ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { mermaid: {} // Enabled by default } }); ``` ## Features - **Theme Awareness**: Diagrams automatically adapt to **Light** or **Dark** mode transitions. - **Interactive Controls**: Built-in **Pan**, **Zoom**, and **Fullscreen** buttons for every diagram. - **Lazy Loading**: Diagrams are initialised only as they enter the user's viewport for optimum performance. - **Icon Support**: Deep integration with the **Lucide** icon pack (use `icon:name` syntax). ## Usage Embed diagrams using a fenced code block with the `mermaid` language identifier. ### Sequence Diagram Example ::: tabs == tab "Preview" ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Enters URL Browser->>Server: HTTP Request Server-->>Browser: HTTP Response Browser-->>User: Displays Page ``` == tab "Source" ````markdown ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Enters URL Browser->>Server: HTTP Request Server-->>Browser: HTTP Response Browser-->>User: Displays Page ``` ```` ::: ### Architecture Example ```mermaid architecture-beta group api(icon:cloud)[API Service] service db(icon:database)[Database] in api service disk(icon:hard-drive)[Storage] in api db:L -- R:disk ``` ::: callout tip "AI Readability" Because Mermaid diagrams are defined as pure text in your Markdown, they are fully readable by AI agents. This allows LLMs to understand and explain your system architecture directly from your documentation source. ::: --- ## [OpenAPI Plugin](https://docs.docmd.io/07/plugins/openapi/) --- title: "OpenAPI Plugin" description: "Static API reference documentation rendered directly from OpenAPI 3.x specifications at build-time." --- The `@docmd/plugin-openapi` plugin converts OpenAPI 3.x specification files into structured, searchable API reference pages. It follows the Docmd "Zero-JS" philosophy - rendering every endpoint, parameter, and response into semantic HTML tables during the build process, ensuring maximum performance and SEO. ## Configuration The OpenAPI plugin is included by default in `@docmd/core`. You can configure global rendering options in your `docmd.config.js`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `info` | `boolean` | `true` | Display the API title, version, and description from the spec's `info` object. | | `download` | `boolean` | `false` | If true, adds a link to the header of the spec to download the raw JSON/YAML file. | | `summaryOnly` | `boolean` | `false` | If true, only renders the method, path, and summary. Useful for large API indexes. | | `allowRawHtml` | `boolean` | `false` | If true, prevents escaping of HTML tags in descriptions. | ### Example ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { openapi: { info: true, download: true, summaryOnly: false } } }); ``` ## Usage Embed an OpenAPI specification anywhere in your Markdown using a fenced code block with the `openapi` tag. The path is resolved relative to your project source. ````markdown ```openapi assets/openapi.json ``` ```` ### Rendering Result ```openapi assets/docmd-api.json ``` ## What Gets Rendered For each path and HTTP method in the spec, the plugin renders: - **Method badge** - colour-coded (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) - **Path** - the full endpoint path with parameters highlighted - **Summary and description** - from the operation object - **Parameters table** - name, location (`path`, `query`, `header`, `cookie`), type, required flag, description - **Request body table** - schema properties with types and defaults - **Responses table** - status codes with descriptions and response schema types - **Deprecated notice** - operations marked `deprecated: true` are flagged inline ::: callout tip "Build-Time Rendering" All rendering happens at build time. The generated pages are fully static - no JavaScript is needed to display the API docs, which means fast page loads and full search indexation. This approach ensures zero-JS performance and SEO-friendliness. ::: ## Capability Support | Feature | Support | | :--- | :--- | | OpenAPI 3.x | ✓ (JSON & YAML*) | | Swagger 2.x | ✗ (Convert to 3.x first) | | `$ref` Resolution | ✓ (Internal schemas) | | `oneOf` / `anyOf` | ✓ (Shown as union types) | | `deprecated` flag | ✓ | *\*YAML support requires the `js-yaml` package to be installed in your project.* --- ## [PWA & Offline Support](https://docs.docmd.io/07/plugins/pwa/) --- title: "PWA & Offline Support" description: "Transform your documentation into a progressive web application with offline caching and mobile-first features." --- The `@docmd/plugin-pwa` plugin transforms your documentation into a Progressive Web App (PWA). It adds a web manifest for mobile installation and registers a service worker for intelligent offline caching, ensuring your technical manuals remain accessible even in low-connectivity environments. ## Configuration Customise your app branding within the `plugins` section of your `docmd.config.js`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable PWA manifest and service worker generation. | | `themeColor` | `string` | `'#1e293b'` | The primary colour of the mobile UI browser chrome. | | `bgColor` | `string` | `'#ffffff'` | Background colour for the splash screen during installation. | | `logo` | `string` | `null` | Path to the app icon (relative to project source). | ### Example ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { pwa: { themeColor: '#1e293b', bgColor: '#ffffff', logo: 'assets/app-icon.png' } } }); ``` ## Features - **Offline Caching**: Uses a "Stale-While-Revalidate" strategy to serve pages instantly from the cache while updating in the background. - **Mobile Installation**: Generates a `manifest.webmanifest` allowing users to "Add to Home Screen" on iOS and Android. - **Smart Asset Resolution**: Automatically generates app icons from your project logo or favicon if no explicit icon is provided. - **SPA Compatible**: Fully compatible with Single Page Application transitions and standard directory routing. ## Icon Resolution Priority The plugin resolves your PWA icons based on the following priority: 1. `pwa.icons` - Explicit array in config. 2. `pwa.logo` - Path relative to source. 3. `config.logo` - Global site logo. 4. `config.favicon` - Global favicon. ::: callout tip "Testing PWA Features" Service workers are bypassed in `docmd dev` to prevent caching issues during editing. To test PWA features, run `docmd build` and serve the `site/` directory using a static host. ::: --- ## [Search Plugin](https://docs.docmd.io/07/plugins/search/) --- title: "Search Plugin" description: "Enable high-speed, offline-first full-text search for your documentation using MiniSearch." --- The `@docmd/plugin-search` plugin provides a powerful, client-side search experience for your documentation. It uses [MiniSearch](external:https://github.com/lucaong/minisearch) to build a lightweight index during the build process, allowing users to find technical information instantly without a server-side database. ## Configuration Search is enabled by default in most `docmd` templates. You can control its visibility and placement via the `layout` configuration. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable the full-text search indexer. | | `placeholder` | `string` | `'Search...'` | Custom placeholder text for the search input. | | `maxResults` | `number` | `10` | Maximum number of results to display in the modal. | ### Usage ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ layout: { optionsMenu: { position: 'header', // 'header', 'sidebar-top', 'sidebar-bottom', or 'menubar' components: { search: true // Set to false to disable the search plugin entirely } } } }); ``` ## How It Works ### 1. Indexing (Build-time) During the `docmd build` process, the search plugin iterates through every page on your site. It extracts the title, headings, and plain-text prose, then compiles this data into a compressed `search-index.json` file. * **Deep Linking**: The indexer automatically registers every heading (`#`, `##`, etc.) as a searchable target. * **Relevancy Boosting**: Titles are given the highest weight, followed by headings, then page content. ### 2. Retrieval (Client-side) When a user opens the search modal (usually via `/` or `Ctrl+K`), the `search-index.json` is fetched by the browser. Searches are performed locally using fuzzy matching (allowing for small typos) and instant prefix matching. ## Customising Search Behaviour While the search plugin is designed for zero-config simplicity, you can exclude specific pages from the index by using the `noindex` flag in their frontmatter: ```yaml --- title: "Internal Specification" noindex: true # This page will not appear in search results or sitemaps --- ``` ## Technical Implementation The plugin injects a lightweight search modal into the `<body>` of your site. It is fully accessible (ARIA compliant) and supports keyboard navigation for a native app-like experience. ::: callout tip "Search Analytics" If you have the [Analytics Plugin](./analytics.md) enabled, search keywords used by your readers are automatically captured and sent to your analytics provider, giving you insights into what information is missing or hardest to find. ::: Because the search happens entirely on the client, no data - not even keystrokes - is ever sent to a server. This makes `docmd` the Gold Standard for documentation search in privacy-sensitive industries (Healthcare, Finance, Security). ## Comparison Many documentation generators (like Docusaurus) rely on **Algolia DocSearch**. While Algolia is powerful, it introduces friction: | Feature | docmd Search | Algolia / External | | :--- | :--- | :--- | | **Setup** | **Zero Config** (Automatic) | Complex (API Keys, CI/CD crawling) | | **Privacy** | **100% Private** (Client-side) | Data sent to 3rd party servers | | **Offline** | **Yes** | No | | **Cost** | **Free** | Free tier limits or Paid | | **Speed** | **Instant** (In-memory) | Fast (Network latency dependent) | --- ## [SEO Plugin](https://docs.docmd.io/07/plugins/seo/) --- title: "SEO Plugin" description: "Optimise your documentation for search engines and control AI crawler access with native meta tag generation." --- The `@docmd/plugin-seo` plugin generates high-quality metadata for every page. It ensures your documentation is not only discoverable by human readers on search engines but also correctly interpreted by AI models and social media platforms. ## Configuration Configure site-wide SEO defaults in your `docmd.config.js`. Page-level settings always take precedence over global defaults. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `defaultDescription` | `string` | `null` | Fallback description for pages without frontmatter descriptions. | | `aiBots` | `boolean` | `true` | Set to `false` to block common AI crawlers (GPTBot, Claude-Web, etc.). | | `openGraph` | `object` | `null` | Open Graph settings for social media (Facebook, LinkedIn). | | `twitter` | `object` | `null` | Twitter (X) Card settings including username and card type. | ### Example ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { seo: { defaultDescription: 'Comprehensive documentation for the docmd ecosystem.', aiBots: false, twitter: { siteUsername: '@docmd_io', cardType: 'summary_large_image' } } } }); ``` ## Features - **Smart Fallbacks**: Automatically extracts the first 150 characters of prose if no description is provided. - **AI Bot Governance**: Easily block or allow AI crawlers to differentiate between indexing and LLM training. - **Canonical Resolution**: Automatically generates `<link rel="canonical">` tags to prevent duplicate content issues. - **Rich Social Previews**: Native support for Open Graph and Twitter Cards for professional link sharing. - **Structured Data**: Supports LD+JSON Article Schema for rich search snippets. ## Page-Level Overrides Fine-tune settings for individual pages using frontmatter: ```markdown --- title: "Advanced Configuration" noindex: true # Hide from all search engines seo: keywords: ["docmd", "javascript", "ssg"] aiBots: true # Override global block for this page ldJson: true # Enable Article Schema --- ``` ::: callout tip "Search Discovery" For best results, ensure your `url` is defined in the root of your configuration. Without a base URL, the plugin cannot generate absolute canonical links or social image paths. ::: --- ## [Sitemap Plugin](https://docs.docmd.io/07/plugins/sitemap/) --- title: "Sitemap Plugin" description: "Automatically generate a standard-compliant sitemap.xml for better search engine discovery." --- The `@docmd/plugin-sitemap` plugin generates a `sitemap.xml` file at the root of your build directory. This provides search engines with a comprehensive map of your site's architecture, ensuring that all pages - including versioned documentation - are crawled and indexed. ## Configuration Enable sitemap generation by providing your `siteUrl` in the root configuration. You can customise the crawl weight within the `plugins` object. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable sitemap generation. | | `defaultChangefreq` | `string` | `'weekly'` | Hint to crawlers on how often pages change. | | `defaultPriority` | `number` | `0.8` | Default weight for standard pages (0.0 to 1.0). | | `rootPriority` | `number` | `1.0` | Weight for the homepage (`index.md`). | ### Example ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ url: 'https://docs.example.com', plugins: { sitemap: { defaultChangefreq: 'weekly', defaultPriority: 0.8 } } }); ``` ## Features - **Automatic URL Construction**: Intelligently resolves page paths to their canonical public URLs with clean directory structure. - **Versioned Discovery**: Automatically includes all pages from all versions (e.g. `/v1/`, `/v2/`) without manual configuration. - **Granular Exclusions**: Exclude specific pages from the sitemap using frontmatter. - **SEO Ready**: Follows standard XML sitemap protocols compatible with all major search engines. ## Page-Level Controls Override sitemap behaviour for specific pages using frontmatter: ```markdown --- title: "Archive Page" priority: 0.3 # Lower weight for legacy content changefreq: "monthly" # Hint to crawlers sitemap: false # Exclude this specific page --- ``` ::: callout tip "Validation" After building your site, you can find the sitemap at `site/sitemap.xml`. You can submit this URL directly to search engine consoles to accelerate indexing. ::: --- ## [Threads Plugin](https://docs.docmd.io/07/plugins/threads/) --- title: "Threads Plugin" description: "Add inline discussion threads to your documentation - stored directly in your markdown files." --- The **Threads plugin** brings collaborative inline comments to your documentation. Select any text on the page, leave a comment, start a discussion - all stored directly in your markdown source files with zero database needed. Original Author: [@svallory](external:https://github.com/svallory) ::: callout info "Alpha Release" This plugin is in alpha. The API and storage format are stable, but the UI is under active development. ::: ## Setup ```bash docmd add threads ``` ```javascript plugins: { threads: {} } ``` ### Configuration Options | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `sidebar` | `boolean` | `false` | When `true`, threads stay grouped at the bottom of the page. When `false` (default), threads are positioned inline next to their highlighted text. | ```javascript // Keep threads at bottom of page instead of inline plugins: { threads: { sidebar: true } } ``` ## How It Works 1. **Select text** on any documentation page during `docmd dev` 2. A **comment popover** appears - write your comment and submit 3. The selected text gets **highlighted** with a thread marker 4. Threads are stored as `::: threads` blocks at the bottom of the markdown file 5. **No database** - your markdown files are the source of truth ## Preview Here's what threads look like on a live page. Text with discussions gets <span class="threads-preview-highlight">highlighted like this</span> and thread cards appear below. <div class="threads-preview-card"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 2d ago</div> <div class="threads-preview-body">This section could use a diagram to explain the architecture. What do you think?</div> </div> <div class="threads-preview-comment threads-preview-reply"> <div class="threads-preview-avatar">B</div> <div class="threads-preview-meta"><strong>Bob</strong> · 1d ago</div> <div class="threads-preview-body">Good idea - I'll add a Mermaid flowchart. Does <code>sequenceDiagram</code> work here?</div> <div class="threads-preview-reactions"> <div class="threads-preview-reaction">👍 <span>2</span></div> <div class="threads-preview-reaction">🚀 <span>1</span></div> </div> </div> <div class="threads-preview-comment threads-preview-reply"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 12h ago</div> <div class="threads-preview-body">Perfect. A simple flowchart would be ideal.</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> And here's a <span class="threads-preview-highlight-blue">second highlight with a different colour</span> - threads cycle through a palette of colours automatically. <div class="threads-preview-card threads-preview-card-blue"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">C</div> <div class="threads-preview-meta"><strong>Charlie</strong> · 3d ago</div> <div class="threads-preview-body">Should we mention backward compatibility here?</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> Resolved threads appear dimmed: <div class="threads-preview-card threads-preview-card-resolved"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 5d ago  <span class="threads-preview-resolved-badge">✓ Resolved</span></div> <div class="threads-preview-body">Fixed the typo in the config example.</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> A floating **discussion button** <span class="threads-preview-fab">💬<span class="threads-preview-fab-badge">2</span></span> appears in the bottom-right corner showing the count of open threads. Click it to jump to the first thread on the page. ## Storage Format Threads are embedded in your markdown using docmd's container syntax: ```markdown # My Documentation Page Some content with ==highlighted text=={t-a1b2c3d4} that has a thread. ::: threads ::: thread t-a1b2c3d4 ::: comment c-e5f6a7b8 "Alice" "2026-04-09" This text needs clarification. ::: ::: comment c-d9e0f1a2 "Bob" "2026-04-09" reply-to c-e5f6a7b8 Updated it - does this work? ::: reactions - 👍 Alice ::: ::: ::: ::: ``` The `==text=={threadId}` syntax links highlighted text in the document body to a specific thread. ## Features | Feature | Description | | :--- | :--- | | **Text Selection** | Select any text to start a new thread | | **Replies** | Nested reply chains within each thread | | **Reactions** | Emoji reactions on individual comments | | **Edit / Delete** | Modify or remove your comments | | **Resolve** | Mark threads as resolved with author + timestamp | | **Author Profiles** | Git-based author detection with Gravatar support | | **Highlight Markers** | Visual indicators on the page showing where threads are anchored | | **Floating Button** | Quick-access FAB with open thread count | | **Scroll Preservation** | Page stays in place after adding comments | ## Actions API The threads plugin exposes the following actions via the WebSocket RPC system. These can be called from browser plugins using `docmd.call()`: | Action | Description | | :--- | :--- | | `threads:get-threads` | Parse and return all threads from a file | | `threads:add-thread` | Create a new thread with its first comment | | `threads:add-comment` | Add a comment to an existing thread | | `threads:edit-comment` | Edit an existing comment's body | | `threads:delete-comment` | Remove a comment from a thread | | `threads:delete-thread` | Remove an entire thread and cleanup highlights | | `threads:resolve-thread` | Toggle resolved/unresolved status | | `threads:toggle-reaction` | Toggle an emoji reaction on a comment | | `threads:get-authors` | Read the author profile map | | `threads:upsert-author` | Create or update an author profile | ## Author Profiles Author information is stored in `<docsRoot>/.threads/authors.json`: ```json { "alice@example.com": { "name": "Alice", "avatarUrl": "https://gravatar.com/avatar/..." } } ``` During development, the plugin automatically detects your git username and email for author identification. ::: callout tip "Version Control Friendly" Since threads are stored in your markdown files, they are automatically version-controlled with git. Review comments in PRs, track discussion history, and collaborate through your existing workflow. ::: --- ## [Using Plugins](https://docs.docmd.io/07/plugins/usage/) --- title: "Using Plugins" description: "Install, configure, and manage docmd plugins - from required defaults to optional add-ons." --- `docmd` features a modular plugin architecture. Required plugins ship with the core and need no installation. Optional plugins can be installed with a single CLI command. ## Installing Plugins Use the `docmd` CLI to install and remove plugins: ```bash # Install a plugin docmd add <plugin-name> # Remove a plugin docmd remove <plugin-name> ``` The installer automatically detects your package manager (npm, pnpm, yarn, or bun), resolves short names to full package names, and injects the plugin config into your `docmd.config.js`. Use `--verbose` (or `-V`) for full installer output: ```bash docmd add <plugin-name> -V ``` ## Required Plugins These plugins are bundled with `@docmd/core` - no installation needed. Enable them in your `docmd.config.js`: ```javascript import { defineConfig } from '@docmd/core'; export default defineConfig({ plugins: { search: {}, // Offline full-text search seo: { aiBots: false }, // Meta tags, Open Graph, AI bot controls sitemap: {}, // Automatic sitemap.xml generation analytics: {}, // Google Analytics v4 llms: {}, // LLM context generation (llms.txt) mermaid: {}, // Native interactive diagrams git: {} // Last updated timestamps and commit history } }); ``` ::: callout tip "Git Plugin" The Git plugin automatically detects if your project is in a Git repository. If not, it gracefully disables itself. No configuration is needed for basic last-updated timestamps - just ensure your docs are in a Git repo. ::: ## Optional Plugins Optional plugins require installation before enabling. | Plugin | Install Command | Description | | :--- | :--- | :--- | | [PWA](pwa.md) | `docmd add pwa` | Progressive Web App support with offline caching | | [Threads](threads.md) | `docmd add threads` | Inline discussion comments stored in your markdown | | [Math](math.md) | `docmd add math` | Native KaTeX and LaTeX mathematics integration | ## Auto-Installation When you add an official plugin to your `docmd.config.js` that isn't installed, docmd automatically downloads and installs it on the next build. This works for all plugins in the [official registry](/plugins/usage). ```javascript // docmd.config.js plugins: { pwa: {} // Not installed? docmd will auto-install it } ``` The auto-installer: - Only works for official `@docmd/plugin-*` packages - Installs the exact version matching your `@docmd/core` version - Uses your project's package manager (npm, pnpm, yarn, or bun) - Shows progress in the terminal ::: callout warning "Third-Party Plugins" Auto-installation only works for official plugins in the registry. Third-party plugins must be installed manually using your package manager. ::: ## Plugin Scopes and `noStyle` Overrides Plugins inject CSS and behaviour by default globally across all pages. However, you can explicitly configure them to bypass specific pages or entirely disable their execution on unstyled landing templates (`noStyle: true`). ### Global Config Extent You can instruct any plugin to automatically skip injecting into `noStyle` pages via your `docmd.config.js`: ```javascript plugins: { math: { noStyle: false // math css/js will no longer load on no-style pages } } ``` ### Page Local Scope (Frontmatter) Regardless of your global config (or what the plugin developer set by default), you can definitively enable or disable any plugin uniquely per-document via markdown frontmatter. ```markdown --- noStyle: true plugins: math: true threads: false --- # Only Math renders here, Threads are completely blocked ``` ## Plugin Lifecycle Plugins hook into different stages of the build and development process: | Hook | Description | | :--- | :--- | | `markdownSetup(md, opts)` | Extend the Markdown parser with custom rules or containers | | `generateMetaTags(config, page, root)` | Inject `<meta>` and `<link>` tags into the `<head>` | | `generateScripts(config, opts)` | Inject scripts into `<head>` or `</body>` | | `getAssets(opts)` | Define external files or CDN scripts to inject | | `onPostBuild(ctx)` | Run logic after all HTML files are generated | | `translations(localeId)` | Return translated UI strings for a locale | | `actions` | Server-side handlers callable from the browser via WebSocket RPC | | `events` | Fire-and-forget handlers for browser-pushed events | ## Plugin Safety The plugin system provides built-in safety guarantees: - **Validation**: Plugins can declare a `plugin` descriptor with `name`, `version`, and `capabilities`. Invalid descriptors are rejected at load time. - **Isolation**: Every hook invocation is wrapped in a try/catch boundary. A broken plugin cannot crash the build or affect other plugins. - **Capability Enforcement**: Plugins that declare capabilities can only register for hooks they've explicitly declared. Undeclared hooks are skipped with a warning. See [Building Plugins](building-plugins.md) for the full API reference. ::: callout tip "AI-Transparent Architecture :robot:" The plugin architecture is designed to be **deterministic**. Every meta-tag and script injected by a plugin is traceable, allowing AI agents (and human developers) to understand exactly how the site behaves without hidden side effects. ::: --- ## [Release Notes - 0.7.0](https://docs.docmd.io/07/release-notes/0-7-0/) --- title: "Release Notes - 0.7.0" description: "First-class internationalisation, zero-config core plugins, and true zero-config defaults." --- The `docmd` 0.7.0 release is a major step forward - introducing native multi-language support (i18n) with a built-in translation system and true zero-config defaults where all core plugins are active out-of-the-box. ## ✨ Highlights ### 🌍 Internationalisation (i18n) docmd now has first-class i18n support. Configure multiple locales and docmd builds a complete, localised version of your site for every locale - with locale-first URLs (`/hi/`, `/zh/`), translated UI strings, and automatic language detection. Every locale lives in its own subdirectory - including the default language. This keeps your source directory clean and makes the structure easy to understand at a glance: ``` docs/ en/ ← default locale (renders at /) hi/ ← Hindi (renders at /hi/) zh/ ← Chinese (renders at /zh/) ``` The locale IDs, folder names, and default language are entirely your choice - `en`, `hi`, `fr`, `de`, or any identifier you prefer. ```js // docmd.config.js export default { i18n: { default: 'en', locales: [ { id: 'en', label: 'English' }, { id: 'hi', label: 'हिन्दी' }, { id: 'zh', label: '中文' }, ] } } ``` This includes **Per-Locale Search Indexes** spanning across your versions automatically, along with translated UI components for official plugins like Search and Threads! ### 🚀 Zero-Config Core Plugins In `0.7.0`, docmd embraces a true zero-config philosophy. All official core plugins (`search`, `seo`, `sitemap`, `pwa`, `analytics`, `llms`, `mermaid`) are now **auto-included by default**. You no longer need to declare them manually in your `plugins` array to use them. If you want to disable a core plugin, you can now simply mark it as `false`: ```js export default { plugins: { search: false // Disables the automatically included search plugin } } ``` ## 📝 Complete Changelog ### 🌍 i18n Architecture - **Clean locale directories**: Every locale (including the default) lives in its own subdirectory inside `src`. No more mixing locale folders alongside content folders. - **Locale-first URL generation**: Build loop now builds nested directories for each configured locale. - **Per-file fallback**: Non-default locales inherit pages from the default locale when a translation is missing, with an automatic warning callout. - **Per-locale navigation**: Each locale directory can have its own `navigation.json`, falling back to the default locale's navigation when absent. - **Versioning + i18n**: Old versions without locale directories are rendered in the default locale only. Add a locale subdirectory to any old version to enable translations for it. - **Translated UI strings**: Native translation system across all UI elements and templates. Handlers resolved against JSON locale files (`en.json`, `hi.json`, `zh.json`) - all template strings accessible via a fast `t('key')` helper. - **Plugin i18n API**: Plugins now support a new `translations(localeId)` hook alongside an `i18n/` directory convention for client-side strings. - **Global Search Locales**: The local MiniSearch index is now built per-locale, dynamically rendering version badges based on context, and gracefully providing localised search results. - **Zero-footprint fallback**: Sites with no `i18n` block build identically to pre-0.7.0 - no path or output changes overhead. - **String Mode (`stringMode: true`)**: A new i18n mode for noStyle pages - generate locale-specific HTML from a single source file. Add `data-i18n` attributes to your HTML, place translation files in `assets/i18n/{locale}.json`, and docmd clones the rendered output with **server-side string replacement** at build time. Produces fully translated, SEO-indexable pages at `/{locale}/` paths. Supports `data-i18n` (textContent), `data-i18n-html` (innerHTML), and `data-i18n-{attr}` (attribute values). Missing translation files gracefully fall back to the default language. Designed for noStyle/HTML pages only - markdown documentation should use directory mode. - **Client-side i18n for noStyle pages**: A lightweight `docmd-i18n-strings.js` module is auto-injected when i18n is configured. Provides a runtime `switchLocale()` API, `inPlace` mode for SPAs, and a `docmd:i18n-applied` event for custom language switchers. ### 🔌 Plugin System & Engine - **Core plugins auto-activation**: Zero-config defaults automatically provide the complete docmd suite without config overhead. - **Asset generation optimisations**: Restructured asset pipeline so that static CSS, JS, and global configurations are built exactly once to the root, regardless of how many locales or versions are active. ### 🎨 UI & Containers - **Container `icon:` parameter**: Callouts, cards, collapsible sections, and buttons now accept an `icon:` parameter to render a Lucide icon inline with the title. Icons are vertically centred and properly sized using flexbox alignment. ```md ::: card "Setup" icon:rocket ::: button "Get Started" /start icon:arrow-right ``` - **`titleAppend` frontmatter option**: Pages can now set `titleAppend: false` in frontmatter to suppress the automatic ` - Site Title` suffix in the `<title>` tag. Useful for homepages and landing pages. - **Pill-style version & language switchers**: The version dropdown and language switcher in the sidebar now render as compact pill buttons that sit side-by-side on the same line, saving vertical space. Shared CSS classes ensure consistent sizing across both components. - **Language switcher version awareness**: When browsing an old version that has no translations, non-default locales are visually disabled in the language switcher with an "N/A" badge, preventing broken navigation to non-existent pages. - **Translatable "(Latest)" badge**: The current version now displays an auto-generated, translatable "Latest" badge in the version dropdown. No longer hardcoded in the config label - uses the built-in translation system. - **Search result version badges**: Search results now display version badges as colour-coded pills aligned to the right of the result title. Each version gets a deterministic colour generated at build time for easy visual identification. - **Responsive language pill**: When both version and language pills are present, the language label auto-hides on standard sidebars and only shows the globe icon, expanding to show the label on wider screens. - **Dev server config hot-reload**: Changes to `docmd.config.js` now trigger a full rebuild during `docmd dev` without requiring a manual restart. File watcher correctly detects config file changes on all platforms. ## 🐛 Bug Fixes - **Versioning + i18n conflict**: Old version directories without locale subdirectories were being duplicated across all locales. Now correctly rendered for the default locale only - non-default locales skip versions that have no translations. - **Ghost locale pages in old versions**: Locale subdirectories inside old version directories (e.g. `docs-v1/hi/`) were rendered as regular content pages during the default locale pass, producing duplicate URLs. Fixed by filtering known locale directory names during the scan. - **Navigation warning false positive**: The "No navigation settings found" message was shown even when `navigation.json` existed inside locale or version directories. Now silent when navigation is available in any locale or version directory. - **Auto-nav scanning wrong directory**: When i18n is enabled, the auto-navigation builder was scanning the source root (which only contains locale directories), generating incorrect navigation from folder names. Now scans the default locale's directory instead. - **`<title>` tag missing site name**: Pages without an explicit title produced empty title tags. The template now auto-appends the site title with an em-dash separator (`Page - Site`), and the homepage shows just the site title. - **Language switcher URL duplication on old versions**: Switching language while browsing a non-current version produced URLs with the version prefix duplicated (e.g. `/zh/06/06/page`). Fixed by stripping the version prefix from the page path before rebuilding the locale URL. ## 🧪 Quality Assurance The 0.7.0 release passes a comprehensive brute test suite covering **25 distinct scenarios** with **85 individual assertions** - all green. Every major feature is tested both in isolation and in combination: ::: collapsible "View full test coverage" | # | Scenario | Assertions | |:--|:---------|:-----------| | 1 | Zero-config (no config file) | 5 | | 2 | Zero-config with nested directories | 4 | | 3 | i18n standalone (non-English default) | 5 | | 4 | Versioning standalone (no i18n) | 5 | | 5 | i18n + versioning combined | 6 | | 6 | Old version with partial translations | 4 | | 7 | Missing locale dir (graceful skip) | 3 | | 8 | Navigation resolution priority | 2 | | 9 | Frontmatter parsing | 3 | | 10 | Containers (callout, tabs, steps, hero) | 5 | | 11 | Code blocks (JS, Python) | 3 | | 12 | Custom CSS/JS injection | 3 | | 13 | Edit links | 3 | | 14 | No-style pages | 3 | | 15 | Search index generation | 3 | | 16 | Sitemap generation | 3 | | 17 | EJS content pages | 3 | | 18 | README.md as index fallback | 4 | | 19 | `.markdown` file extension | 3 | | 20 | Deep nested structure (4+ levels) | 2 | | 21 | Zero-config auto-nav accuracy | 3 | | 22 | Title tag auto-append | 2 | | 23 | Open Graph meta tags | 3 | | 24 | Redirects | 3 | | 25 | Per-page layout override | 3 | All 13 internal failsafe checks also pass. The brute test script is included in `scripts/brute-test.js` for anyone to run locally. ::: ## ⚠️ Breaking Changes - **Third-party plugin shorthand names are no longer resolved** - you must use the full package name if you are importing third-party plugins. (`search`, `threads`, etc., are reserved strictly for `@docmd/plugin-*`). - **`pnpm onboard` removed** - the `onboard` script has been merged into `pnpm prep`. Use `pnpm prep` for full environment setup and `pnpm prep --link` (or `pnpm verify --link`) to also link `docmd` globally. - **PWA Plugin is now an optional plugin and no longer auto-included**, if you want to add PWA to your docs, use `docmd add pwa` command. ## Migration Guide Upgrade by running `npm install docmd@latest`. Then: 1. **You may remove** core plugins from your `plugins` array if you were using them with default settings - they are now automatically enabled! 2. If you use third-party plugins by shorthand, update them to their full package name. See [Getting Started - Installation](../getting-started/installation) for a full walkthrough. --- ## [Release Notes - 0.7.1](https://docs.docmd.io/07/release-notes/0-7-1/) --- title: "Release Notes - 0.7.1" description: "Dedicated Plugin API package, plugin descriptors, isolation, and capability enforcement." --- The `docmd` 0.7.1 release introduces a major architectural improvement - the plugin system has been extracted into a dedicated `@docmd/api` package, bringing plugin descriptors, crash isolation, and capability enforcement to the ecosystem. ## ✨ Highlights ### 📦 `@docmd/api` - Dedicated Plugin Package The plugin API surface - hook registration, WebSocket RPC dispatch, and source editing tools - now lives in its own dedicated package: `@docmd/api`. ```bash npm install @docmd/api ``` This decouples the plugin ecosystem from the build engine, allowing plugin authors to depend on a lightweight API contract without pulling in the entire `@docmd/core` package. > **Backward Compatible:** All exports from `@docmd/api` are re-exported from `@docmd/core`. Existing code using `@docmd/core` imports continues to work without changes. ### 🛡️ Plugin Descriptors Plugins can now export a `plugin` descriptor declaring their identity and capabilities: ```javascript export default { plugin: { name: 'my-analytics', version: '1.0.0', capabilities: ['head', 'body', 'post-build'] }, generateScripts: (config, opts) => { ... }, onPostBuild: async (ctx) => { ... } }; ``` The engine validates descriptors at load time - invalid names, versions, or unknown capabilities are rejected immediately for official plugins, and emit warnings for third-party packages. > **Migration Note:** Descriptors are **optional** in 0.7.x. A soft deprecation warning is emitted for plugins without one. This will become a **hard requirement in 0.8.0**. ### 🔒 Plugin Isolation Every hook invocation is now wrapped in a try/catch boundary. A broken plugin cannot crash the build or interfere with other plugins. Errors are logged and collected into a summary displayed at the end of the build: ``` ⚠️ 2 plugin error(s) occurred (build completed) ``` ### 🔑 Capability Enforcement Plugins that declare capabilities can only register for hooks matching those declarations. If a plugin exports a hook it didn't declare, the engine skips it with a warning: ``` Plugin "analytics" exports markdownSetup but didn't declare "markdown" capability - skipped ``` | Capability | Allowed Hooks | Phase | | :--- | :--- | :--- | | `init` | `onConfigResolved` | Init | | `markdown` | `markdownSetup` | Setup | | `head` | `generateMetaTags`, `generateScripts` (head) | Render | | `body` | `generateScripts` (body) | Render | | `build` | `onBeforeParse`, `onAfterParse`, `onPageReady` | Build | | `post-build`| `onPostBuild` | Post-Build | | `dev` | `onDevServerReady` | Dev Server | | `assets` | `getAssets` | Output | | `actions` | `actions` | Interactive | | `events` | `events` | Interactive | | `translations`| `translations` | i18n | Legacy plugins without a descriptor continue to have full access to all hooks. ## 📝 Complete Changelog ### 📦 Architecture - **`@docmd/api` package**: Extracted `loadPlugins`, `createActionDispatcher`, `createSourceTools`, and all plugin/RPC types into `packages/api/`. - **`@docmd/core` re-exports**: All moved API symbols are re-exported from `@docmd/core/src/index.ts` for seamless backward compatibility. - **Dead code removal**: Deleted the original `plugin-loader.ts`, `action-dispatcher.ts`, `source-tools.ts`, and `types.ts` from `@docmd/core` after migration. ### 🔌 Plugin System - **Plugin Descriptor** (`plugin` export): Name, version, and capability declaration. - **Validation (§1)**: Strict enforcement for `@docmd/plugin-*` packages; soft warnings for third-party plugins. - **Isolation (§2)**: `safeCall()` wrappers around all synchronous hooks; async try/catch for `onPostBuild`. - **Capability Enforcement (§3)**: Hook registration gated by declared capabilities. - **Expanded Lifecycle Hooks (§4)**: Introduced `onConfigResolved`, `onDevServerReady`, `onBeforeParse`, `onAfterParse`, and `onPageReady` to handle complex site integration. - **Error Summary**: Plugin errors are collected and displayed as a count at the end of the build, without halting the process. ### 🐛 Bug Fixes - **404 page raw key display**: Fixed an issue where the 404 page could display `errorCode404` as literal text when translations failed to load. The error code is now hardcoded as `404`. - **i18n `stringMode` script leak**: Fixed `no-style.ejs` injecting the `docmd-i18n-strings.js` runtime when `stringMode` is active. The client-side locale runtime is now correctly suppressed in string mode. - **Plugin resolution in pnpm workspaces**: Fixed `loadPlugins` failing to locate `@docmd/plugin-*` packages when called from `@docmd/api` - the function now accepts `resolvePaths` from the caller to support pnpm's strict `node_modules` layout. ## ⚠️ Breaking Changes ### Plugin API Import Path (Recommended Migration) The canonical home for the plugin API is now `@docmd/api`. While `@docmd/core` re-exports everything for backward compatibility, **plugin authors are encouraged to update their imports**: ```diff -import { createActionDispatcher, createSourceTools } from '@docmd/core'; +import { createActionDispatcher, createSourceTools } from '@docmd/api'; ``` ```diff -import type { PluginModule, ActionContext, SourceTools } from '@docmd/core'; +import type { PluginModule, ActionContext, SourceTools, PluginDescriptor, Capability } from '@docmd/api'; ``` > **No action required for end users.** This only affects plugin developers who directly import API utilities. The `@docmd/core` re-exports will remain available indefinitely. ### Threads Plugin Peer Dependency The `@docmd/plugin-threads` package now peer-depends on `@docmd/api` instead of `@docmd/core`. If you install Threads manually (rather than via `docmd add threads`), ensure `@docmd/api` is available in your dependency tree. ## Migration Guide For **end users**: No changes required. `npm install docmd@latest` is sufficient. For **plugin authors**: 1. **Add a plugin descriptor** to your default export (optional now, required in 0.8.0): ```javascript export default { plugin: { name: 'my-plugin', version: '1.0.0', capabilities: ['head', 'post-build'] }, // ... hooks }; ``` 2. **Update imports** from `@docmd/core` to `@docmd/api` for `createActionDispatcher`, `createSourceTools`, `loadPlugins`, and all type exports. 3. **Update peer dependencies** from `@docmd/core` to `@docmd/api` in your `package.json` if your plugin uses the RPC or source editing APIs. See [Building Plugins](../../plugins/building-plugins) for the full updated API reference. --- ## [Release Notes - 0.7.2](https://docs.docmd.io/07/release-notes/0-7-2/) --- title: "Release Notes - 0.7.2" description: "Introducing config-aware 'docmd deploy', production security headers, and the 7-pillar failsafe verification engine." --- The `docmd` 0.7.2 release introduces the **`docmd deploy`** command : a config-aware deployment scaffolder that reads your project and generates production-ready server configurations tailored to it. No other documentation tool does this. Docusaurus, VitePress, MkDocs - they all leave you to write your own Dockerfiles and server configs from scratch. `docmd` reads your `docmd.config.js` (or its zero-config defaults) and generates files that are ready to ship. ## ✨ `docmd deploy` : Config-Aware Deployment Run a single command and get production-ready deployment files personalised to your project: ```bash docmd deploy --docker # Dockerfile + .dockerignore docmd deploy --nginx # nginx.conf docmd deploy --caddy # Caddyfile ``` ### What Makes It Smart The deploy command **reads your configuration** before generating anything. It extracts: - **Project title** - stamped into every generated file as a header comment - **Output directory** (`out`) - used in `COPY` paths, `root` directives, and file server configs instead of hardcoded values - **Site URL** (`url`) - extracted hostname is injected as `server_name` (Nginx) or the Caddy site address - **SPA mode** (`layout.spa`) - only generates `try_files` SPA fallback routing when SPA mode is active - **Config file path** - if you use a non-default config name, the Dockerfile build step runs `docmd build --config your-config.js` If no `docmd.config.js` exists, the command still works - it falls back to the same zero-config defaults that `docmd dev` and `docmd build` use. ### Always In Sync Every run regenerates the deployment files to match your current configuration. Changed your `url` or `out` directory? Just run `docmd deploy --nginx` again. No `--force` flag needed for updates - your configs always reflect the latest state of your project. ### Generated File Quality - **Docker**: Multi-stage builds with `package.json` layer caching and exact `@docmd/core` version pinning for reproducible builds - **Nginx**: Security headers (`X-Content-Type-Options`, `X-Frame-Options`), GZIP compression, immutable asset caching - **Caddy**: Automatic HTTPS-ready addressing, security headers, SPA routing, static asset caching ## 🛡️ The 7-Pillar Failsafe Our internal verification engine has been refactored into **7 logical pillars of stability**. This includes a new **Dynamic Integrity Engine** that catches version mismatch regressions instantly across the entire monorepo. ## 🌍 Global Ecosystem Expansion Major localisation updates in this release: - **Native Language Support**: Built-in UI translations for **German, Spanish, Japanese, and French** added to the core engine - these locales work out-of-the-box for all UI components. - **Full German Translation**: The entire documentation suite is now available in German (`/de/`). ## 📝 Complete Changelog ### 🚀 Features & Enhancements - **New Command**: `docmd deploy` with `--docker`, `--nginx`, `--caddy` targets. - **Config-Aware Scaffolding**: Deploy command reads `docmd.config.js` (or zero-config defaults) and personalises generated files with project title, output directory, hostname, SPA mode, and config path. - **Always Fresh Configs**: Deployment files regenerate on every run to stay in sync with config changes. - **Docker Scaffolding**: Multi-stage Dockerfile with `package.json` layer caching and version-pinned `@docmd/core`. - **Web Server Scaffolding**: Hardened Nginx and Caddy templates with security headers, GZIP, and intelligent 404/SPA routing. - **Unified Config Labels**: All internal modules (SEO, sitemap, LLMS, PWA, deployer, generator) now use the modern config keys (`config.title`, `config.url`, `config.out`, `config.src`) instead of scattered legacy fallbacks. Defaults are defined once in `normalizeConfig` - the single source of truth. - **Failsafe**: Consolidated verification logic into a faster, more professional 7-stage pipeline. - **Versioning**: New integrity engine automatically flags outdated internal workspace references. - **SEO Plugin**: Fully respects the `titleAppend` frontmatter property for social media (OG/Twitter) metadata. - **Native Support**: Added built-in UI translations for **German, Spanish, Japanese, and French** to the core engine. - **Localisation**: Added comprehensive **German** translation and optimised **Chinese** translation for the documentation site. ### 🐛 Bug Fixes - **Deploy CLI**: Fixed argument parsing when running through `pnpm` proxy scripts with `--cwd`. - **Deploy UX**: Unknown arguments now show a helpful usage summary instead of a raw error with exit code 1. - **Caddy Config**: Corrected Cache-Control header syntax (quoted values) for Caddyfile compatibility. - **Bump Script**: Fixed a regex `lastIndex` bug in `scripts/bump.js` that caused inconsistent version replacements. - **CLI Safety**: Added proper async error handling to all deployment command entry points. - **Live Editor**: Fixed mobile overflow issues and template switching state tracking. ## Migration Guide For **end users**: No breaking changes. Update and try `docmd deploy` to generate deployment configs tailored to your project. For **plugin authors**: No changes required. --- ## [Release Notes - 0.7.3](https://docs.docmd.io/07/release-notes/0-7-3/) --- title: "Release Notes - 0.7.3" description: "Introducing code block titles, the multi-service migration engine, interactive Mermaid diagrams with Lucide icons, and first-class Bun ecosystem support." --- The `docmd` 0.7.3 release delivers significant new authoring capabilities, a production-grade migration engine for users switching from competing platforms, and a complete overhaul of the Mermaid diagram rendering pipeline. We have also unified the icon rendering logic across all interactive containers and introduced deeply contextual pagination logic. ## ✨ Highlights ### 🚀 Multi-Service Migration Engine We have replaced the legacy internal config migration tool with a full-featured **migration engine** that can move your entire documentation project from a competing platform to `docmd` in a single command. ### Supported Sources | Source | Command | Config Detected | |---|---|---| | **Docusaurus** | `npx @docmd/core migrate --docusaurus` | `docusaurus.config.js` / `.ts` | | **MkDocs** | `npx @docmd/core migrate --mkdocs` | `mkdocs.yml` | | **VitePress** | `npx @docmd/core migrate --vitepress` | `.vitepress/config.[js\|ts\|mjs]` | | **Astro Starlight** | `npx @docmd/core migrate --starlight` | `astro.config.mjs` / `.ts` | Each migration will: 1. Detect the source project's configuration file and extract the site title. 2. Safely move all existing files into a `<source>-backup/` directory. 3. Copy the documentation source files (`docs/`, `src/content/docs/`, etc.) into `docmd`'s standard `docs/` structure. 4. Generate a ready-to-use `docmd.config.js` with sensible defaults. ```bash cd my-docusaurus-site npx @docmd/core migrate --docusaurus npx @docmd/core dev ``` > **Note:** Because every documentation platform handles complex logic like sidebars, versioning, and internationalization (i18n) via proprietary code or APIs, `docmd` does not attempt to auto-translate these configurations to avoid breaking your build. The migration engine focuses purely on safely moving your Markdown content and assets, while leaving the setup of `navigation.json` and `localisation` to you via `docmd`'s simple native APIs. Read our new comprehensive [Migration Guides](/migration/overview) to see exactly what gets migrated and the easy steps required to map your previous tool's configuration to `docmd`. ### 📝 Code Block Titles You can now add a descriptive **filename or title** to any fenced code block by placing a quoted string after the language identifier. This renders a clean, Mintlify-style header bar above the code. ````markdown ```javascript "config.js" export default { title: "My Site" }; ``` ```` The title is rendered as a semantic label (not a heading), so it will never appear in the Table of Contents or interfere with your page structure. ### 📊 Interactive Mermaid Diagrams We have completely overhauled how `docmd` renders Mermaid diagrams, turning static SVGs into deeply interactive visual elements. - **Smart Scaling**: Diagrams are rendered at full Mermaid quality and then intelligently scaled to fit the content width using CSS transforms, preserving all label and edge positioning. - **Pan & Drag**: Click and drag to pan across large diagrams. - **Zoom Controls**: Dedicated zoom in/out buttons appear on hover for precise inspection. - **Fullscreen Mode**: A native fullscreen toggle allows users to expand complex charts for distraction-free viewing. - **Lucide Icon Integration**: The Lucide icon pack is registered directly into the Mermaid engine (`icon:icon-name`), enabling rich architecture diagrams with the same icons used in your sidebar and tabs. - **Dark Mode**: Diagrams and their containers now render correctly in dark mode with properly themed borders and backgrounds. ### ✨ Isomorphic Container Icons We have refactored the core parser to use a shared **Container Integrity Engine**. This ensures that all interactive elements - Callouts, Cards, Collapsibles, and now **Tabs** - support a unified `icon:name` syntax. ### Icons in Tabs You can now add any Lucide icon directly to your tab labels, providing immediate visual context to your users. This is particularly useful for differentiating between package managers, operating systems, or programming languages. ```markdown ::: tabs == tab "npm" icon:box npx @docmd/core dev == tab "Bun" icon:zap bunx docmd dev ::: ``` All icons are rendered as optimised inline SVGs, maintaining `docmd`'s commitment to zero-layout-shift and sub-100ms navigation performance. ### ⚡ First-Class Bun Support Following the rapid adoption of the Bun runtime, we have updated all core documentation and "Getting Started" guides to include native Bun examples. - **`bunx` support**: All one-off commands now include `bunx` alternatives alongside `npx`. - **Dependency management**: Installation guides now cover `bun add` workflows for project-level integration. - **Documentation Parity**: English, Chinese, and German guides have been synchronised to ensure a consistent experience regardless of your preferred runtime or language. ### 🧭 Contextual Pagination Navigation The Next and Previous page pagination links at the bottom of articles have received a major intelligence upgrade. Previously, these links defaulted to generating URLs for the primary locale and latest version, which disrupted the user experience when browsing translated docs or archived versions. The Core Engine now natively understands the `outputPrefix` context, ensuring that your readers stay perfectly within their current language and version silo as they navigate sequentially through your documentation. ### 🎨 Visual Refinements - **Softer Code Blocks**: All code blocks now feature softer `border-radius` corners and subtle box shadows for a more premium aesthetic. - **Dark Mode Code Borders**: Added a dedicated `--border-colour-codeblock` variable for dark mode, fixing invisible borders on code blocks and diagram containers. - **Mermaid Container Chrome**: Diagrams are now wrapped in a bordered, padded container with consistent styling across light and dark themes. ### 🛠️ Internal Refactoring This release includes a significant architectural cleanup of the `docmd/parser` package: - **Refactored Utility Layer**: Moved `parseTitleAndIcon` into a central `container-helper` utility. This eliminates logic duplication between the `tabs` and `common-containers` modules. - **Custom Fence Renderer**: Code block titles are implemented via a markdown-it fence renderer override, ensuring titles are never misinterpreted as content headings. - **Performance Optimisation**: The shared helper uses optimised regex patterns to reduce the overhead of parsing large documents with many interactive containers. ## 📝 Complete Changelog ### 🚀 Features & Enhancements - **Migration Engine**: New `docmd migrate` command supporting Docusaurus, MkDocs, VitePress, and Astro Starlight. - **Code Block Titles**: Added `language "title"` syntax for filename headers on fenced code blocks. - **Tabs Icons**: Added support for `icon:name` syntax in the `== tab` sub-delimiter. - **Shared Parser Logic**: Created a unified `container-helper` utility for parsing titles and icons across all containers. - **Mermaid Interactive Controls**: Diagrams now feature native pan, zoom, and fullscreen capabilities with smart transform-based scaling. - **Mermaid Icons**: Registered the Lucide icon pack within the Mermaid rendering engine. - **Context-Aware Pagination**: Next/Previous links now automatically respect the active locale and version silos. - **Bun Ecosystem**: Comprehensive update to all Getting Started and Installation guides to include Bun/bunx examples. - **Dark Mode Code Borders**: Added `--border-colour-codeblock` dark mode variable for proper border visibility. - **Visual Consistency**: Standardised icon sizes and alignment within tab navigation bars. ### 🐛 Bug Fixes - **Navigation Sync**: Fixed an inconsistency in the Chinese (`zh`) navigation where a legacy "Recipes" section was incorrectly visible. - **Code Block Title Rendering**: Fixed a critical bug where titles after the language identifier were being parsed as markdown headings instead of being captured as code block labels. - **Mermaid Scroll Hijacking**: Fixed an issue where mouse wheel scrolling was blocked when hovering over Mermaid diagrams. - **Mermaid Dark Mode**: Fixed invisible diagram container borders in dark mode. - **Parser Robustness**: Fixed an edge case where nested containers within tabs could occasionally fail to render if they contained specific Markdown-it fence markers. - **Locale Consistency**: Corrected several technical translation inaccuracies in the German `content-ux` guides. ## Migration Guide For **end users**: No changes required. `npm update @docmd/core` is sufficient. For **plugin authors**: If you were manually parsing tab headers, we recommend switching to the exported `parseTitleAndIcon` utility from `@docmd/parser` to maintain compatibility with future icon enhancements. For **users of other documentation platforms**: Run `npx @docmd/core migrate --help` to see all available migration sources and get started in seconds. --- ## [Release Notes - 0.7.4](https://docs.docmd.io/07/release-notes/0-7-4/) --- title: "Release Notes - 0.7.4" description: "Introducing context-aware version filtering for offline search, plus Mermaid icon rendering standardisation." --- The `docmd` 0.7.4 release introduces a powerful new feature to our offline search plugin: **Context-Aware Version Filtering**. It also includes a hotfix for Mermaid icon rendering and syntax standardisation. ## ✨ Highlights ### 🔍 Version Filtering in Search When building documentation with multiple versions, finding the right information can be challenging. The built-in search modal now natively understands version silos and automatically generates a dynamic filter bar. - **Smart Version Detection**: The search engine automatically extracts all available versions from your index and generates clickable filter tags. - **Colour-Coded Tags**: Each version tag is automatically assigned a unique, aesthetically pleasing colour from a predefined palette to help users visually distinguish between different documentation silos. - **Real-Time Toggling**: Users can click tags to instantly narrow down their search results to one or multiple specific versions, providing a much cleaner and more accurate search experience. ### 🏷️ Inline Tags Container We've introduced a brand new `tag` container! This is a self-closing, inline component designed for inserting pill-shaped badges directly into your text or headings. - **Fully Customisable**: Override default colours with any CSS colour string (`color:#ef4444`). - **Icon Support**: Attach any Lucide icon (`icon:check-circle`) directly to the tag. - **Hyperlinks**: Easily turn tags into links using the `link:` attribute. - **Heading-Safe**: Tags automatically align to the baseline without inheriting massive font sizes when used inside `<h1>` or `<h2>` elements. ## 🐛 Bug Fixes - **Mermaid Icon Registration**: Fixed an issue where the Lucide icon pack was not properly decoupled from the user-facing syntax in Mermaid flowcharts. - **Architecture Syntax Support**: We have officially migrated our documented Mermaid icon support to use Mermaid's native `architecture` and `architecture-beta` diagram types, which support inline Iconify nodes perfectly. ## 🛡️ Security - **Dependency Audit**: Addressed multiple security advisories by forcefully upgrading deeply nested sub-dependencies across the monorepo (`cross-spawn`, `dompurify`, `lodash-es`, `uuid`, and `mermaid`). The entire engine ecosystem is now 100% clean and vulnerability-free. ## ✨ Standardised Icon Syntax To abstract the underlying icon library (currently Lucide) from your diagrams, we have registered the pack generically as `icon`. This means that instead of explicitly tying your documentation to `lucide:`, you should now use `icon:`. This future-proofs your diagrams - if we ever expand or change the underlying icon library in `docmd`, your diagrams will automatically inherit the updates without any changes required on your end! **Example:** ```mermaid architecture-beta group api(icon:cloud)[API] service db(icon:database)[Database] in api service disk(icon:hard-drive)[Storage] in api db:L -- R:disk ``` ## Migration Guide For **end users**: Update to the latest patch with `npm update @docmd/core`. If you previously used `lucide:` in your Mermaid diagrams, please replace it with the new `icon:` prefix. --- ## [Release Notes - 0.7.5](https://docs.docmd.io/07/release-notes/0-7-5/) --- title: "Release Notes - 0.7.5" description: "Security patch and i18n optimisation: eliminates uuid vulnerability, adds language switcher failsafes, and introduces build-time page manifests for zero-latency locale switching." --- The `docmd` 0.7.5 release combines a security fix with significant i18n optimisations. It eliminates the upstream `uuid` vulnerability from the Mermaid plugin, adds multi-layer failsafes to the language switcher, and introduces a **build-time page manifest** that replaces all runtime network checks with instant local lookups. ## 🛡️ Security ### Mermaid Plugin - Dependency Tree Fix The `@docmd/plugin-mermaid` package previously declared `mermaid` as a production `dependency`. This caused the vulnerable transitive sub-dependency `uuid@<14.0.0` to be installed in every consumer's `node_modules`, even though the package never uses it at runtime. **Root Cause**: The mermaid library is loaded exclusively from a CDN at runtime in the browser. The npm `mermaid` package was only needed during development for TypeScript type-checking and the esbuild bundling step. It was incorrectly categorised as a production dependency. **Fix**: `mermaid` has been moved from `dependencies` to `devDependencies` in `@docmd/plugin-mermaid`. The published package now ships with **zero production dependencies**, so `mermaid` and its vulnerable `uuid` sub-dependency are never installed for end users. - `npm audit` / `pnpm audit` now reports **0 vulnerabilities** for projects using `@docmd/plugin-mermaid`. - No functional changes - the mermaid rendering pipeline is completely unaffected. ## 🌐 i18n - Language Switcher Failsafe Previously, if a locale was declared in `i18n.locales` but its source directory (e.g. `docs/hi/`) did not exist, the language switcher would still render it as clickable - leading to a **404** when selected. **Fix**: The engine now **pre-scans locale directories** at build time. Locales without a source directory are automatically disabled in the language switcher with an **N/A** badge, `aria-disabled` attribute, and non-clickable state. - **Build-time detection**: The engine checks which locale directories actually exist before any pages are rendered. - **Template-level disabling**: Unavailable locales appear greyed out with an "N/A" badge and `href="#"`. - **Client-side guard**: Clicking a disabled locale is a no-op - no navigation, no 404. - **Chained fallback**: If a locale is available but a specific page is missing, the engine falls back to the default locale's version of that page with a localised warning callout. ## ⚡ i18n - Build-Time Page Manifest Previously, the language switcher used `fetch(url, { method: 'HEAD' })` to verify whether a page existed in the target locale before navigating. This added latency, broke on some CDNs, and didn't work offline. **Fix**: The engine now generates a **page manifest** at build time - a tiny JS file (`docmd-i18n-manifest.js`) that maps every locale to its available page paths. The client-side switcher reads this manifest synchronously. - **Zero network requests**: Page existence is checked locally from the manifest - no HEAD fetches. - **Works offline**: The manifest is bundled with the site assets. - **CDN-agnostic**: No dependency on how the hosting provider handles HEAD requests. - **Graceful degradation**: If the manifest fails to load, the switcher falls back to HEAD fetches automatically. ::: callout info When i18n is enabled, each locale **must** have its own subdirectory under the source directory (e.g. `docs/en/`, `docs/hi/`). The default locale's directory is required as the fallback source for partially translated locales. ::: ## i18n Failsafe - How docmd Compares | Capability | docmd | VitePress | Docusaurus | Starlight | |:-----------|:-----:|:---------:|:----------:|:---------:| | Per-page fallback to default locale | ✅ | ❌ (404) | ❌ (404) | ✅ | | Localised "not translated" warning | ✅ | ❌ | ❌ | ✅ | | Auto-disable missing locales in switcher | ✅ | ❌ | ❌ | ❌ | | Client-side navigation guard | ✅ | ❌ | ❌ | ❌ | | Versioning + i18n combined | ✅ | ❌ | ❌ | ❌ | | Old version backward compat (no locale dirs) | ✅ | N/A | N/A | N/A | | RTL direction support | ✅ | ✅ | ✅ | ✅ | | Zero-config (no custom React/Vue) | ✅ | Partial | ❌ | ✅ | VitePress and Docusaurus both return **404 errors** when a page is missing in a non-default locale - requiring manual server-side redirects or custom components to handle gracefully. Starlight (Astro) provides per-page fallback with a translation notice, similar to docmd - but does not auto-disable missing locale directories or guard against client-side navigation to non-existent locales. ## Migration Guide For **end users**: Update to the latest patch with `npm update @docmd/plugin-mermaid` or `pnpm update @docmd/plugin-mermaid`. No configuration changes are required. --- ## [Release Notes - 0.7.6](https://docs.docmd.io/07/release-notes/0-7-6/) --- title: "Release Notes - 0.7.6" description: "Unified URL normalisation engine, universal external: and raw: link prefixes, SEO trailing-slash enforcement, SPA hash navigation fix, and silent plugin warnings in dev mode." --- The `docmd` 0.7.6 release introduces a **unified URL normalisation engine** that eliminates 301 redirects, enforces trailing-slash URLs for SEO, and brings consistent link handling across every surface. ## ✨ Highlights ### Unified URL Normalisation All URL handling now routes through a single `resolveHref()` function in `@docmd/parser`. Trailing-slash enforcement, `index.md` stripping, and double-slash prevention are applied consistently across Markdown links, button containers, navigation, and menubar. - **Eliminate 301 Redirects**: URLs like `/configuration/overview` resolve to `200` directly at `/configuration/overview/`. - **No Path Artefacts**: No `/index` remnants or `.md` extensions in any rendered link. - **Hreflang Accuracy**: Alternate tags now correctly strip locale prefixes from page paths. See the [Linking & Referencing](https://docs.docmd.io/content/syntax/linking/) guide for the full URL translation table. ### Universal `external:` and `raw:` Prefixes We've introduced two new magic prefixes to give you total control over link behaviour across all `docmd` components. - **`external:` - Force New Tab**: Add this to any link (Markdown, Buttons, Menubar) to force it to open in a new tab. - **`raw:` - Bypass Normalisation**: Use this when you need to link to a file (like `template.md`) without the engine stripping its extension. ```markdown [Open in new tab](external:./configuration/overview.md) ::: button "API Docs" external:./api/node-api.md [Download Template](raw:templates/starter.md) ``` **Behaviour change**: HTTP/HTTPS links no longer auto-open in a new tab. Use `external:` explicitly when you want that behaviour. ### Centralised URL API for Plugins A new URL utility layer in `@docmd/parser` is re-exported via `@docmd/api`. Plugins no longer need to parse `outputPath` manually - the engine pre-computes clean URLs for every page: ```typescript import { outputPathToSlug, sanitizeUrl } from '@docmd/api'; export async function onPostBuild({ pages }) { for (const page of pages) { page.urls.slug; // "guide/" page.urls.canonical; // "https://example.com/guide/" page.urls.pathname; // "/guide/" } } ``` See the [Plugin Development](https://docs.docmd.io/advanced/plugins/) guide for the full API reference. ## 🔧 Developer Experience ### Silent Plugin Warnings in Dev Mode Previously, a missing or misconfigured plugin would print a warning on **every file change** during `docmd dev`. These warnings are now **printed once** per dev session and suppressed on subsequent rebuilds to keep your terminal clean. ``` ↻ Change in docs/en/guide.md... ⚠️ Could not load plugin: @docmd/plugin-math Done. ``` ### SPA Hash Navigation Fixed In SPA mode, clicking a `#heading` anchor on the current page now scrolls smoothly to the target element. Browser back/forward through hash history (via `popstate`) also scrolls correctly. ```markdown [Jump to Configuration](#configuration) <!-- now working in SPA mode --> ``` ## 🚀 SEO Improvements - **Trailing Slashes**: All internal URLs rendered with trailing slashes to eliminate 301 redirect chains. - **Clean paths**: Canonical and hreflang `<link>` tags use correct normalised paths. - **Zero Artefacts**: No `.md` extensions or `/index` fragments in production HTML. ## Migration Guide Update with `npm update @docmd/core` or `pnpm update @docmd/core`. No configuration changes required. ::: callout info If you have custom server-side redirect rules that strip trailing slashes, remove them. The engine now produces the canonical trailing-slash format natively. ::: --- ## [Release Notes - 0.7.7](https://docs.docmd.io/07/release-notes/0-7-7/) --- title: "Release Notes - 0.7.7" description: "Introducing multi-project support, the Universal TUI Design System, and a premium, emoji-free terminal experience for professional documentation workflows." --- The `docmd` 0.7.7 release introduces **multi-project support** - the ability to orchestrate multiple independent documentation sites from a single repository. Alongside this architectural shift, we are debuting the **Universal TUI Design System**, a complete modernisation of our terminal interface that delivers a premium, high-signal developer experience through a new standalone styling package. ## ✨ Highlights ### Multi-Project Support You can now build and serve multiple independent documentation sites from a single `docmd` instance. A single root configuration allows you to define multiple projects, each with its own prefix, independent versioning, and isolated navigation, while sharing a unified theme and deployment pipeline. ```javascript // docmd.config.js (root) import { defineConfig } from '@docmd/api'; export default defineConfig({ projects: [ { prefix: '/', src: 'docmd-main' }, { prefix: '/search', src: 'docmd-search' } ] }); ``` Each project maintains its own directory structure and configuration, allowing you to manage complex documentation ecosystems (e.g., a core engine and its satellite tools) under a single domain without version conflicts. ### Universal TUI Design System We have completely rebuilt the `docmd` terminal interface to provide a professional, high-signal experience. Moving away from "playful" emojis, the new system uses refined box-drawing characters and a curated colour palette to deliver clear, actionable feedback. - **Improved Branding**: Centralised ASCII logo definition within the TUI system ensures a consistent brand presence across all CLI interactions. - **High-Signal Output**: Logs are now structured using a clean, tabular aesthetic that prioritises readability in both local development and CI/CD environments. - **Consistency**: Whether you are building a site, running a dev server, or using a migration tool, the terminal experience remains perfectly unified. ### Standalone `@docmd/tui` Package To support this new design system, we have decoupled terminal aesthetics from the core logic into a dedicated `@docmd/tui` package. This architectural shift eliminates circular dependencies and allows plugin authors to consume the same professional UI components as the core engine. By centralising our "Terminal User Interface" logic, we ensure that every piece of output - from core build logs to third-party plugin warnings - follows the same premium design language. ### Emoji-Free Professionalism In line with our commitment to a premium developer experience, 0.7.7 transitions to an **emoji-free standard**. We've replaced legacy emoji-based status markers with a sophisticated box-drawing aesthetic. This change ensures that `docmd` looks and feels like a production-grade tool, providing a cleaner interface that integrates easily into professional IDEs and terminal emulators. ### Intelligent Config Validation Configuration errors no longer leak Node.js stack traces. We've enhanced real-time configuration feedback using standardised TUI components to provide clean, human-readable error messages. The validator now detects multi-project root configurations and provides specific guidance for missing properties or typos. When a configuration error occurs, `docmd` now presents a clear "Error Report" with exact line references and suggested fixes, ensuring you spend less time debugging and more time writing. ### Multi-Project Dev Server The `docmd dev` command has been upgraded to support multi-project orchestration. It builds all projects and serves them from a single port, with intelligent file watching that triggers targeted rebuilds for the specific project being edited. ``` ──────────────────────────────────────── MULTI-PROJECT DEV SERVER Local: http://127.0.0.1:3000 Network: http://192.168.1.5:3000 Project: / → docmd-main/ Project: /search → docmd-search/ ──────────────────────────────────────── ``` ## 🛠️ Internal Refactoring This release includes significant architectural hardening to support the new TUI and multi-project capabilities: - **Dependency Architecture**: Optimised package dependencies to ensure a strictly directed acyclic flow, preventing circular imports between the engine and UI layers. - **Logger Refactoring**: Fully deprecated legacy logger utilities in favour of the centralised TUI system. - **Project Orchestration**: The multi-project handler lives in a standalone module that safely manages directory contexts (`chdir`) and merges independent outputs into a unified site structure without modifying the existing build pipeline. ## 📝 Complete Changelog ### Features & Enhancements - **Multi-Project Engine**: Support for `projects[]` in root configuration with shared assets and independent versioning. - **Universal TUI**: Rebuilt terminal interface using box-drawing characters and professional styling. - **Standalone TUI Package**: New `@docmd/tui` library for unified CLI aesthetics across the monorepo. - **Improved Branding**: Introduced a centralised ASCII logo for all CLI entry points. - **Config Validation**: Enhanced real-time feedback with human-readable error reports and no stack traces. - **Dependency Optimisation**: Strictly enforced acyclic dependency flow across all internal packages. ### Cleanups & Removals - **Emoji-Free Standard**: Removed all legacy emoji-based terminal output. - **Redundant Logs**: Eliminated ad-hoc `chalk` and `console.log` calls in favour of the TUI logger. - **Legacy Utilities**: Removed deprecated internal logger helpers. ## Migration Guide ### For Existing Projects **Existing single-project setups require no changes.** The engine continues to support the standard single-project workflow by default. ### Adopting Multi-Project Support To transition to a multi-project setup: 1. Move your existing documentation source into a subdirectory. 2. Create a root `docmd.config.js` and define your projects using the `projects` array. 3. Remove redundant `src` and `out` paths from child configurations, as the root orchestrator now manages these. We recommend migrating any custom `console.log` or `chalk` statements to the new `@docmd/tui` package to ensure your plugin's output matches the core `docmd` aesthetic. --- ## [Release Notes - 0.7.8](https://docs.docmd.io/07/release-notes/0-7-8/) --- title: "Release Notes - 0.7.8" description: "Introducing the Git plugin, a redesigned high-signal terminal interface with live progress tracking, parallel page processing for significantly faster builds, auto-installation for official plugins, and container syntax compatibility." --- The `docmd` 0.7.8 release introduces the **Git plugin** for repository-aware metadata, a completely **redesigned terminal interface** with live progress feedback, **parallel page processing** for dramatically faster builds, **automatic plugin installation** for official plugins, and **container syntax compatibility** for users migrating from other documentation engines. ## ✨ Highlights ### Build Engine - Parallel Processing The page rendering pipeline has been redesigned from sequential to **batched parallel processing**, delivering significant speedup on documentation sites of all sizes. **What changed:** - **Batched file I/O**: Files are now read 64 at a time and written 128 at a time via `Promise.all`, instead of one-by-one sequential reads - **Pipeline overlap**: File reading, markdown parsing, and HTML writing phases now overlap across batches - **Parallel writes**: All rendered HTML files are written to disk concurrently in batches instead of sequentially **Projected performance (simple pages):** | Scale | Before (0.7.7) | After (0.7.8) | Improvement | | :--- | :--- | :--- | :--- | | ~1,000 pages | ~22s | ~12s | **~45% faster** | | ~10,000 pages | ~4 min+ | ~1.5 min | **~60% faster** | | File read phase | Sequential | 64-file batches | **64x concurrency** | | File write phase | Sequential | 128-file batches | **128x concurrency** | | Progress feedback | None (silent) | Live progress bar | Real-time | The performance improvement scales with documentation size. Larger sites (1,000+ pages) with heavy I/O benefit the most from batched parallel processing. ### Terminal Interface - Unified TUI All terminal output has been redesigned into a **unified, high-signal design system** shared across every command. No more silent waits, inconsistent formatting, or cluttered multi-line output. **New TUI primitives:** | Feature | Description | | :--- | :--- | | **Progress bar** | `━━━━━━━━━━━━───────── 42/100 (42%)` - single-line, updates in-place | | **Spinner** | `⠋ ⠙ ⠹` - braille-dot animation during long operations | | **Timer** | Every build, rebuild, and project shows elapsed time | | **Sections** | Consistent `┌─ Section / └──` framing across all commands | **Unified output across all commands:** <img width="640" alt="image" src="https://github.com/user-attachments/assets/4d5a780b-73c1-4b6b-bd83-99837c09362f" /> **Commands unified:** - **`docmd build`** - section header with source/output/versions/locales, progress bar, timing - **`docmd dev`** - animated spinner during initial build and rebuilds, timing per-rebuild - **Multi-project builds** - per-project spinner animation, per-project timing, total summary - **`docmd live`** - consistent section framing matching all other commands ### Git Plugin The new **Git plugin** brings repository-aware metadata to your documentation pages, last-updated timestamps, commit history tooltips, and edit links, all derived directly from your Git history with zero configuration. ```javascript // Configure edit links plugins: { git: { repo: 'https://github.com/your-org/docs', branch: 'main' } } ``` **Features:** - **Last Updated Timestamps**: Shows when each page was last modified, using relative formatting for recent changes - **Commit History Tooltip**: Hover to see recent commits with author names and messages - **Edit Links**: Automatically constructs "Edit this page" links for GitHub, GitLab, and Bitbucket - **Graceful Degradation**: Automatically disables itself if the project is not in a Git repository The plugin replaces the legacy `editLink` configuration option with a more feature-rich alternative. See the [Git plugin documentation](https://docs.docmd.io/plugins/git/) for full details. ### Auto-Installation for Official Plugins Official plugins listed in your `docmd.config.js` are now automatically installed if missing. When you add a plugin to your config that isn't installed, docmd downloads it from npm on the next build. ```javascript // docmd.config.js plugins: { pwa: {}, // Not installed? docmd auto-installs it threads: {} // Same here } ``` **Security features:** - Only works for official `@docmd/plugin-*` packages in the registry - Installs the exact version matching your `@docmd/core` version - Uses your project's package manager (npm, pnpm, yarn, or bun) - Shows progress in the terminal ### Container Syntax Compatibility Users migrating from **VitePress**, **Docusaurus**, or similar documentation engines can now use familiar container syntax without modification. **VitePress-style containers now work:** ```markdown :::tip This renders as a tip callout. ::: :::warning This renders as a warning callout. ::: :::details Click to expand This renders as a collapsible section. ::: ``` **Docusaurus-style containers now work:** ```markdown :::note This renders as an info callout. ::: :::caution This renders as a warning callout. ::: ``` Additionally, **spaceless syntax** is now supported for all containers: ```markdown :::callout info Works the same as ::: callout info ::: :::tabs Works the same as ::: tabs ::: ``` This allows documentation to be migrated from other engines with minimal changes. ### Migration-Friendly Aliases | Alias | Maps To | Origin | | :--- | :--- | :--- | | `:::tip` | `callout tip` | VitePress | | `:::warning` | `callout warning` | VitePress | | `:::danger` | `callout danger` | VitePress | | `:::info` | `callout info` | VitePress | | `:::details` | `collapsible` | VitePress | | `:::note` | `callout info` | Docusaurus | | `:::caution` | `callout warning` | Docusaurus | These aliases work silently alongside the standard `docmd` syntax. Your existing documentation continues to work unchanged, whilst imported content from other engines renders correctly. ## Internal Improvements ### British English Standardisation Documentation has been updated to use British English spelling consistently throughout. This includes terminology like "optimised", "centralised", "localisation", and "colour" where appropriate. ### Code Quality - Replaced em-dashes with standard hyphens across documentation and code comments for improved readability - Standardised comment formatting in source files - Improved TypeScript type definitions for plugin APIs ## 📝 Complete Changelog ### Features - **Git Plugin (Core)**: New core plugin for last-updated timestamps, commit history, and edit links with graceful degradation - **Auto-Install**: Official plugins in config are automatically installed if missing - **Container Aliases**: VitePress and Docusaurus container syntax now works out of the box - **Spaceless Containers**: All containers now accept syntax with or without space after `:::` - **Parallel Processing**: Batched file I/O with 64-file read and 128-file write concurrency - **Unified TUI**: Progress bar, spinner, timer, and consistent section output across all commands ### Improvements - **Build Performance**: Up to ~60% faster builds on large sites through parallel I/O batching - **Live Progress**: Real-time progress bar during page processing - **Animated Spinners**: Visual feedback during builds, rebuilds, and multi-project processing - **Build Timing**: Every operation reports elapsed time - **Git Widget UI**: Tooltip uses CSS `:hover`/`:focus-within` for smooth, jitter-free display - **Code Block Styling**: `docmd-code-block-wrapper` now uses the universal `--shadow-sm` variable, matching all other container blocks - **Live Editor TUI**: Unified section framing and graceful shutdown - **Documentation**: British English spelling standardisation - **Code Style**: Consistent formatting across codebase - **Plugin Registry**: Added Git plugin to official registry ### Deprecations - **editLink Config**: The standalone `editLink` configuration option is deprecated in favour of the Git plugin ## Migration Guide ### Adopting the Git Plugin If you were using the `editLink` configuration, replace it with the `git` plugin. The new approach is smarter, it automatically detects your git repository root and computes the correct file path, so you no longer need to hardcode a directory in the URL. **Before (deprecated):** ```javascript export default defineConfig({ editLink: { enabled: true, baseUrl: 'https://github.com/org/repo/edit/main/docs' // ← hardcoded dir } }); ``` **After:** ```javascript export default defineConfig({ plugins: { git: { repo: 'https://github.com/org/repo', // ← just the repo, no path needed branch: 'main' } } }); ``` The plugin resolves the correct file path relative to the git root automatically. This means edit links work correctly in monorepos and multi-project setups without any manual path configuration. **Additional options:** | Option | Default | Description | | :--- | :--- | :--- | | `repo` | - | Repository URL (any provider) | | `branch` | `'main'` | Branch to link to | | `editPath` | `'edit'` | URL segment for edit page. Use `'-/edit'` for GitLab, `'src'` for Bitbucket | | `editLink` | `true` | Set `false` to disable the edit link | | `editLinkText` | i18n string | Custom label for the edit link | ### For Users Migrating from Other Engines If you are importing documentation from VitePress, Docusaurus, or similar engines: 1. Your existing `:::tip`, `:::warning`, `:::note` containers will render correctly 2. Spaceless syntax like `:::tabs` works alongside the standard `::: tabs` 3. No changes to your markdown files are required We recommend gradually transitioning to the standard `docmd` syntax (`::: callout tip`) for new content, as it provides more flexibility with titles and icons. --- ## [Release Notes - 0.7.9](https://docs.docmd.io/07/release-notes/0-7-9/) --- title: "Release Notes - 0.7.9" description: "OpenAPI plugin, Plugin API improvements with onBeforeRender hook and sourcePath, Git plugin commit history accuracy fix for multi-project builds, contributor avatars, and smart sticky footer." --- The `docmd` 0.7.9 release introduces **Incremental Rebuilds** for near-instant development, the **OpenAPI plugin**, and major performance optimizations via a **Parallel Plugin Architecture**. It also resolves critical config file leakage, fixes monorepo git history accuracy, adds contributor avatars, and implements a smart sticky footer. ## ✨ Highlights ### OpenAPI Plugin The new **OpenAPI plugin** renders API reference documentation directly from OpenAPI 3.x spec files inside Markdown pages - at build time, with no client-side JavaScript and no third-party UI libraries (no Swagger UI, no Redoc). Add a spec embed anywhere in your Markdown: ````markdown ```openapi ./api/openapi.json ``` ```` The plugin reads the spec at build time and outputs static HTML: colour-coded method badges, parameter tables, request/response schema tables, and status code descriptions. It supports both JSON and YAML specs, resolves internal `$ref` references, and handles `oneOf`/`anyOf` union types. **New in 0.7.9:** Added a `download: true` option to provide direct links to the raw spec file in the UI - perfect for AI models (like GPT-4 or Claude) to consume your API documentation programmatically. ```bash docmd add openapi ``` See the [OpenAPI plugin documentation](../plugins/openapi/) for full details. ### Incremental Rebuilds (Instant Dev Mode) The development server now features a **Targeted Rebuild** system. Previously, editing a single Markdown file triggered a full site rebuild. For sites with hundreds of pages, this could take 10+ seconds. In 0.7.9, `docmd dev` only re-renders the specific file you modified. Page reloads are now **instant (<1s)**, even for massive projects. The system correctly maintains all navigation, versioning, and asset context during these partial updates. ### Parallel Plugin Architecture (Multi-Threaded Performance) The build engine has been overhauled to support **parallel plugin execution**. Previously, plugin hooks like `onBeforeRender` ran sequentially for every page. For plugins that perform I/O or spawn child processes (like the Git plugin), this was a significant bottleneck. In 0.7.9, the engine now processes page rendering in concurrent batches. Combined with the new **Asynchronous Git Plugin**, which uses non-blocking `execFile` calls, build times for large sites with hundreds of pages are up to **3x faster**. **Key improvements:** - **Batched Rendering**: Phase 3 of the generator now runs in parallel batches of 64 pages. - **Async Hooks**: All plugin hooks can now be `async`, and the engine correctly awaits them in parallel. - **Git Plugin Overhaul**: Replaced synchronous `execSync` with asynchronous, non-blocking process spawning. ## 📝 Complete Changelog ### Bug Fixes - **Git Plugin - Per-file commit history in multi-project builds**: Module-level singleton state (`_gitRootPath`) was set once from whichever project docmd processed first, and reused for all subsequent projects. This caused pages in project 2+ to query git history against the wrong repository root, returning empty or mismatched results. The fix resolves the git root per file directory using a per-directory cache, so each file always queries its own repository context - safe for monorepos and multi-project setups. - **Git Plugin - SPA hydration**: The git widget was re-hydrating timestamps on `docmd.afterReload()` (dev-server only). In SPA mode, navigating between pages left timestamps un-formatted. Fixed to listen on `docmd:page-mounted` instead, which fires after every SPA page swap. ### Features - **OpenAPI Plugin (`@docmd/plugin-openapi`)**: Build-time OpenAPI 3.x spec renderer. Outputs static HTML endpoint docs from JSON or YAML spec files. No client-side dependencies. - **Plugin API - `onBeforeRender` hook**: New lifecycle hook called before template rendering. Receives full `PageContext` including `sourcePath`. Mutations to `frontmatter` and `html` are reflected in the rendered output. - **Plugin API - `PageContext` type**: Formally typed and exported from `@docmd/api`. Includes `sourcePath`, `frontmatter`, `html`, `localeId`, `versionId`, and `relativePathToRoot`. - **Git Plugin - Contributor Avatars**: Commit history tooltip now shows Gravatar images (MD5-hashed email, `?d=mp` fallback) instead of initials. - **Git Plugin - Configurable Date Formats**: New `dateFormat` option: `relative` (default), `iso`, or `locale-aware`. ```javascript plugins: { git: { dateFormat: 'locale-aware' } } ``` - **Parallel Build Pipeline**: The generator now parallelises the template rendering phase. Plugins can now perform expensive operations (like Git calls or OpenAPI parsing) concurrently across multiple CPU cores via child processes. - **Asynchronous Git Plugin**: The Git plugin is now fully asynchronous. It uses non-blocking child processes and path normalisation to ensure high performance and accuracy even in complex monorepo structures. - **Incremental Rebuild System**: The dev server now performs targeted partial builds. Editing a file re-renders only that file, reducing reload times from 10s+ to under 300ms for large sites. - **OpenAPI Plugin - Download Spec**: New `download` option provides a link to the raw JSON/YAML spec in the page header for AI accessibility. - **UI - Smart Sticky Footer**: Footer is now always pinned to the bottom of the viewport using flex layout, even on pages with minimal content. (Fixed). ### Internal - **Edit Link Path Resolution**: Computed from the git repository root, not `config.src` or `process.cwd()`. Correct in all project layouts. - **Config Loader - Hardening**: Implemented mandatory cleanup for orphaned temporary config files (`docmd.config-*.js`) and added `try-finally` safety to prevent leakage during syntax errors. --- ## [Assets Management](https://docs.docmd.io/07/theming/assets-management/) --- title: "Assets Management" description: "How docmd handles CSS, JavaScript, and Image assets during the build process." --- `docmd` takes a "Mirror & Map" approach to assets. This ensures that your local development paths stay consistent with your production build. ## Directory Structure By default, `docmd` looks for an `assets/` folder in your project root. ```bash my-docs/ ├── assets/ # Source Assets │ ├── css/ │ ├── js/ │ └── images/ ├── docs/ # Content ├── docmd.config.js └── site/ # Build Output (Automatically mirrored) ``` ## Automatic Copying When you run `docmd build` or `docmd dev`: 1. **The Mirroring Logic**: The entire contents of your `assets/` folder are recursively copied to `site/assets/`. 2. **Stability**: We use a hardened copy engine with automatic retries to prevent "File Busy" or "ENOENT" errors on macOS and modern SSDs. 3. **Referencing**: You should always reference assets from your Markdown or Config using the **root-relative** path: ```markdown ![Logo](/assets/images/logo.png) ``` ## Custom CSS & JS Integration To link your assets to every page, add them to your theme configuration: ```javascript // docmd.config.js export default { theme: { customCss: ['/assets/css/branding.css'] }, customJs: ['/assets/js/utils.js'] } ``` ::: callout info "AI Recognition Strategy :robot:" * **Organise by type**: Keep `/css`, `/js`, and `/images` separate. This helps AI agents locate relevant styles or scripts instantly when you ask them to "edit the header colour". * **Use Descriptive Filenames**: Naming an image `authentication-flow-diagram.png` provides much more context to the `llms.txt` crawler than `img_01.png`. ::: --- ## [Available Themes](https://docs.docmd.io/07/theming/available-themes/) --- title: "Available Themes" description: "Explore docmd's built-in themes including Sky, Ruby, and Retro. Learn how to switch themes with a single config line." --- `docmd` provides a set of professionally designed, light/dark responsive themes. You can switch your entire site's aesthetic by changing a single key in `docmd.config.js`. ## How to Switch Themes ```javascript // docmd.config.js export default { theme: { name: 'sky', appearance: 'system', // Options: 'light', 'dark', 'system' } } ``` ## Built-in Theme Gallery | Theme | Best For | Vibes | | :--- | :--- | :--- | | `default` | Low-profile docs | Clean, lightweight, neutral | | `sky` | Product Docs | Modern, premium, standard-issue | | `ruby` | Brand Identity | Sophisticated, serif headers, vibrant | | `retro` | Dev Tools | 80s Terminals, monospace, neon accents | ::: grids ::: grid ::: button "Default" javascript:switchDocTheme('default') ::: ::: grid ::: button "Sky" javascript:switchDocTheme('sky') ::: ::: grid ::: button "Ruby" javascript:switchDocTheme('ruby') ::: ::: grid ::: button "Retro" javascript:switchDocTheme('retro') ::: ::: ### 1. `default` The very theme used for this documentation site. Use this if you plan on adding extensive custom CSS and don't want any built-in design layers interfering. ### 2. `sky` The gold standard for modern documentation. It features crisp typography, subtle transitions, and high-contrast light/dark modes that match modern SaaS platforms. ### 3. `ruby` A high-elegance theme using serif typography for headers and a deep, jewel-toned colour palette. Perfect for documentation that needs to feel authoritative and premium. ### 4. `retro` A nostalgia-fueled theme inspired by vintage computing. Features include phosphor-green text on black backgrounds (in dark mode), scanline effects, and monospace fonts like Fira Code by default. ## Theming Architecture 1. **CSS Layering**: Themes are additive. Choosing `sky` actually loads the base `default` styles and then overlays the `sky` aesthetic on top. 2. **Native dark-mode**: Every theme includes a first-class dark mode implementation. 3. **No Refresh**: When users switch themes via the UI, the SPA engine updates the `--docmd-primary` variables instantly without a page reload. ::: callout tip When describing your documentation layout to an AI developer tool, mentioning your theme (e.g., "I'm using the `retro` theme") helps the model suggest custom CSS overrides that align with that specific theme's variable schema. ::: --- ## [Custom Styles & Scripts](https://docs.docmd.io/07/theming/custom-css-js/) --- title: "Custom Styles & Scripts" description: "Inject your own CSS and JS files to extend docmd's functionality and branding." --- While `docmd` themes are highly flexible, you may want to inject your own stylesheets or interactive scripts. This is done via the `theme.customCss` and `customJs` arrays in your configuration. ## Custom CSS Use `theme.customCss` to override existing styles or add new ones. ```javascript // docmd.config.js export default { theme: { customCss: [ '/assets/css/branding.css' // Path relative to site root ] } } ``` ### How it Works 1. Place your CSS file inside your project’s assets folder (e.g., `docs/assets/css/branding.css`). 2. `docmd` will automatically copy it to the build folder and inject a `<link>` tag into every page. 3. Custom CSS is loaded **after** the theme styles, ensuring your overrides take priority. ## Custom JavaScript Use the top-level `customJs` array for scripts that add behaviour or integrate 3rd-party services. ```javascript // docmd.config.js export default { customJs: [ '/assets/js/feedback-widget.js' ] } ``` ### Life-cycle Awareness Scripts are injected at the bottom of the `<body>` tag. Since `docmd` is a **Single Page Application (SPA)**, remember that: * The page does not fully reload when navigating between links. * You may need to listen for custom lifecycle events to re-initialise your scripts on new pages. For the full event list and usage examples, see [Client-Side Events](../api/client-side-events.md). ::: callout tip Adding custom CSS and JS allows AI models (like ChatGPT) to suggest much more tailored UI improvements. If you mention "I have a custom `branding.css` file", the model can provide specific selectors that won't conflict with the core `docmd` engine. ::: --- ## [Customisation & Variables](https://docs.docmd.io/07/theming/customisation/) --- title: "Customisation & Variables" description: "A complete reference of docmd's CSS variables and component classes for advanced styling." --- `docmd` is built using a CSS variable-first architecture. This means you can restyle your entire site by simply overriding a few keys in a `:root` block without writing complex CSS selectors. ## Global Variable Reference | Variable | Default (Light) | Default (Dark) | Description | | :--- | :--- | :--- | :--- | | `--bg-colour` | `#ffffff` | `#09090b` | Main page background. | | `--text-colour` | `#3f3f46` | `#a1a1aa` | Standard body text. | | `--text-heading` | `#09090b` | `#fafafa` | Title and Header colours. | | `--link-colour` | `#068ad5` | `#068ad5` | Primary accent / links. | | `--border-colour` | `#e4e4e7` | `#27272a` | Dividers and borders. | | `--sidebar-bg` | `#fafafa` | `#09090b` | Navigation background. | | `--ui-border-radius` | `6px` | `6px` | Rounding for all UI items. | | `--sidebar-width` | `260px` | `260px` | Sidebar column width. | ## Example Override To change your site's primary accent colour, add this to your `customCss`: ```css :root { --link-color: #f43f5e; /* Rose 500 */ } body[data-theme="dark"] { --link-color: #fb7185; /* Rose 400 */ } ``` ## Component Targeting If you need to style specific components, use these top-level classes: * `.main-content`: The wrapper for all Markdown content. * `.sidebar-nav`: The internal navigation list. * `.page-header`: The top navigation bar. * `.docmd-search-modal`: The search overlay. * `.docmd-tabs`: Tab container components. * `.callout`: The alert/note boxes. ## Troubleshooting specificity Most `docmd` styles use low specificity. If your overrides aren't applying, ensure your `customCss` is registered correctly and check if adding a `body` prefix (e.g., `body .main-content`) helps. ::: callout tip Because `docmd` uses standard CSS variables, you can ask an AI: *"Give me a professional colour palette using --link-colour and --bg-colour for docmd"*. The model will be able to provide ready-to-paste CSS that integrates perfectly with the built-in themes. ::: --- ## [Icons](https://docs.docmd.io/07/theming/icons/) --- title: "Icons" description: "How to use and customise Lucide icons in your documentation." --- `docmd` comes with built-in support for the [Lucide](external:https://lucide.dev/) icon library. Icons can be used in your navigation sidebar, buttons, and custom components to provide visual cues and improve scannability. ## Navigation Icons Assign an icon to any navigation item in your `docmd.config.js`. Use the kebab-case name of any icon found on the Lucide website. ```javascript navigation: [ { title: 'Home', path: '/', icon: 'home' }, { title: 'Setup', path: '/setup', icon: 'settings' } ] ``` ## Icons in Containers You can also use icons inside your buttons, tags, tabs, and other containers by including the raw HTML or using standard `icon:` prefix across docmd. ```markdown ::: button "Download" /download icon:download ``` ## CSS Styling All icons are rendered as inline SVGs with the class `.lucide-icon`. You can globally change their size or stroke weight in your `customCss`: ```css .lucide-icon { stroke-width: 1.5px; /* Thinner icons for a modern look */ width: 1.2rem; height: 1.2rem; } /* Target a specific icon */ .icon-rocket { color: #ff5733; } ``` ## Icon Reference We support the entire Lucide library. You can browse the thousands of available icons here: ::: button "Browse Lucide Icons" external:https://lucide.dev/icons icon:globe --- ## [Light & Dark Mode](https://docs.docmd.io/07/theming/light-dark-mode/) --- title: "Light & Dark Mode" description: "How to configure the default viewing mode and manage the theme switcher for the best user experience." --- `docmd` provides built-in support for light and dark colour schemes. It detects user system preferences automatically and allows manual overrides via a UI toggle. ## Default Viewing Mode You specify the starting state of your documentation in `docmd.config.js`. ```javascript // docmd.config.js export default { theme: { name: 'sky', appearance: 'system' // Options: 'light', 'dark', 'system' (default) } } ``` * **`system`**: Matches the user's OS preference (Recommended). * **`light`**: Force light mode on initial load. * **`dark`**: Force dark mode on initial load. ## Configuring the Toggle Button The theme switcher is part of the **Options Menu**. You can control its visibility and position within the `layout` object. ```javascript layout: { optionsMenu: { position: 'header', // Options: 'header', 'sidebar-top', 'sidebar-bottom' components: { themeSwitch: true // Show or hide the Sun/Moon toggle } } } ``` ## How it works (Technical) The theme engine applies a `data-theme` attribute to the `<body>` tag: * `<body data-theme="light">` * `<body data-theme="dark">` If you are using a themed design like `sky`, the attribute will be `sky-light` or `sky-dark`. ### CSS Variables `docmd` themes use CSS variables for all colours. You can override these variables in your own CSS to customise the look of either mode. ```css /* Custom CSS override */ :root { --docmd-primary: #4f46e5; /* Primary accent for light mode */ } body[data-theme="dark"] { --docmd-primary: #818cf8; /* Primary accent for dark mode */ } ``` ## User Persistence When a user manually toggles the mode, their preference is stored in `localStorage`. `docmd` instantly reads this value on every page load to prevent "theme flickering" (FOUC). ::: callout tip When generating content, LLMs prefer high-contrast structures. `docmd` ensures that code snippets and callouts remain accessible in both modes, ensuring that `llms-full.txt` payloads are correctly understood as semantic blocks regardless of which mode was active during the build. ::: --- ## [Comparison](https://docs.docmd.io/comparison/) --- title: "Comparison" description: "How docmd stacks up against Docusaurus, VitePress, MkDocs, Starlight, and Mintlify - real numbers, real features." --- Here is how docmd stacks up against the alternatives, with measurements from a 50-page site built on the same hardware. ## Start writing in 3 seconds, not 30 minutes ::: tabs == tab "docmd" ```bash npx @docmd/core dev ``` Done. Your docs are live. No config files, no project scaffolding, no dependency maze. == tab "Docusaurus" ```bash npx create-docusaurus@latest my-site classic cd my-site npm install npm start ``` Four commands, a generated project with around 250 MB in `node_modules`, and a config file you need to edit before anything useful happens. == tab "VitePress" ```bash npx vitepress init ``` Asks you 5 questions, generates a config file, then you run `vitepress dev`. Clean - but still requires scaffolding. == tab "MkDocs" ```bash pip install mkdocs-material mkdocs new my-site && cd my-site mkdocs serve ``` Python ecosystem. You'll need `pip`, a virtual environment, and a `mkdocs.yml` before the first page renders. ::: ## The payload gap is real Your readers shouldn't download a React app just to read a paragraph. Here's what the browser actually receives on a 50-page site: | Generator | Total initial load | JS payload | CSS payload | |:----------|:------------------:|:----------:|:----------:| | **docmd** | **~18 KB** | ~12 KB | ~6 KB | | MkDocs Material | ~40 KB | ~25 KB | ~15 KB | | VitePress | ~50 KB | ~35 KB | ~15 KB | | Mintlify | ~120 KB | ~80 KB | ~40 KB | | Docusaurus | ~250 KB | ~200 KB | ~50 KB | ::: callout tip "Why this matters" icon:lightbulb Every 100 KB of JavaScript costs ~50ms of parse time on a mid-range phone. docmd's 12 KB JS means your docs load instantly, even on 3G. Docusaurus ships 16× more JavaScript for the same content. ::: ## Build speed Building the same 50-page site on an M1 MacBook Air: | Generator | Cold build | Hot rebuild (dev) | |:----------|:----------:|:-----------------:| | **docmd** | **~1.2s** | **~80ms** | | VitePress | ~2.5s | ~150ms | | MkDocs Material | ~3.0s | ~500ms | | Docusaurus | ~15s | ~2s | docmd rebuilds are fast enough that the page refreshes before you switch windows. ## i18n that handles missing translations Most tools fall apart when a reader switches to a language where some pages are not yet translated. docmd falls back to the default locale at build time. | Capability | docmd | VitePress | Docusaurus | Starlight | |:-----------|:-----:|:---------:|:----------:|:---------:| | Per-page fallback to default locale | ✅ | ❌ (404) | ❌ (404) | ✅ | | Localised "not translated" warning | ✅ | ❌ | ❌ | ✅ | | Auto-disable missing locales in switcher | ✅ | ❌ | ❌ | ❌ | | Instant page-existence check (no network) | ✅ | ❌ | ❌ | ❌ | | Versioning + i18n combined | ✅ | ❌ | ❌ | ❌ | | Zero-config (no custom React/Vue) | ✅ | Partial | ❌ | ✅ | ::: callout warning "What happens in VitePress and Docusaurus" icon:info If a reader switches to Hindi and that page isn't translated, they get a **404 error**. The only workaround is server-side redirects or writing a custom React/Vue component. docmd handles this at build time - unavailable locales show an "N/A" badge, and untranslated pages fall back silently with a localised warning callout. ::: ## Workspace Teams that maintain multiple products under one domain (for example, a core platform and an SDK) often need separate docs for each, with independent navigation and release cycles. Most generators require either separate deployments or custom plugin glue. | Capability | docmd | Docusaurus | VitePress | MkDocs | Starlight | |:-----------|:-----:|:----------:|:---------:|:------:|:---------:| | Native workspace support | ✅ | Plugin | ❌ | Plugin | ❌ | | Single config line per project | ✅ | ❌ | ❌ | ❌ | ❌ | | Independent versioning per project | ✅ | ✅ | ❌ | ❌ | ❌ | | Independent i18n per project | ✅ | ❌ | ❌ | ❌ | ❌ | | Shared assets across projects | ✅ | ❌ | ❌ | ❌ | ❌ | | Single `site/` output (no proxy needed) | ✅ | ❌ | ❌ | ❌ | ❌ | | Zero-config detection | ✅ | ❌ | ❌ | ❌ | ❌ | ::: callout info "How docmd does it" icon:info ```json "docmd.config.json" { "workspace": { "projects": [ { "prefix": "/", "src": "main-docs", "title": "Docs" }, { "prefix": "/sdk", "src": "sdk-docs", "title": "SDK" } ] } } ``` Each project folder has its own `docmd.config.json` with independent configuration. One `npx @docmd/core build` produces a single deployable directory - no reverse proxy, no nginx, no separate CI pipelines. ::: Docusaurus achieves similar results through multi-instance plugins, which require separate plugin entries, sidebar files, and manual route configuration per instance. MkDocs needs the third-party `mkdocs-monorepo-plugin`. VitePress, Starlight, and Mintlify have no native workspace support at all. ## Full feature matrix | Feature | docmd | Docusaurus | VitePress | MkDocs Material | Starlight | Mintlify | |:--------|:-----:|:----------:|:---------:|:---------------:|:---------:|:--------:| | **Zero-config start** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Config required** | None | `docusaurus.config.js` | `config.mts` | `mkdocs.yml` | `astro.config.mjs` | `mint.json` | | **Workspace** | ✅ | Plugin | ❌ | Plugin | ❌ | ❌ | | **SPA navigation** | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | | **Native versioning** | ✅ | ✅ | ❌ | Plugin | ❌ | ✅ | | **Native i18n** | ✅ | ✅ | Manual | Plugin | ✅ | ✅ | | **Built-in search** | ✅ | ❌ (Algolia) | ✅ | ✅ | ✅ | Cloud | | **llms.txt** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **MCP Server** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Agent Skills** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Docker Image** | ✅ | ❌ | ✅ | ❌ | ❌ | N/A | | **Inline discussions** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | **PWA support** | ✅ | Community | ❌ | ❌ | ❌ | ❌ | | **Self-hosted** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | **Deploy config generator** | ✅ | ❌ | ❌ | ❌ | ❌ | N/A | ## Configuration overhead Lines of config required for a site with versioning, i18n, search, and sitemap: | Generator | Config lines | Files required | |:----------|:------------:|:--------------:| | **docmd** | **~15 lines** | 1 (`docmd.config.json`) | | MkDocs Material | ~50 lines | 1 + plugins | | VitePress | ~80 lines | 1 + theme dir | | Docusaurus | ~120 lines | 3+ config files | ## Quality assurance docmd ships with a brute test suite that validates **25 distinct scenarios** across **85 assertions** - covering every feature in isolation and in combination. Every release must pass all 85 assertions and 13 internal failsafe checks before shipping. ::: callout tip "Run the tests yourself" icon:lightbulb ```bash git clone https://github.com/docmd-io/docmd.git cd docmd && node scripts/brute-test.js ``` ::: No other documentation generator in this class publishes a comparable end-to-end feature test suite as part of its source. --- ## [Cookie Consent](https://docs.docmd.io/configuration/cookie-consent/) --- title: "Cookie Consent" description: "Opt-in cookie consent dialog shipped with the default UI. Stores the user's choice in localStorage, supports translations, and emits a docmd:cookie-consent CustomEvent so plugins and templates can react." --- # Cookie Consent > **New in 0.8.7.** The cookie consent dialog is a built-in feature of the default `@docmd/ui` package. No plugin install required. **Opt-in** — nothing is rendered unless you set `config.cookie`. A minimal, accessible GDPR-style consent dialog. The user's choice is persisted in `localStorage` with a configurable TTL. A `docmd:cookie-consent` `CustomEvent` fires on `window` after a choice is made so plugins and templates can react (e.g. enable analytics, load third-party scripts). ## Enable in 30 seconds ```json "docmd.config.json" { "cookie": { "enabled": true, "message": "We use cookies to ensure you get the best experience.", "policyUrl": "/privacy", "position": "bottom-right" } } ``` Build, and the dialog appears on first visit. Subsequent visits respect the stored choice. ## Configuration reference | Field | Default | Description | |---|---|---| | `enabled` | `true` (when `cookie` object is present) | Master switch. | | `message` | Translation key `cookieMessage` | Dialog body text. Inline HTML allowed via the `t()` helper. | | `acceptText` | Translation key `cookieAccept` | Accept button label. | | `declineText` | Translation key `cookieDecline` | Decline button label. | | `policyUrl` | `null` | Optional link to your privacy policy. | | `position` | `"bottom"` | `"bottom"` \| `"bottom-left"` \| `"bottom-right"` \| `"center"` | | `dismissible` | `true` | Show an "X" close button. | | `expiryDays` | `180` | How long the choice is remembered in `localStorage`. | ### Position values | Value | Effect | |---|---| | `bottom` | Centered horizontally along the bottom edge. | | `bottom-left` | Anchored to the bottom-left corner. | | `bottom-right` | Anchored to the bottom-right corner. | | `center` | Centered modal. | ## Localisation All user-facing strings support the existing `t(key)` translation system. Override the keys in your `translations/<locale>.json` files: ```json "translations/fr.json" { "cookieMessage": "Cette page utilise des cookies pour vous offrir la meilleure expérience.", "cookieAccept": "Accepter", "cookieDecline": "Refuser", "cookiePolicy": "Politique de confidentialité", "cookieConsent": "Consentement aux cookies" } ``` ## Reacting to a choice A `CustomEvent` named `docmd:cookie-consent` is dispatched on `window` after the user accepts, declines, or dismisses: ```js window.addEventListener('docmd:cookie-consent', (e) => { if (e.detail.value === 'accept') { // Load analytics, marketing scripts, etc. } }); ``` The `detail.value` is one of `"accept"`, `"decline"`, or `"dismissed"`. If you need to read the choice synchronously (e.g. before any other script runs), `localStorage.getItem('docmd-cookie-consent')` returns the same payload. ## Re-styling The dialog is built from BEM-style classes on the `.docmd-cookie-banner` root. Re-skin it via `customCss` (always wins at priority 15): ```css .docmd-cookie-banner { --accent-color: #ff5a5f; border-radius: 16px; } .docmd-cookie-banner__btn--accept { background-color: var(--accent-color); border-color: var(--accent-color); } ``` ## Disabling To remove the dialog entirely, simply remove the `cookie` key from your config. There is no plugin to disable. ::: callout tip "GDPR best practice" If you are subject to GDPR, leave the dialog **enabled by default** and link to a real privacy policy via `policyUrl`. The default message is intentionally generic so you can supply your own via `message` or the translation system. ::: --- ## [Layout & UI Zones](https://docs.docmd.io/configuration/layout-ui/) --- title: "Layout & UI Zones" description: "Control the interface structure by managing headers, sidebars, and functional UI slots." --- A standard page contains six primary functional zones: 1. **Menubar**: A full-width top navigation bar for global site links. 2. **Header**: A persistent secondary bar. It contains the page title and utility buttons. 3. **Sidebar**: The primary navigation tree, usually on the left. 4. **Content Area**: The central Markdown rendering zone. Includes **Breadcrumbs**. 5. **Table of Contents (TOC)**: Right-hand heading navigation for the current page. 6. **Footer**: Bottom area for copyright, branding, and site-wide links. ## Global Component Configuration The engine uses a modular layout system. Configure most UI zones in the `layout` section of your `docmd.config.json`. ### Menubar The menubar provides a high-level navigation layer. It supports brand titles, regular links, and nested dropdowns. * **Location**: Fixed at the `top` or inline within the `header`. * **Documentation**: See [Menubar Configuration](menubar.md) for schemas and styling. ### The Page Header The header displays the page title, breadcrumbs, and utility menus. * **Controls**: Enable or disable the header globally via `layout.header`. Toggle breadcrumbs via `layout.breadcrumbs`. * **Overriding**: Use `hideTitle: true` in your [Page Frontmatter](../content/frontmatter.md) to hide the title area locally. ### Copy Widgets The breadcrumbs bar includes two copy buttons. One copies the page's raw Markdown, the other copies a structured context block that includes the URL, title, and description. Useful for pasting into AI chat windows or support tickets. Configure these buttons under `theme.copyWidgets` in your `docmd.config.json`: ```json "docmd.config.json" { "theme": { "copyWidgets": { "enabled": true, "raw": true, "context": true } } } ``` * `enabled`: Set to `false` to disable the bar completely. * `raw`: Set to `false` to hide the "Copy Markdown" button. * `context`: Set to `false` to hide the "Copy Context" button. ### Utility Menus (Options Menu) The `optionsMenu` groups core utilities like **Global Search**, **Theme Toggle**, and **Sponsorship links**. ```json "docmd.config.json" { "layout": { "optionsMenu": { "position": "header", "components": { "search": true, "themeSwitch": true, "sponsor": "https://github.com/sponsors/mgks" } } } } ``` ::: callout info "Automatic Fallback" icon:sparkles If the chosen position targets a disabled container, the engine moves the options menu to `sidebar-top`. This ensures utilities remain accessible. ::: ### Sidebar & Navigation The sidebar is the primary navigation tree. Define its structure in your config or external JSON files. * **Behaviour**: Supports animations, collapsible groups, and automatic path preservation. * **Documentation**: See [Navigation Configuration](navigation.md). ### Footer The engine provides **minimal** and **complete** layouts for your site footer. ```json "docmd.config.json" { "layout": { "footer": { "style": "complete", "description": "Documentation built with docmd.", "branding": true, "columns": [ { "title": "Community", "links": [ { "text": "GitHub", "url": "https://github.com/docmd-io/docmd" } ] } ] } } } ``` ::: callout tip "Interface Hierarchy" icon:lightbulb Use the menubar for global links and the sidebar for documentation structure. This separation keeps the navigation predictable for both human readers and crawlers. ::: --- ## [Localisation](https://docs.docmd.io/configuration/localisation/) --- title: "Localisation" description: "Serve documentation in multiple languages with locale-first routing, translated navigation, and automatic fallback." --- Add multi-language support to your documentation site. docmd serves each locale at its own URL prefix, translates system UI strings, and falls back gracefully when a translation is missing. ## Add languages to your config ```json "docmd.config.json" { "i18n": { "default": "en", "locales": [ { "id": "en", "label": "English" }, { "id": "hi", "label": "हिन्दी" }, { "id": "zh", "label": "中文" } ] } } ``` The `default` locale renders at the site root (`/`). All other locales render at `/{id}/`. You choose the IDs, labels, and which locale is the default - there are no hardcoded assumptions. If you want Hindi as the default, set `default: 'hi'` and Hindi renders at `/` whilst English renders at `/en/`. | Key | Type | Description | |:----|:-----|:------------| | `default` | `string` | Locale ID that renders at `/`. Defaults to the first locale if omitted. | | `locales` | `array` | List of locale objects. Each must have an `id`. | | `position` | `string` | Where the language switcher appears. `options-menu` (default), `sidebar-top`, or `sidebar-bottom`. | | `stringMode` | `boolean` | When `true`, generates locale pages from a single source using `data-i18n` attribute replacement. Default `false`. | | `inPlace` | `boolean` | When `true` (with client-side script), swaps strings without URL navigation. For SPAs/dashboards only. Default `false`. | Each locale object accepts: | Key | Type | Default | Description | |:----|:-----|:--------|:------------| | `id` | `string` | - | Any identifier you choose (e.g. `en`, `hi`, `fr-ca`). Used as the folder name and URL prefix. Required. | | `label` | `string` | Same as `id` | Display name shown in the language switcher. | | `dir` | `string` | `ltr` | Text direction. Set to `rtl` for Arabic, Hebrew, etc. | | `translations` | `object` | `{}` | Custom UI string overrides (see [Custom UI strings](ui-strings.md)). | ## URL structure The default locale has no URL prefix. Non-default locales are nested under `/{id}/`. When combined with [versioning](../versioning.md), the URL is `/{locale}/{version}/page`. ``` / ← default locale, current version /getting-started ← default locale page /05/ ← default locale, old version /hi/ ← non-default locale, current version /hi/getting-started ← non-default locale page /hi/05/ ← non-default locale, old version ``` The language switcher preserves your current page and version when you switch locales. The version switcher preserves your current locale. ## Missing locale directories If a locale is declared in `locales` but its source directory does not exist (e.g. no `docs/hi/` folder), docmd automatically **disables** that locale in the language switcher. The locale still appears in the dropdown - with an "N/A" badge and greyed-out styling - but clicking it does nothing. This prevents 404 errors when you list planned languages before their content is ready. ## Position the language switcher <img width="500" class="with-border" src="/assets/previews/menu-i18n.webp"> Control where the language switcher appears using the `position` option: ```json "docmd.config.json" { "i18n": { "position": "sidebar-top" } } ``` | Position | Behaviour | |:---------|:----------| | `options-menu` | Compact globe icon alongside theme toggle and search. Default. | | `sidebar-top` | Full dropdown with label at the top of the sidebar. | | `sidebar-bottom` | Full dropdown with label at the bottom of the sidebar. | ## String Mode (noStyle pages only) Standard i18n uses separate directories per locale (`docs/en/`, `docs/hi/`), each with its own markdown files. **String Mode** is a simpler alternative designed specifically for [noStyle pages](../../content/no-style-pages.md) - pages that use raw HTML instead of markdown. ```json "docmd.config.json" "i18n": { "default": "en", "stringMode": true, "locales": [ { "id": "en", "label": "English" }, { "id": "zh", "label": "中文" } ] } ``` With `stringMode: true`: 1. Source files stay in the root `docs/` directory (no locale subdirectories) 2. The default locale builds at `/` as normal 3. For each non-default locale, docmd clones the rendered HTML and applies **server-side string replacement** using JSON files from `assets/i18n/{locale}.json` 4. Output goes to `/{locale}/` - e.g. `/zh/index.html` - with full SEO (hreflang tags, correct `lang` attribute) 5. If a translation file is missing, the page renders with the default language text For full details on the `data-i18n` attribute syntax and JSON file format, see [noStyle string replacement](../../content/no-style-pages.md#string-replacement-i18n-for-nostyle). ::: callout warning "String Mode does not translate markdown content" icon:info String replacement works by finding `data-i18n` attributes in the rendered HTML. Standard markdown content (`## Heading`, paragraphs, lists) renders to plain HTML tags without these attributes - so there is nothing for the replacer to find. - **Documentation sites** → use directory mode (the default). Each locale has its own markdown files with fully translated prose. - **Landing pages, marketing sites, dashboards** → use string mode. These are noStyle pages with custom HTML where you control every tag and can add `data-i18n` attributes. If your site has both - for example, a noStyle landing page plus documentation - use directory mode for the docs and add `data-i18n` attributes to your noStyle page. String mode will translate the noStyle HTML while directory mode handles the documentation content. ::: ## Next steps - [Translated content](translated-content.md) - directory structure, writing translations, navigation - [UI strings & SEO](ui-strings.md) - customising system text, hreflang tags - [noStyle string replacement](../../content/no-style-pages.md#string-replacement-i18n-for-nostyle) - `data-i18n` attribute syntax and JSON format for noStyle pages --- ## [Translated Content](https://docs.docmd.io/configuration/localisation/translated-content/) --- title: "Translated Content" description: "Organise translations in locale subdirectories with per-file fallback and per-locale navigation." --- ## Directory Structure Every locale lives in its own subdirectory inside the source directory. The folder name matches the locale `id` from your config. ```text docs/ ├── en/ ← default locale content │ ├── index.md │ ├── navigation.json │ └── getting-started/ │ └── installation.md ├── hi/ ← second locale │ ├── index.md ← translated homepage │ ├── navigation.json ← translated navigation labels │ └── getting-started/ │ └── installation.md ← translated page └── zh/ ← third locale └── index.md ← only the homepage translated ``` The source directory holds only locale folders. No content files sit at the root level when i18n is enabled. ::: callout info "Folder Names Are Your Choice" icon:info Folder names match the `id` values in your config. If your config sets `{ id: 'fr-ca' }`, your folder is `docs/fr-ca/`. ::: ## Per-file Fallback You do not need to translate every page. docmd scans the **default locale directory** as the canonical structure. For every other locale, it checks for a translated page: - If `docs/hi/getting-started/installation.md` exists → serves the Hindi translation. - If it does not exist → serves the default locale version. When a page falls back, docmd displays a translated callout. This informs viewers the page is shown in the default language. Customise this message via your [UI strings](ui-strings.md) configuration. ## Locale-Exclusive Pages A non-default locale can host pages that do not exist in the default locale. These render only for that specific locale. ## Translate the Navigation Each locale directory can include its own `navigation.json`. docmd uses a cascading priority system to resolve the sidebar. For details on the resolution hierarchy, see [Navigation Configuration](../navigation.md). A locale's `navigation.json` uses the standard format: ```json "navigation.json" [ { "title": "शुरू करें", "children": [ { "title": "इंस्टालेशन", "path": "/getting-started/installation" }, { "title": "स्थानीयकरण", "path": "/configuration/localisation" } ] } ] ``` ::: callout tip "Partial Navigation" icon:info Create a locale `navigation.json` only when you want translated labels. If missing, the default navigation is used. ::: ## Versioning and i18n When combining versioning and i18n, structure the source directories hierarchically: ```text docs/ ← current version en/ ← current version, default locale hi/ ← current version, translated locale docs-v1/ ← previous version en/ ← v1, default locale hi/ ← v1, translated locale ``` The output URLs nest locale first, then version: ```text / ← default locale, current version /hi/ ← translated locale, current version /v1/ ← default locale, previous version /hi/v1/ ← translated locale, previous version ``` --- ## [UI Strings & SEO](https://docs.docmd.io/configuration/localisation/ui-strings/) --- title: "UI Strings & SEO" description: "Customise system UI text per locale and understand automatic SEO tags for multi-language sites." --- ## Built-in Language Support docmd and its official plugins ship with built-in translations for common languages. When you configure a supported locale, the engine automatically translates system text like search placeholders, navigation labels, and theme toggles. For unsupported languages or custom phrasing, the system falls back to English. You can override any string per locale. ## Custom UI Strings Use the `translations` property on any locale to override system text: ```json "docmd.config.json" "i18n": { "default": "en", "locales": [ { "id": "en", "label": "English" }, { "id": "ar", "label": "العربية", "dir": "rtl", "translations": { "onThisPage": "في هذه الصفحة", "previous": "السابق", "next": "التالي", "search": "بحث", "toggleTheme": "تبديل المظهر", "editThisPage": "تعديل هذه الصفحة", "selectLanguage": "اختر اللغة", "selectVersion": "اختر الإصدار", "fallbackMessage": "هذه الصفحة غير متاحة بعد باللغة {active}. عرض اللغة الافتراضية ({default})." } } ] } ``` The merge order is: **system translations → plugin translations → your config translations**. Your config always wins. ## Available Keys Instead of hardcoding a list of available keys, you can review the complete set of supported languages and translation keys directly in the docmd source repository. **[View Translation Source on GitHub](external:https://github.com/docmd-io/docmd/tree/main/packages/ui/translations)** The `fallbackMessage` key supports `{active}` and `{default}` placeholders. The engine replaces these with locale labels at build time. ## SEO and Hreflang docmd automatically generates `<link rel="alternate" hreflang="...">` tags for every page across all locales. The default locale also receives the `x-default` hreflang value. ```html <!-- Generated automatically on every page --> <link rel="alternate" hreflang="en" href="/"> <link rel="alternate" hreflang="x-default" href="/"> <link rel="alternate" hreflang="hi" href="/hi/"> <link rel="alternate" hreflang="zh" href="/zh/"> ``` No configuration is required. The engine injects these tags into every page when i18n is enabled. ::: callout info "noStyle Pages" icon:info The UI strings system applies to themed layout pages. For noStyle pages using custom HTML, see [Client-Side String Replacement](../../content/no-style-pages.md#string-replacement-i18n-for-nostyle). ::: --- ## [Menubar](https://docs.docmd.io/configuration/menubar/) --- title: "Menubar" description: "Structure and position your menubar, manage navigation links, and configure drop-down menus." --- The `menubar` is a premium navigation layer. It provides global context across your site. Position it as a fixed bar at the viewport top or relatively above the page header. ## Configuration Configure the menubar in the `layout` section of your `docmd.config.json`. ```json "docmd.config.json" { "layout": { "menubar": { "enabled": true, "position": "top", "left": [ { "type": "title", "text": "Brand", "url": "/", "icon": "home" }, { "text": "Documentation", "url": "/docs" }, { "type": "dropdown", "text": "Ecosystem", "items": [ { "text": "GitHub", "url": "https://github.com/docmd-io/docmd" }, { "text": "Live Editor", "url": "https://live.docmd.io" } ] } ], "right": [ { "text": "Support", "url": "/support", "icon": "help-circle" } ] } } } ``` ### Options | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `Boolean` | `false` | Toggles menubar visibility. | | `position` | `String` | `'top'` | `'top'` (fixed at absolute top) or `'header'` (positioned above the page title). | | `left` | `Array` | `[]` | Left-aligned navigation items. | | `right` | `Array` | `[]` | Right-aligned navigation items. | ## Item Types The `left` and `right` arrays support various item types. ### 1. Standard Link The most common item type. - `text`: Display label. - `url`: Path or external URL. - `icon`: Optional Lucide icon name. - `external`: Set to `true` to open in a new tab. ### 2. Title (Brand) Set `type: 'title'` to apply branding styles (e.g. bold fonts). ### 3. Dropdown Menu Set `type: 'dropdown'` and provide an `items` array to create a nested menu. ## Utility Integration Host the global search and theme toggle in the menubar. Set `optionsMenu.position` to `'menubar'`. ```json "docmd.config.json" { "layout": { "optionsMenu": { "position": "menubar" } } } ``` The options menu automatically aligns to the **right region**. It appears after any links defined in the `right` array. ::: callout info "Automatic Fallback" If the `menubar` is disabled, assigned utilities automatically fall back to the `sidebar-top` position. ::: ## Custom Styling Use CSS variables in your custom stylesheets to override the menubar appearance. See [Custom CSS & JS](../theming/custom-css-js.md) for details. ```css :root { --menubar-h: 56px; --menubar-bg: var(--bg-color); --menubar-border: var(--border-color); --menubar-text: var(--text-color); } ``` --- ## [Navigation Configuration](https://docs.docmd.io/configuration/navigation/) --- title: "Navigation Configuration" description: "Structure your sidebar, categorise links, and configure icons for readers and search engines." --- The compiler provides explicit control over your site navigation. A clear navigation hierarchy creates a logical reading sequence. This optimises the SPA experience and provides a clear context map for search indexing and AI models. ## 1. The Navigation Schema An array of link objects in your `docmd.config.json` file controls the sidebar. Each object is a direct link or a nested category group. <img width="260" class="with-border" src="/assets/previews/navigation-hierarchy.webp"> ```json "docmd.config.json" { "navigation": [ { "title": "Overview", "path": "/", "icon": "home" }, { "title": "Quick Start", "path": "/getting-started/quick-start", "icon": "rocket" } ] } ``` ## 2. Supported Properties Every item supports these settings: | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | | `title` | `String` | Yes | The text displayed in the sidebar menu. | | `path` | `String` | No | Target URL. Relative local paths must begin with a forward slash (`/`). | | `icon` | `String` | No | Name of any [Lucide Icon](external:https://lucide.dev/icons) in kebab-case format (e.g., `git-branch`). | | `children` | `Array` | No | An array of nested navigation items to establish a submenu. | | `collapsible`| `Boolean`| No | When `true`, the user can expand or collapse the category folder. | | `external` | `Boolean`| No | When `true`, opens the link in a new browser tab. | ## 3. Organising Section Groups Structure your sidebar using two primary grouping methods: ### Clicking Group (Direct Page + Child Folders) Specify a `path` along with `children` for a category header. Clicking the title loads the landing page and expands the child links. ```json "docmd.config.json" { "title": "Cloud Services", "path": "/cloud/overview", "children": [ { "title": "AWS Setup", "path": "/cloud/aws" }, { "title": "GCP Setup", "path": "/cloud/gcp" } ] } ``` ### Static Label (Category Headers Only) Omit the `path` parameter. The header serves as a non-clickable title grouping related links. Use this to divide major technical categories without a single landing page. ```json "docmd.config.json" { "title": "Formatting & Elements", "icon": "layout-grid", "children": [ { "title": "Syntax Guide", "path": "/content/syntax" }, { "title": "Rich Containers", "path": "/content/containers" } ] } ``` ## 4. Automated Breadcrumbs The engine automatically generates contextual breadcrumbs for every page. These display directly above the main page header to assist with rapid orientation. <img width="500" class="with-border" src="/assets/previews/navigation-breadcrumb.webp"> ### Key Behaviours * **Automatic Resolution**: The engine traces the active route through your navigation tree to construct the hierarchy. * **Active Indicator**: The current page is the final, unlinked breadcrumb item. * **Mobile Optimisation**: Breadcrumbs simplify or hide dynamically on small viewports to save screen space. ### Disabling Breadcrumbs Breadcrumbs are enabled by default. Update your site layout options to disable them globally: ```json "docmd.config.json" { "layout": { "breadcrumbs": false } } ``` ## 5. Navigation Resolution Cascading The compiler uses a "closest file wins" cascading resolution system. This supports multiple versions or languages without bloating your global configuration. ```text my-project/ ├── docmd.config.json [Level 3: Global Config] - Default Fallback ├── docs-v1.0/ │ ├── navigation.json [Level 2: Version Navigation] - Overrides Global │ └── zh/ │ └── navigation.json [Level 1: Language Navigation] - Absolute Priority ``` 1. **Level 1: Language-Specific** (`navigation.json` inside a locale folder): Overrides all settings for this specific language and version. 2. **Level 2: Version-Specific** (`navigation.json` inside a version folder): Overrides global configuration for this version across all languages. 3. **Level 3: Global Configuration** (`config.navigation`): The base fallback definition in the central configuration file. ### Smart Broken-Link Prevention The engine automatically checks if targeted files exist during Level 2 or 3 navigation fallback. Missing files are filtered out of the sidebar dynamically. This eliminates broken links for older versions or missing translations. ## 6. Icon Integration The compiler includes the complete **Lucide Icon** system. Use the official Lucide name in kebab-case format (e.g., `settings`, `folder-open`, `book-marked-line`) to apply an icon. ::: callout tip "Optimising Sidebar Labels" icon:sparkles Keep sidebar titles clear and descriptive. A concise navigation structure allows AI agents to parse your site map easily from the compiled `llms.txt` feed. ::: --- ## [General Configuration](https://docs.docmd.io/configuration/overview/) --- title: "General Configuration" description: "Configure docmd.config.json to manage branding, custom schemas, routing, layout behaviour, and build engines." --- The `docmd.config.json` file is the central configuration for your workspace. It controls site styling, sidebar hierarchies, localisation details, and compiler options. ## 1. The Configuration Schema JSON is the standard configuration format. This allows high-performance serialisation across the engine's worker pools. However, `docmd.config.js` and `docmd.config.ts` remain fully supported if you need dynamic JavaScript logic. ```json "docmd.config.json" { "title": "My Project", "url": "https://docs.myproject.com", "src": "docs", "out": "site", "base": "/" } ``` ## 2. Core Settings These top-level parameters configure the compiler's base inputs and destinations. | Parameter | Type | Default | Description | | :--- | :--- | :--- | :--- | | `title` | `String` | `"Documentation"` | The formal name of your site. Appears in navigation headers and browser title tabs. | | `url` | `String` | `""` | Your canonical production URL. Critical for SEO validation, Sitemap indexing, and OpenGraph metadata. | | `src` | `String` | `"docs"` | Relative path to the folder containing your source Markdown (.md) files. | | `out` | `String` | `"site"` | Relative path where the compiler writes the optimised production static site. | | `base` | `String` | `"/"` | The root base path of your site (e.g., set to `/docs/` if hosting in a subfolder). | | `tmp` | `String` | `null` | Custom directory for temporary compile files and caching. Defaults to an isolated system temp folder. | | `i18n` | `Object` | `null` | Multi-language parameters. See the [Localisation Guide](localisation/translated-content.md). | | `plugins` | `Object` | `{}` | Key-value mapping to configure standard and custom plugins. See [Plugins Guide](../plugins/usage.md). | | `engine` | `String` | `"js"` | The active processing engine: `"js"` or `"rust"` (preview). | ## 3. Branding & Identity Manage how your brand appears in the header and browser tabs. ```json "docmd.config.json" { "logo": { "light": "assets/images/logo-dark.png", "dark": "assets/images/logo-light.png", "href": "/", "alt": "Company Logo", "height": "32px" }, "favicon": "assets/favicon.ico" } ``` ## 4. UI Layout and Behaviour The engine provides a modular header and sidebar layout. Customise functional regions. Toggle component visibility (search, dark-mode switch, breadcrumbs). ```json "docmd.config.json" { "layout": { "spa": true, "header": { "enabled": true }, "sidebar": { "collapsible": true, "defaultCollapsed": false }, "optionsMenu": { "position": "header", "components": { "search": true, "themeSwitch": true } } } } ``` See the [Layout & UI Zones](layout-ui.md) guide for full visual customisation options. ## 5. Core Engine Features Fine-tune how the parser processes your content files. ```json "docmd.config.json" { "minify": true, "autoTitleFromH1": true, "copyCode": true, "pageNavigation": true, "markdown": { "breaks": true } } ``` | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `minify` | `Boolean` | `true` | Compresses output HTML and JS structures for maximum speed. | | `autoTitleFromH1` | `Boolean` | `true` | Resolves missing page titles using the first H1 header in the file. | | `copyCode` | `Boolean` | `true` | Displays a "Copy Code" button on the top-right of syntax blocks. | | `pageNavigation` | `Boolean` | `true` | Adds "Previous" and "Next" page links at the bottom of every page based on the navigation order. | | `markdown.breaks` | `Boolean` | `true` | Standardises line breaks. Set to `false` if you wrap markdown lines at 80 columns. | ::: callout warning "Standalone editLink Deprecated" icon:alert-triangle The standalone `editLink` configuration is deprecated. Use the core [Git plugin](../plugins/git.md) instead. It provides identical edit link functionality alongside commit timestamps and metadata logs. ::: --- ## [Redirects & 404](https://docs.docmd.io/configuration/redirects/) --- title: "Redirects & 404" description: "Configure metadata-based redirects and custom branded 404 error pages for static deployments." --- Static hosting environments lack server-side logic (like Nginx rules) for dynamic routing. docmd generates native HTML failsafes to handle redirection and error states automatically. ## Server-less Redirects Forward traffic from old URLs to new destinations by defining mappings in the `redirects` object. ```json "docmd.config.json" { "redirects": { "/setup": "/getting-started/installation", "/v1/api": "/api-reference" } } ``` ### Technical Implementation When you define a redirect, the engine creates an `index.html` file at the old path containing a `<meta http-equiv="refresh">` tag. This strategy ensures: 1. **Seamless Redirection**: Users forward to the new destination instantly. 2. **SEO Preservation**: Search engines recognise the redirection to maintain link equity. 3. **Analytics Tracking**: Page views register before the redirect occurs. ## Branded 404 Pages When users request a missing URL, static hosts automatically load a root `404.html` file. docmd generates this file by default. It inherits your site's theme, sidebar, and SPA functionality perfectly. ### Customising Error Content Personalise the 404 error message in your configuration: ```json "docmd.config.json" { "notFound": { "title": "404: Page Not Found", "content": "We couldn't find the page you're looking for. Use the sidebar to find your way back." } } ``` ::: callout tip "Local Development" icon:lightbulb The development server automatically serves your custom 404 page for missing files. Test the error experience locally. ::: --- ## [Site Banner](https://docs.docmd.io/configuration/site-banner/) --- title: "Site Banner" description: "Site-wide announcement banner. Sits above the menubar, supports inline markdown, optional icon, CTA link, and per-session dismissal." --- # Site Banner > **New in 0.8.7.** A dismissable announcement banner built into the default UI. Sits above the menubar and below the page header. **Opt-in** — nothing is rendered unless you set `config.layout.banner`. Use it for release announcements, maintenance windows, beta calls-to-action, or any other site-wide message. ## Enable in 30 seconds ```json "docmd.config.json" { "layout": { "banner": { "content": "**v0.9 ships Friday** — read the announcement.", "type": "info", "dismissible": true, "link": { "text": "Read more", "url": "/blog/v0-9" } } } } ``` The banner appears on every page. Users who close it once won't see it again until the next browser session. ## Configuration reference | Field | Default | Description | |---|---|---| | `content` | `""` | Inline markdown text (`**bold**`, `` `code``). Mutually exclusive with `html`. | | `html` | `""` | Raw HTML. Takes precedence over `content`. Use for richer layouts. | | `type` | `"info"` | `"info"` \| `"success"` \| `"warning"` \| `"danger"` — affects background tint. | | `dismissible` | `true` | Show a close (X) button. When `false`, the banner is permanent. | | `link` | `null` | `{ text, url }` for an optional CTA link rendered after the content. | | `icon` | `null` | Lucide icon name shown on the left. Common picks: `megaphone`, `info`, `bell`. | ### Examples Plain announcement: ```json "docmd.config.json" { "layout": { "banner": { "content": "Site maintenance scheduled for Sunday 02:00–04:00 UTC.", "type": "warning" } } } ``` Success / release: ```json "docmd.config.json" { "layout": { "banner": { "content": "**v1.0 is out!** Read the release notes.", "type": "success", "icon": "party-popper", "link": { "text": "Release notes", "url": "/blog/v1-0" } } } } ``` Rich HTML (escape carefully): ```json "docmd.config.json" { "layout": { "banner": { "html": "<strong>New:</strong> AI-powered search is here. <a href=\"/blog/ai-search\">Learn more →</a>", "type": "info", "dismissible": false } } } ``` ## Behaviour - **Position** — Sits at the very top of the page, above the menubar and sidebar logo bar. CSS-only positioning, no layout shift when dismissed. - **Dismissal persistence** — The "dismissed" state is stored in `sessionStorage`. A fresh browser session re-shows the banner. If you need longer persistence, write to `localStorage` from your own client-side script — the banner's `data-docmd-banner` attribute makes it easy to find. - **Per-page override** — Not yet supported in 0.8.7. To hide the banner on a single page, set `layout.banner: null` in a `config.templates[page]` entry (planned for a follow-up). ## Re-styling The banner is built from BEM-style classes on the `.docmd-banner` root. Re-skin it via `customCss`: ```css .docmd-banner--info { background: linear-gradient(90deg, #fef3c7 0%, #fff 100%); border-bottom: 2px solid #f59e0b; } .docmd-banner__link { font-weight: 600; } ``` ## Disabling To remove the banner globally, set `layout.banner` back to `null` (or remove the key). To hide it on a single page, use the planned per-page override or render `null` in a `frontmatter` (post-0.8.7). ::: callout tip "Combine with a changelog template" Pair the banner with a `template-changelog` package to give your users a permanent record of every release you announce. ::: --- ## [Versioning](https://docs.docmd.io/configuration/versioning/) --- title: "Versioning" description: "Enable multi-version documentation with seamless switching, sticky path preservation, and isolated build directories." --- docmd features a native Versioning Engine. Manage and serve multiple versions of your project simultaneously. The engine automatically handles URL routing, sidebar updates, and switching logic. ## Directory Organisation Organise your documentation into versioned source folders. A common pattern keeps the active version in `docs/` and archived versions in directories prefixed with `docs-`. ```text my-project/ ├── docs/ # Latest Version (Main) ├── docs-v1/ # Legacy Version ├── docmd.config.json ``` ## Configuration <img width="500" class="with-border" src="/assets/previews/menu-versioning.webp"> Define your versions within the `versions` object: ```json "docmd.config.json" { "versions": { "current": "v2", "position": "sidebar-top", "all": [ { "id": "v2", "dir": "docs", "label": "v2.x (Latest)" }, { "id": "v1", "dir": "docs-v1", "label": "v1.x" } ] } } ``` ## Core Features ### 1. Root SEO (The "Current" Version) The `current` version generates directly at your output root (e.g., `mysite.com/`). This ensures search traffic always lands on your most up-to-date documentation. ### 2. Isolated Sub-directories Non-current versions build automatically into subfolders matching their `id`. * `v2 (Current)` → `mysite.com/` * `v1` → `mysite.com/v1/` ### 3. Sticky Switching (Path Preservation) docmd preserves the relative path when users switch versions. If a user reads `mysite.com/getting-started` and switches to **v1**, they automatically redirect to `mysite.com/v1/getting-started` (if the page exists). ### 4. Asset Isolation Each version inherits your global `assets/` directory. docmd isolates them during the build to prevent style leakage or conflicts. ### 5. Versioned Navigation Each version can maintain an independent navigation structure. docmd uses a cascading priority system to resolve the sidebar. See [Navigation Configuration](navigation.md) for details on the resolution hierarchy. ## Best Practices 1. **Semantic IDs**: Use concise, URL-friendly IDs like `v1`, `v2`, or `beta`. 2. **Navigation Parity**: Maintain consistent folder structures across versions to maximise "Sticky Switching". 3. **Unified Configuration**: Do not create separate config files for each version. docmd processes all versions in a single pass. --- ## [Workspaces](https://docs.docmd.io/configuration/workspaces/) --- title: "Workspaces" description: "Build multiple independent documentation projects from a single docmd instance, with global configuration cascading and a built-in Project Switcher." --- Workspaces let you build and deploy multiple documentation projects from one repository. Each project keeps its own configuration. Global settings defined at the workspace root cascade automatically into every project. ```text docs.example.com/ → Main documentation docs.example.com/sdk/ → SDK reference docs.example.com/cli/ → CLI documentation ``` ## Setup ### 1. Directory Structure One directory per project. Shared assets and global configuration live at the repository root. ```text my-docs/ ├── assets/ ← shared assets (all projects inherit these) ├── main-docs/ │ ├── docmd.config.json ← project config (overrides root defaults) │ └── docs/ ← project content ├── sdk-docs/ │ ├── docmd.config.json │ └── docs/ ├── docmd.config.json ← workspace root config └── package.json ``` ### 2. Root Workspace Config The root `docmd.config.json` uses the `workspace` key. Any top-level keys (e.g. `theme`, `menubar`, `logo`) act as **global defaults** for every project. ```json "docmd.config.json" { "workspace": { "projects": [ { "prefix": "/", "src": "main-docs", "title": "Docs" }, { "prefix": "/sdk", "src": "sdk-docs", "title": "SDK Reference" } ], "switcher": { "enabled": true, "position": "sidebar-top" } }, "theme": { "name": "default", "appearance": "system" }, "logo": { "light": "assets/logo-dark.svg", "dark": "assets/logo-light.svg" }, "menubar": [ { "text": "GitHub", "url": "https://github.com/my-org/my-repo", "external": true } ] } ``` #### `workspace` Options | Key | Type | Description | | :-- | :--- | :---------- | | `projects` | `Array` | List of project entries. At least one must use `prefix: "/"`. | | `switcher` | `Object` | Controls the [Project Switcher](#project-switcher) visibility and position. | #### Project Entry Fields | Key | Type | Required | Description | | :-- | :--- | :------- | :---------- | | `prefix` | `String` | ✅ | URL prefix. Use `"/"` for the root project. | | `src` | `String` | ✅ | Directory path (relative to CWD) containing the project's content and optional `docmd.config.json`. | | `title` | `String` | - | Display name shown in the Project Switcher UI. | ### 3. Project-Level Config Each project directory can have its own `docmd.config.json`. Settings defined here **override** the workspace root defaults. ```json "docmd.config.json" { "title": "SDK Reference", "src": "docs", "plugins": { "search": {}, "openapi": {} } } ``` If no local config file is found, the engine applies zero-config auto-routing using the workspace defaults. ### 4. Global Configuration Cascading Any key defined in the root workspace config automatically applies to every project. Project configs can selectively override any of these globals. | Layer | Precedence | | :---- | :--------- | | Root workspace config | Lowest (applied first as defaults) | | Project `docmd.config.json` | Higher (overrides root defaults) | | Project `navigation.json` | Highest (always wins for navigation) | **Example**: Define your global `theme` and `menubar` once at the root. Each project only needs to set `title`, `src`, and its own `plugins`. ::: callout info "Navigation Priority" icon:info A project-level `navigation.json` file **always takes precedence** over any `navigation` array defined in the workspace root config. If neither exists, docmd falls back to automatic directory scanning. ::: ## Project Switcher The Project Switcher renders a slim UI component for navigating between workspace projects. ### Configuration ```json "docmd.config.json" { "workspace": { "switcher": { "enabled": true, "position": "sidebar-top" } } } ``` | Position | Description | | :------- | :---------- | | `sidebar-top` (default) | Pinned at the top of the sidebar, above navigation. | | `sidebar-bottom` | Pinned at the bottom of the sidebar. | | `options-menu` | Integrated into the header options menu alongside search and theme toggles. | The switcher only renders when two or more projects are defined. ## Assets ### Shared Assets Place logos, favicons, and global CSS in the root `assets/` directory. The engine copies these into every project's output automatically during both `dev` and `build`. ### Project-Specific Assets Each project can have its own `assets/` directory. Project assets take priority over shared assets when filenames conflict. ## Building & Development ### Dev Server ```bash npx @docmd/core dev ``` Builds all projects and serves them from a single port. File changes trigger **targeted, per-project** rebuilds - only the modified project re-renders, not the whole workspace. Root config changes trigger a full workspace rebuild. ### Production Build ```bash npx @docmd/core build ``` Outputs a single static directory. All projects merge into their respective subpaths. No reverse proxy or complex CI pipelines are required. ## Rules & Constraints 1. **Root Project Required**: Exactly one project must have `prefix: "/"`. 2. **Unique Prefixes**: Every project must use a unique URL prefix. 3. **`out` in Root Only**: Only the root workspace config controls the output directory. Child project configs must not define `out`. 4. **No Prefix Conflicts**: If a root project has a folder named `sdk/`, and another project uses `prefix: "/sdk"`, the engine emits a conflict warning. The prefixed project always wins. ## Migrating from Legacy Configurations The pre-0.8.3 `projects` array syntax and other legacy configuration keys are automatically normalised to the modern `workspace` schema for backward compatibility. While manual updates are strictly not required, you can automatically upgrade your configuration file to the modern schema using the CLI. ::: callout tip "Migrate with one command" icon:lightbulb Run `npx @docmd/core migrate --upgrade` to automatically rewrite your root configuration to the current schema. ::: --- ## [Zero-Config](https://docs.docmd.io/configuration/zero-config/) --- title: "Zero-Config" description: "Understand the heuristics engine of docmd that automatically structures your site without files." --- `docmd` features a smart heuristics engine designed to parse and structure your documentation automatically. You can start building, serving, and translating your documentation without writing a single line of configuration. ## How It Works When run without a `docmd.config.json` file, the engine automatically triggers **Zero-Config Mode**. It scans the workspace directory for content and applies the following heuristics: ### 1. Source Directory Detection The engine looks for documentation files in these candidate directories in order: 1. `docs/` 2. `src/docs/` 3. `documentation/` 4. `content/` 5. `.` (Root directory fallback) If one of the candidate directories is found and contains Markdown files, it is selected as the source. If no directory is found, but the project root has Markdown files, the root directory is used (automatically ignoring `node_modules`, `.git`, output folders like `site/`, `dist/`, and `out/`). If no documentation content is found at all, `docmd` initializes a fresh starter structure automatically. ### 2. Heuristics for Versions and Locales The folder structure is scanned to dynamically extract versioning and localization metadata: - **Versions**: Subdirectories matching `v[0-9]+` (e.g., `v1.0`, `v08`) are parsed as documentation versions. - **Locales**: Subdirectories with two-letter language codes (e.g., `en`, `de`, `zh`) are treated as localized variants. - **Structure Extraction**: The highest version is designated as the current release, and the first locale found (prioritizing `en` if present) is set as the default language. ### 3. Automatic Navigation Routing If there are no root-level versions or locales, the engine builds a navigation tree dynamically by analyzing the file structure: - Subdirectories are mapped to navigation groups. - Titles are generated dynamically from file basenames. E.g., `getting-started.md` is formatted as `Getting Started`. - Index files (`index.md`, `README.md`) are routed as the landing page of the current directory. ## Zero-Config Best Practices To get the most out of Zero-Config mode, follow these structure recommendations: - **Explicit file naming**: Use clear, hyphenated or camelCase file names. The autoloader converts them to readable titles. - **Folder-based sections**: Place related documents inside subfolders to automatically group them in the sidebar. - **Index fallback**: Always place an `index.md` or `README.md` at the root of your source folder to serve as the landing page. - **Clean output path**: If you are using the root folder `.` as your source, keep your built assets in the default `site/` folder which is automatically ignored. ## Built-in Defaults (new in 0.8.7) A `docmd.config.json` (or no config at all) gives you a usable site out of the box. The following keys ship with sensible defaults, so you only need to set them when you want a different value. ::: callout info "How to opt out" Set the key to `false` (or the appropriate empty value) to disable a default. For example, `pageNavigation: false` removes prev/next links; `theme.appearance: "dark"` overrides the colour mode. ::: ### Top-level QoL defaults | Key | Default | Notes | |---|---|---| | `pageNavigation` | `true` | prev/next links at the bottom of each article | | `copyCode` | `true` | copy-code buttons on `<pre>` blocks | | `autoTitleFromH1` | `true` | use the first `# H1` as the page title when frontmatter is absent | ### Layout & sidebar defaults | Key | Default | Notes | |---|---|---| | `layout.spa` | `true` | SPA navigation between pages | | `layout.breadcrumbs` | `true` | breadcrumb row above the page header | | `layout.header.enabled` | `true` | top page header | | `layout.sidebar.collapsible` | `true` | sidebar can collapse on desktop | | `layout.sidebar.defaultCollapsed` | `false` | sidebar starts expanded | | `layout.optionsMenu.position` | `"header"` | options menu (search / theme switch / sponsor) goes in the header | | `layout.optionsMenu.components.search` | `true` | search trigger in the menu | | `layout.optionsMenu.components.themeSwitch` | `true` | light/dark toggle in the menu | | `layout.optionsMenu.components.sponsor` | `null` | opt-in — set to a URL to enable | ### Footer defaults | Key | Default | Notes | |---|---|---| | `layout.footer.style` | `"minimal"` | one-line footer bar | | `layout.footer.copyright` | `` `© ${new Date().getFullYear()}` `` | auto-generated current-year copyright | | `layout.footer.branding` | `true` | show "Built with docmd" by default | ### Theme defaults | Key | Default | Notes | |---|---|---| | `theme.name` | `"default"` | base CSS theme; reserved values: `default`, `sky`, `ruby`, `retro`. Any other value is auto-promoted to a [template name](../theming/templates.md). | | `theme.appearance` | `"system"` | default colour mode (follows `prefers-color-scheme`). Set to `"light"` or `"dark"` to force. | | `theme.codeHighlight` | `true` | syntax highlighting on `<pre>` blocks | ### New opt-in features (off by default) | Key | Default | Notes | |---|---|---| | `cookie` | `null` | opt-in cookie consent dialog — see [Cookie Consent](cookie-consent.md) | | `layout.banner` | `null` | opt-in site-wide announcement banner — see [Site Banner](site-banner.md) | | `theme.template` | `null` | opt-in template selection — see [Templates](../theming/templates.md) | The defaults were chosen to give brand-new sites a usable look and feel without any config. Older configs keep their explicit values untouched — only `undefined` keys are filled in. --- ## [Buttons](https://docs.docmd.io/content/containers/buttons/) --- title: "Buttons" description: "Inject clear, highly visible call-to-actions directly into your documentation." --- Buttons are interactive components designed for navigation and call-to-actions. They can point to internal documentation pages or external resources. ## Syntax Reference ```markdown ::: button "Label text" target_url [property:value...] ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Path** | `/path/` | Relative project URL. Resolves automatically for SPA navigation. | | **External** | `external:URL`| Opens the target URL in a new browser tab (`target="_blank"`). | | **Colour** | `color:VALUE` | Applies a background colour (supports CSS names or Hex codes). | | **Icon** | `icon:NAME` | Adds a [Lucide](external:https://lucide.dev/icons) icon before the label. | ## Examples ### Internal Navigation Use relative Markdown paths to ensure seamless transitions within the docmd SPA. ```markdown ::: button "Install docmd" ../../getting-started/installation.md ``` ::: button "Install docmd" ../../getting-started/installation.md ### External Resource Link Prepend `external:` to the URL to force the link to open in a new tab. ```markdown ::: button "View GitHub Repository" external:https://github.com/docmd-io/docmd ``` ::: button "View GitHub Repository" external:https://github.com/docmd-io/docmd ### Styling & Icons Match buttons to your brand identity using colour overrides and Lucide icons to enhance visual clarity. ```markdown ::: button "Success Confirmation" ./#success color:#228B22 ::: button "Danger Action" ./#delete color:crimson icon:alert-circle ::: button "View Source" external:https://github.com/docmd-io/docmd icon:github ``` ::: button "Success Confirmation" ./#success color:#228B22 ::: button "Danger Action" ./#delete color:crimson icon:alert-circle ::: button "View Source" external:https://github.com/docmd-io/docmd icon:github ## Critical Note: Self-Closing Logic Buttons are self-closing. Adding a terminal `:::` line immediately after a button will terminate the **parent container** (e.g., a Card or Tab), potentially breaking your layout. **Incorrect Sequence:** ```markdown ::: card "Setup" ::: button "Begin" ../../setup.md ::: <-- Error: This closes the Card prematurely. ::: ``` **Correct Sequence:** ```markdown ::: card "Setup" ::: button "Begin" ../../setup.md ::: <-- Correct: This closes the Card cleanly. ``` --- ## [Callouts](https://docs.docmd.io/content/containers/callouts/) --- title: "Callouts" description: "Highlight critical warnings, pro-tips, and background context using semantic visual blocks." --- Callouts isolate information that requires the reader's immediate attention. docmd provides five semantic types, each with distinct styling and iconography. ::: callout info "Migration-Friendly Aliases" If migrating from VitePress or Docusaurus, you can use their native syntax: - `:::tip`, `:::warning`, `:::danger`, `:::info` (VitePress) - `:::note`, `:::caution` (Docusaurus) These aliases render identically to their docmd equivalents. Spaceless syntax like `:::callout` also works. ::: ## Syntax Reference ```markdown ::: callout type "Title text" [property:value...] The content or warning goes here. ::: ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Type** | `info` \| `tip` \| `warning` \| `danger` \| `success` | The semantic intent which defines default colours and iconography. | | **Title** | `"String"` | Optional. Overrides the default semantic label with a custom title. | | **Icon** | `icon:NAME` | Optional. Overrides the default icon with a custom [Lucide](external:https://lucide.dev/icons) icon. | ### Supported Types | Type | Visual Signal | | :--- | :--- | | `info` | Contextual background or helpful non-critical information. | | `tip` | Performance shortcuts or best practices. | | `warning` | Potential issues or deprecated features to monitor. | | `danger` | Risk of data loss, breaking changes, or critical failures. | | `success` | Confirmation of a successful configuration or build. | ## Examples ### Basic Callout A minimal callout without a title uses the type as its default label. ```markdown ::: callout info Legacy configuration schemas remain supported but are no longer recommended. ::: ``` ::: callout info Legacy configuration schemas remain supported but are no longer recommended. ::: ### Custom Title & Icon Override the default label and icon with a custom title and any Lucide icon name. ```markdown ::: callout warning "Breaking Change" icon:alert-triangle The internal WebSocket RPC system is officially deprecated. ::: ``` ::: callout warning "Breaking Change" icon:alert-triangle The internal WebSocket RPC system is officially deprecated. ::: ### Rich Content Composition Callouts support full Markdown. Embed code blocks and buttons directly within the alert. ````markdown ::: callout tip "Optimised Local Testing" icon:command Use the preserve flag to maintain build files during dev sessions: ```bash npx @docmd/core dev --preserve ``` ::: button "CLI Flag Reference" /cli-commands ::: ```` ::: callout tip "Optimised Local Testing" icon:command Use the preserve flag to maintain build files during dev sessions: ```bash npx @docmd/core dev --preserve ``` ::: button "CLI Flag Reference" ./#cli-commands ::: ::: callout tip "Prioritised Logic for AI" For LLMs, callouts act as **High-Priority Anchors**. Use `::: callout danger` to document breaking changes - this provides a clear signal that the AI model must prioritise that information. ::: --- ## [Cards](https://docs.docmd.io/content/containers/cards/) --- title: "Cards" description: "Organise information into framed, visually distinct containers. Perfect for feature grids and landing pages." --- Cards encapsulate related content into a distinct, bordered frame with an optional header, providing clear visual hierarchy for your documentation. ## Syntax Reference ```markdown ::: card "Title text" [property:value...] This is the primary content area of the card. ::: ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Title** | `"String"` | Optional header title rendered at the top of the card. | | **Icon** | `icon:NAME` | Optional. Adds a [Lucide](external:https://lucide.dev/icons) icon next to the header title. | ## Examples ### Feature Highlight Use a card to frame a single technical capability with a clear title and icon. ```markdown ::: card "Asynchronous Generation" icon:zap The core engine uses a non-blocking I/O pipeline, generating thousands of pages in milliseconds. ::: ``` ::: card "Asynchronous Generation" icon:zap The core engine uses a non-blocking I/O pipeline, generating thousands of pages in milliseconds. ::: ### Rich Content Cards accept any standard Markdown, including code blocks and buttons. ````markdown ::: card "Instant Localisation" Prepare your documentation for a global audience using the built-in i18n support. ```bash docmd add i18n ``` ::: button "L10n Strategy Guide" /guides/localization ::: ```` ::: card "Instant Localisation" Prepare your documentation for a global audience using the built-in i18n support. ```bash docmd add i18n ``` ::: button "L10n Strategy Guide" ./#localization ::: ### Multi-Column Layout Wrap multiple cards inside a `grids` container for a responsive multi-column layout. ```markdown ::: grids ::: grid ::: card "Primary Node" Configuration for the master instance. ::: ::: ::: grid ::: card "Secondary Node" Configuration for redundant slave instances. ::: ::: ::: ``` ::: grids ::: grid ::: card "Primary Node" Configuration for the master instance. ::: ::: ::: grid ::: card "Secondary Node" Configuration for redundant slave instances. ::: ::: ::: ::: callout tip "Semantic Clustering for AI" icon:lightbulb In the `llms-full.txt` stream, content wrapped in a `card` is treated by AI agents as a **Cohesive Topic Cluster**. Utilising cards to segment unrelated concepts prevents context leakage and ensures LLM-generated summaries remain logically isolated. ::: --- ## [Changelogs](https://docs.docmd.io/content/containers/changelogs/) --- title: "Changelogs" description: "Generate structured, timeline-based version history and release notes." --- The `changelog` container provides a specialised layout for documenting project evolution. It parses version or date headers into a vertical timeline, ensuring historical updates are easily scannable. ## Syntax Reference ```markdown ::: changelog == Label Text Description of the entry goes here. ::: ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Entry Marker** | `==` | The delimiter that defines a new timeline entry within the changelog. | | **Label** | `String` | The text (e.g., version number or date) that renders as a timeline badge on the left. | ## Examples ### Release History Changelogs support rich Markdown within each entry, including lists, callouts, and code blocks. ```markdown ::: changelog == v2.0.0 (2026-03-15) ### Major System Overhaul The core engine has been rearchitected for isomorphic execution. * Implemented **SPA Router** for zero-reload navigation. * Introduced the **Isomorphic Plugin** system. ::: callout success This release offers a 40% improvement in initial build speed. ::: == v1.5.1 (2025-12-10) ### Security Patch * Resolved high-severity vulnerability in the internal parser. * Updated dependency `flatted` to `v3.3.2`. == v1.0.0 (2024-05-01) Initial public release. ::: ``` ::: changelog == v2.0.0 (2026-03-15) ### Major System Overhaul The core engine has been rearchitected for isomorphic execution. * Implemented **SPA Router** for zero-reload navigation. * Introduced the **Isomorphic Plugin** system. ::: callout success This release offers a 40% improvement in initial build speed. ::: == v1.5.1 (2025-12-10) ### Security Patch * Resolved high-severity vulnerability in the internal parser. * Updated dependency `flatted` to `v3.3.2`. == v1.0.0 (2024-05-01) Initial public release. ::: ::: callout tip "Historical Context for AI" Changelogs provide a temporal map for AI agents. The `::: changelog` structure allows an LLM to accurately parse when specific features or security fixes were introduced in the `llms.txt` context stream. ::: --- ## [Collapsible Sections](https://docs.docmd.io/content/containers/collapsible/) --- title: "Collapsible Sections" description: "Embed interactive accordion-style toggles for FAQs, deep-dive content, and spoilers." --- The `collapsible` container creates an interactive, toggleable accordion. It is ideal for FAQs and detailed technical configuration, keeping secondary information accessible without cluttering the primary view. ::: callout info "VitePress Alias" If migrating from VitePress, use `:::details` as an alias for `:::collapsible`. Spaceless syntax like `:::collapsible` also works. ::: ## Syntax Reference ```markdown ::: collapsible [open] "Title text" [property:value...] Main content goes here. ::: ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Open State** | `open` | Optional. If provided, the section initialises in an expanded state. | | **Title** | `"String"` | The text rendered on the toggle bar. Defaults to "Click to expand". | | **Icon** | `icon:NAME` | Optional. Adds a [Lucide](external:https://lucide.dev/icons) icon before the title text. | ## Examples ### Default State A collapsible section is closed by default. Ideal for FAQs and reducing visual density. ```markdown ::: collapsible "How do I upgrade docmd?" Run `npm update -g @docmd/core` to fetch the latest stable engine. ::: ``` ::: collapsible "How do I upgrade docmd?" Run `npm update -g @docmd/core` to fetch the latest stable engine. ::: ### Initially Open Use the `open` flag for sections that should be visible by default but allow users to minimise them. ```markdown ::: collapsible open "Environment Prerequisites" 1. Node.js v18+ (LTS recommended) 2. PNPM package manager ::: ``` ::: collapsible open "Environment Prerequisites" 1. Node.js v18+ (LTS recommended) 2. PNPM package manager ::: ### Rich Content Collapsibles can contain any Markdown, including syntax-highlighted code blocks. ````markdown ::: collapsible "Sample JSON Response" ```json { "status": "success", "data": { "version": "0.8.2" } } ``` ::: ```` ::: collapsible "Sample JSON Response" ```json { "status": "success", "data": { "version": "0.8.2" } } ``` ::: ::: callout tip Content inside a `collapsible` is fully indexed by search and included in the `llms.txt` stream. AI agents can answer questions based on hidden technical details while keeping the human-facing interface clean. ::: --- ## [URL Embeds](https://docs.docmd.io/content/containers/embed/) --- title: URL Embeds description: Safely embed dynamic video, social, and interactive content directly into your documents. --- docmd ships natively with the highly-optimised **[embed-lite](external:https://github.com/mgks/embed-lite)** parser. It transforms external URLs into secure, zero-latency UI components automatically. ## Supported Platforms The engine natively supports structured formatters for the following networks: * **Video:** YouTube (including Shorts), Vimeo, Dailymotion, TikTok * **Social:** X (Twitter), Reddit, Instagram, Facebook, LinkedIn * **Code & Prototyping:** GitHub Gists, CodePen, Figma, Google Maps * **Music:** Spotify, SoundCloud ## Syntax Reference ```markdown ::: embed "target_url" ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **URL** | `"String"` | The absolute URL of the external resource to embed (e.g., a YouTube video, Figma file, or GitHub Gist). | ## Examples ### Video Embed Paste any YouTube, Vimeo, or TikTok URL to render a native, responsive player. ```markdown ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ``` ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ### Fallback Behaviour If the parser encounters an unsupported or invalid URL, docmd gracefully falls back to a hyperlink button rather than breaking the page. ```markdown ::: embed "https://docs.docmd.io/content/containers/embed/" ``` ::: embed "https://docs.docmd.io/content/containers/embed/" --- ## [Grids](https://docs.docmd.io/content/containers/grids/) --- title: "Grids" description: "Organise layout into auto-adjusting responsive columns without writing HTML." --- Grids provide a native, Markdown-driven layout system. Use the `grids` container to structure elements side-by-side. Columns automatically fill available space and stack vertically on smaller screens. ## Syntax Reference ```markdown ::: grids ::: grid Content for the first column. ::: ::: grid Content for the second column. ::: ::: ``` | Container | Description | | :--- | :--- | | **`::: grids`** | The parent container that initiates the responsive flexbox layout. | | **`::: grid`** | Each child `grid` block acts as an individual column. Add as many as needed. | ## Examples ### Side-by-Side Cards Combine `grids` with `cards` to display multiple features in a clean, responsive layout. ```markdown ::: grids ::: grid ::: card "Speed" icon:zap Built on a non-blocking I/O pipeline for maximum performance. ::: ::: ::: grid ::: card "Scalability" icon:layers Designed for massive monorepos and extensive project structures. ::: ::: ::: ``` ::: grids ::: grid ::: card "Speed" icon:zap Built on a non-blocking I/O pipeline for maximum performance. ::: ::: ::: grid ::: card "Scalability" icon:layers Designed for massive monorepos and extensive project structures. ::: ::: ::: ### Three-Column Layout Add a third `grid` block to create a three-column row. Columns automatically balance their widths. ```markdown ::: grids ::: grid ::: card "Search" icon:search Client-side full-text search powered by MiniSearch. ::: ::: ::: grid ::: card "i18n" icon:globe First-class locale routing and translated search indexes. ::: ::: ::: grid ::: card "Themes" icon:palette Built-in dark mode and full CSS variable customisation. ::: ::: ::: ``` ::: grids ::: grid ::: card "Search" icon:search Client-side full-text search powered by MiniSearch. ::: ::: ::: grid ::: card "i18n" icon:globe First-class locale routing and translated search indexes. ::: ::: ::: grid ::: card "Themes" icon:palette Built-in dark mode and full CSS variable customisation. ::: ::: ::: ::: callout tip "Semantic Layouts" The `grids` container keeps your structure purely in Markdown. This results in cleaner source files and ensures LLMs interpret structural relationships accurately. ::: --- ## [Hero Sections](https://docs.docmd.io/content/containers/hero/) --- title: "Hero Sections" description: "Build high-impact landing page headers and marketing highlights purely in Markdown." --- The `hero` container creates visually striking landing page headers. It handles complex layouts including splits, glow effects, and sliders without requiring custom HTML. ## Syntax Reference ```markdown ::: hero [property:value...] # Page Title A short supporting tagline. ::: button "Call to Action" /target-url ::: ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Layout** | `layout:split` \| `layout:slider` | `split` divides the hero into a text area and a side media area. `slider` creates a horizontal scroll-snap carousel. | | **Glow** | `glow:true` | Injects a subtle radial gradient glow in the background. | | **Side Separator** | `== side` | Used with `layout:split`. Everything after this delimiter renders in the secondary (right-hand) area. | | **Slide Separator** | `== slide` | Used with `layout:slider`. Each `== slide` defines a new carousel panel. | ## Examples ### Split Layout Use the `== side` separator to divide content into a primary text area and a secondary media area. ```markdown ::: hero layout:split glow:true # docmd Isomorphic execution. AI-optimised. ::: button "Quickstart" ../../getting-started/quick-start.md color:blue == side ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ::: ``` ::: hero layout:split glow:true # docmd Isomorphic execution. AI-optimised. ::: button "Quickstart" ../../getting-started/quick-start.md color:blue == side ::: embed "https://www.youtube.com/watch?v=0CSyIBHQy9g" ::: ### Slider Layout Use `== slide` separators to build an auto-advancing carousel of content panels. ```markdown ::: hero layout:slider == slide # Isomorphic Core The engine renders everywhere. == slide # AI Optimisation Built for the LLM era. ::: ``` ::: hero layout:slider == slide # Isomorphic Core The engine renders everywhere. == slide # AI Optimisation Built for the LLM era. ::: ::: callout tip "Best Practices" Use `glow:true` sparingly on dark mode sites for a premium feel. Place `::: button` elements in the primary text section, before `== side`, to ensure they remain visible on mobile screens. ::: --- ## [Custom Interactive Containers](https://docs.docmd.io/content/containers/) --- title: "Custom Interactive Containers" description: "A comprehensive directory of the interactive UI building blocks available in docmd." --- Standard Markdown excels at basic text formatting, but professional technical documentation requires rich structural components to effectively communicate complex logic. `docmd` extends Markdown with a suite of **isomorphic containers** that render into responsive, high-fidelity UI elements. ::: callout tip "Migrating from Other Documentation Engines?" `docmd` supports syntax aliases from **VitePress** and **Docusaurus** out of the box. Containers like `:::tip`, `:::warning`, `:::note`, `:::details`, and `:::caution` work without modification. Spaceless syntax (e.g., `:::tabs` instead of `::: tabs`) is also supported for all containers. ::: ## Block Syntax Reference All containers utilise a consistent block syntax, ensuring a predictable authoring experience across your entire project. ```markdown ::: type "Optional Header Title" This is the primary content area. It supports **Markdown**, imagery, and deep component nesting. ::: ``` | Component | Keyword | Primary Use Case | | :--- | :--- | :--- | | **[Callouts](callouts.md)** | `callout` | Semantic highlights for tips, warnings, and alerts. | | **[Cards](cards.md)** | `card` | Framed structural blocks for feature grids and layout control. | | **[Grids](grids.md)** | `grids` | Auto-adjusting multi-column structural groups. | | **[Tabs](tabs.md)** | `tabs` | Interactive switchable panes for alternative platform instructions. | | **[Steps](steps.md)** | `steps` | Visual numbered timelines for how-to guides and tutorials. | | **[Collapsibles](collapsible.md)** | `collapsible` | Interactive accordion toggles for FAQs and deep-dive technical data. | | **[Buttons](buttons.md)** | `button` | Self-closing, prominent call-to-action navigation links. | | **[Tags](tags.md)** | `tag` | Self-closing, coloured labels for versions, statuses, or inline highlights. | | **[Hero](hero.md)** | `hero` | High-impact landing page sections with layout and slider support. | | **[URL Embeds](embed.md)** | `embed` | Secure, zero-latency embeds for video, social, and interactive content. | | **[Changelogs](changelogs.md)** | `changelog` | Structured, timeline-based version history and release notes. | | **[Nested Containers](nested-containers.md)** | - | Recursive composition patterns for complex, multi-component layouts. | ## The Strategic Importance of Containers Containers facilitate more than visual polish; they provide high-fidelity **Semantic Signals** to the `docmd` engine and downstream AI agents: 1. **AI Context Mapping**: Marking a block as a `callout warning` explicitly tells LLMs to prioritise that information during its reasoning and generation phases. 2. **Structural Integrity**: Combining `cards` with standard CSS allows for the creation of sophisticated landing pages without ever leaving the Markdown environment. 3. **Source Maintainability**: Eliminates "HTML Bloat" in your documentation source, keeping your `.md` files clean and machine-readable. ## Recursive Composition `docmd` supports **Infinite Nesting Depth**. You can compose any container within another to build complex, interactive documentation nodes purely in Markdown. ```markdown ::: card "Architecture Overview" ::: callout info This module utilises an asynchronous I/O pipeline. ::: ::: button "Deep Explore Core Engine" /advanced/developer-guide ::: ``` [Master the Nesting Guide](nested-containers.md) --- ## [Nested Containers](https://docs.docmd.io/content/containers/nested-containers/) --- title: "Nested Containers" description: "Use the recursive parser to combine cards, tabs, and callouts into high-fidelity page layouts." --- docmd uses a recursive parsing engine. You can nest components within each other to build complex, interactive documentation blocks without writing custom HTML. ::: callout warning "Self-Closing Buttons" The `::: button` component is self-closing (single line). Never add a terminal `:::` immediately after it - doing so closes the **parent container**, resulting in a broken layout. ::: ## Examples ### Interactive Resource Block Combine a **Card** for structural framing, **Tabs** for environment-specific instructions, and a **Callout** for critical information. ````markdown ::: card "Monorepo Quickstart" Choose your preferred initialisation path: ::: tabs == tab "Automated" ```bash pnpm onboard ``` ::: callout success This script handles all package installation and build tasks automatically. ::: == tab "Manual" Manually fetch and link the core engine. ::: button "Go to Developer Guide" ../../advanced/developer-guide.md ::: ::: ```` ### Platform-Specific Tutorial Steps Nesting **Tabs** inside **Steps** is a standard pattern for providing platform-specific instructions within a sequential tutorial. ```markdown ::: steps 1. **Environment Setup** Configure your local operating system. ::: tabs == tab "macOS" Ensure Homebrew is installed and up-to-date. == tab "Linux" Verify the presence of `curl` and `bash`. ::: 2. **Core Verification** Execute the version check to confirm connectivity. ::: ``` ::: steps 1. **Environment Setup** Configure your local operating system. ::: tabs == tab "macOS" Ensure Homebrew is installed and up-to-date. == tab "Linux" Verify the presence of `curl` and `bash`. ::: 2. **Core Verification** Execute the version check to confirm connectivity. ::: ## Design Constraints | Constraint | Note | | :--- | :--- | | **Recursive Tabs** | Nesting tabs within other tabs is technically supported but strongly discouraged - it creates confusing navigation on smaller viewports. | | **Sequential Conflict** | If you need numbered steps within a tab, use a standard ordered list rather than `::: steps` to avoid layout conflicts. | | **Indentation** | Indentation is not required by the parser, but 2 or 4-space indentation significantly improves source readability. | ::: callout tip "Knowledge Segmentation for AI" Nesting provides clear **Semantic Boundaries**. A `callout` nested within a `card` explicitly scopes that tip to the card's topic in the `llms.txt` stream, preventing context leakage across unrelated sections. ::: --- ## [Steps](https://docs.docmd.io/content/containers/steps/) --- title: "Steps" description: "Convert standard ordered lists into high-impact visual timelines and tutorials." --- The `steps` container transforms a standard Markdown ordered list into a numbered vertical timeline. It is designed for technical tutorials and sequential how-to guides. ::: callout info "Spaceless Syntax" Both `::: steps` and `:::steps` (spaceless) work natively. Use whichever style you prefer. ::: ## Syntax Reference ```markdown ::: steps 1. **Step Title** Step description goes here. 2. **Next Step** Continue the sequence. ::: ``` | Container | Description | | :--- | :--- | | **`::: steps`** | The parent container that transforms child ordered list items into a numbered timeline. | | **`1. `** | Any standard Markdown ordered list item acts as a chronological step. Bold the first line of each item to create a clear title. | ## Examples ### Basic Workflow A straightforward sequence for a common task. ```markdown ::: steps 1. **Initialise Project** Run `npx @docmd/core init` to scaffold your directory. 2. **Author Content** Write your documentation using standard Markdown files. 3. **Build & Deploy** Run `npx @docmd/core build` to generate your static site. ::: ``` ::: steps 1. **Initialise Project** Run `npx @docmd/core init` to scaffold your directory. 2. **Author Content** Write your documentation using standard Markdown files. 3. **Build & Deploy** Run `npx @docmd/core build` to generate your static site. ::: ### Steps with Rich Content Each step can contain code blocks, callouts, and other nested containers. ```markdown ::: steps 1. **Configure Environment** Define your project variables in `docmd.config.json`. ::: callout tip Use `defineConfig` to enable IDE autocompletion for all configuration keys. ::: 2. **Generate Production Build** Execute the build command to generate a highly optimised static site. ```bash npx @docmd/core build ``` 3. **Deploy to Infrastructure** Synchronise the `site/` directory with S3, Cloudflare Pages, or Vercel. ::: ``` ::: steps 1. **Configure Environment** Define your project variables in `docmd.config.json`. ::: callout tip Use `defineConfig` to enable IDE autocompletion for all configuration keys. ::: 2. **Generate Production Build** Execute the build command to generate a highly optimised static site. ```bash npx @docmd/core build ``` 3. **Deploy to Infrastructure** Synchronise the `site/` directory with S3, Cloudflare Pages, or Vercel. ::: ::: callout tip "Workflow Optimisation" icon:lightbulb AI models interpret the `steps` container as a signal for **Sequential Workflows**. Always start each list item with a **bolded title** - this allows agents to reliably parse the objective of each step from the `llms.txt` context. ::: --- ## [Tabs](https://docs.docmd.io/content/containers/tabs/) --- title: "Tabs" description: "Organise dense, alternative, or multi-language information into switchable interactive panes." --- Tabs present mutually exclusive or related data sets - such as "pnpm vs npm" or "macOS vs Windows". They condense information into a compact, interactive format. ::: callout info "Spaceless Syntax" Both `::: tabs` and `:::tabs` (spaceless) work natively. Use whichever style you prefer. ::: ## Syntax Reference ```markdown ::: tabs == tab "Label" [property:value...] Content for this tab. == tab "Another Label" Content for the second tab. ::: ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Label** | `"String"` | The text displayed on the tab trigger button. | | **Icon** | `icon:NAME` | Optional. Adds a [Lucide](external:https://lucide.dev/icons) icon before the label text. | ## Examples ### Package Manager Instructions Show installation commands for multiple package managers in a single compact block. ````markdown ::: tabs == tab "pnpm" ```bash pnpm add @docmd/core ``` == tab "npm" ```bash npm install @docmd/core ``` == tab "yarn" ```bash yarn add @docmd/core ``` ::: ```` ::: tabs == tab "pnpm" ```bash pnpm add @docmd/core ``` == tab "npm" ```bash npm install @docmd/core ``` == tab "yarn" ```bash yarn add @docmd/core ``` ::: ### Multi-Language Code Snippets Keep programming environments cleanly separated with tab icons for quick visual identification. ````markdown ::: tabs == tab "TypeScript" icon:hexagon ```typescript import { build } from '@docmd/core'; await build('./docmd.config.json'); ``` == tab "JavaScript" icon:braces ```javascript const { build } = require('@docmd/core'); build('./docmd.config.json'); ``` ::: ```` ::: tabs == tab "TypeScript" icon:hexagon ```typescript import { build } from '@docmd/core'; await build('./docmd.config.json'); ``` == tab "JavaScript" icon:braces ```javascript const { build } = require('@docmd/core'); build('./docmd.config.json'); ``` ::: ## Constraints | Constraint | Note | | :--- | :--- | | **Nesting Depth** | Tabs cannot nest inside other tab components. | | **Interactive Conflict** | Do not nest `::: steps` inside a tab. Use a standard ordered list instead. | | **Responsive Limit** | Limit tab counts to 6 per block for mobile compatibility. | | **State Persistence** | The active tab is tracked by the SPA router. Selecting "pnpm" on one page activates it on subsequent pages. | ::: callout tip "AI Context Mapping" Always include the target language or platform in the tab label (e.g., `== tab "TypeScript"`). This helps AI agents instantly identify the correct context stream without having to infer it from code content. ::: --- ## [Tags](https://docs.docmd.io/content/containers/tags/) --- title: "Tags" description: "Use the tag container to label versions, statuses, or highlight short text snippets inline." --- The `tag` container is a self-closing component that inserts small, pill-shaped badges inline. Tags retain their compact proportions everywhere - they do not inherit heading sizes or surrounding text styles. ## Syntax Reference ```markdown ::: tag "Label text" [property:value...] ``` | Parameter | Type | Description | | :--- | :--- | :--- | | **Label** | `"String"` | The text displayed inside the pill-shaped badge. | | **Colour** | `color:VALUE` | Applies a background colour (supports CSS names or Hex codes). Automatically calculates a contrasting text colour. | | **Icon** | `icon:NAME` | Adds a [Lucide](external:https://lucide.dev/icons) icon inside the badge. | | **URL** | `url:URL` | Makes the tag a clickable hyperlink. Prefix with `external:` to force a new tab. Matches the unquoted-URL convention used by [buttons](button). | ## Examples ### Version Badge Use a coloured tag inline to mark when a feature was introduced. ```markdown This feature was added in ::: tag "v0.8.2" color:blue and works perfectly. ``` This feature was added in ::: tag "v0.8.2" color:blue and works perfectly. ### Status Labels Use tags for status indicators across a page. Colours are fully customisable. ```markdown ::: tag "Deprecated" color:#ef4444 ::: tag "Beta" color:#eab308 ::: tag "Stable" color:#22c55e ::: tag "Verified" icon:check-circle color:#10b981 ``` ::: tag "Deprecated" color:#ef4444 ::: tag "Beta" color:#eab308 ::: tag "Stable" color:#22c55e ::: tag "Verified" icon:check-circle color:#10b981 ### Linked Tag Add `url:` to make a tag act as a hyperlink, useful for cross-referencing release notes or external resources. The value is unquoted to match the convention used by [buttons](buttons.md). ```markdown Check out the latest ::: tag "Release Notes" icon:external-link url:/release-notes/0-8-2.md ``` Check out the latest ::: tag "Release Notes" icon:external-link url:/release-notes/0-8-2.md ### External Link Prefix the URL with `external:` to force the link to open in a new tab, even when the target lives on your own domain. ```markdown ::: tag "GitHub" icon:github url:external:https://github.com/docmd-io/docmd ``` ::: tag "GitHub" icon:github url:external:https://github.com/docmd-io/docmd --- ## [Frontmatter Reference](https://docs.docmd.io/content/frontmatter/) --- title: "Frontmatter Reference" description: "The complete guide to page-level metadata and configuration." --- Frontmatter overrides global settings for specific pages. Write it in YAML format at the top of your Markdown files. ## Core Metadata | Key | Type | Description | | :--- | :--- | :--- | | `title` | `String` | **Required.** Sets the HTML `<title>` and the primary section header. | | `description` | `String` | Sets the meta description for SEO and search results. | | `keywords` | `Array` | A list of keywords for the `<meta name="keywords">` tag. | ::: callout warning "Title is Important" icon:triangle-alert The `title` field is strongly recommended. Without it, the engine falls back to the first `# H1` heading or the filename. This can produce less ideal search results. ::: ## Visibility & Indexing | Key | Type | Description | | :--- | :--- | :--- | | `noindex` | `Boolean` | Excludes the page from the internal search index. | | `llms` | `Boolean` | Set to `false` to exclude this page from AI context files (`llms.txt`). | | `hideTitle` | `Boolean` | Hides the title from the sticky header. Useful for custom H1s. | | `bodyClass` | `String` | Adds a custom CSS class to the `<body>` tag. | ## Layout Control | Key | Type | Description | | :--- | :--- | :--- | | `layout` | `String` | Set to `full` to use maximum width and hide the TOC sidebar. | | `toc` | `Boolean` | Set to `false` to disable the Table of Contents entirely. | | `noStyle` | `Boolean` | Disables the entire UI (Sidebar, Header, Footer) for custom pages. | | `titleAppend` | `Boolean` | Set to `false` to prevent appending the site title to metadata tags. Default is `true`. | ### `noStyle` Component Control When `noStyle: true` is active, you must opt-in to the components you wish to retain. ```yaml --- noStyle: true components: meta: true # Injects SEO metadata favicon: true # Injects site favicon css: true # Injects docmd-main.css theme: true # Injects theme-specific styling highlight: true # Injects syntax highlighting scripts: true # Injects the SPA router logic sidebar: true # Injects the navigation sidebar footer: true # Injects the site footer --- ``` ## Plugin Overrides ### SEO (`seo`) * `image`: Custom social share image URL for the page. * `aiBots`: Set to `false` to block AI crawlers from this page. * `canonicalUrl`: Sets a custom canonical link for SEO. --- ## [Live Preview](https://docs.docmd.io/content/live-preview/) --- title: "Live Preview" description: "Run the engine entirely in the browser without a backend server using the Live architecture." --- The compiler separates filesystem operations from core logic. The core engine can therefore run entirely in the browser, powering live editors and CMS previews without a Node.js backend. <img width="720" class="with-border" src="/assets/previews/live-editor-preview.webp"> ::: button "Open Live Editor" external:https://live.docmd.io ## The Live Editor The built-in Live Editor provides a high-performance, split-pane interface. Author your Markdown in the left pane. Watch the rendered output update and sync in real-time on the right. ### Local Execution Launch the Live Editor locally within your project: ```bash npx @docmd/core live ``` ### Static Distribution Generate a standalone, static version of the editor. Host it on platforms like Vercel or GitHub Pages: ```bash npx @docmd/core live --build-only ``` This generates a `dist/` directory. It contains the `index.html` entry point and the bundled `docmd-live.js` engine. ## Embedding @docmd/core Add the browser-compatible bundle to a third-party app to render Markdown on the client. ### 1. Resource Integration Include the CSS and JavaScript bundles from your assets or a CDN: ```html <link rel="stylesheet" href="/assets/css/docmd-main.css"> <script src="/docmd-live.js"></script> ``` ### 2. Isomorphic API The global `docmd` object exposes a `compile` method for instant rendering. ```javascript const html = await docmd.compile(markdown, { "title": "Dynamic Preview", "theme": { "appearance": "dark" } }); document.getElementById("preview-frame").srcdoc = html; ``` ::: callout tip "AI Feedback Loops" icon:sparkles The Live architecture is ideal for building **AI-Agent Sandboxes**. Pipe an agent's suggested changes to a live-compilation buffer. Visually verify AI suggestions before committing changes to your repository. ::: --- ## [docmd : Bespoke No-Style Page Demo](https://docs.docmd.io/content/no-style-example/) --- title: "docmd : Bespoke No-Style Page Demo" description: "A functional demonstration of the noStyle architectural feature." noStyle: true components: meta: true favicon: true css: true theme: true scripts: true mainScripts: true copyCode: true customHead: | <style> body { font-family: 'Inter', -apple-system, system-ui, sans-serif; margin: 0; padding: 0; line-height: 1.6; background: var(--bg-primary); color: var(--text-primary); } .demo-container { max-width: 900px; margin: 0 auto; padding: 80px 20px; } .demo-hero { text-align: centre; margin-bottom: 60px; } .demo-hero h1 { font-size: 3.5rem; margin-bottom: 20px; color: var(--brand-primary, #4a6cf7); } .demo-hero p { font-size: 1.25rem; color: var(--text-secondary); } .demo-card { background: var(--bg-secondary, #f8f9fa); padding: 40px; border-radius: 16px; border: 1px solid var(--border-colour); box-shadow: 0 4px 20px rgba(0,0,0,0.05); } .demo-button { display: inline-block; padding: 14px 28px; background-color: var(--brand-primary, #4a6cf7); color: white; text-decoration: none; border-radius: 8px; font-weight: 600; margin-top: 30px; transition: filter 0.2s ease; } .demo-button:hover { filter: brightness(1.1); } </style> --- <div class="demo-container"> <div class="demo-hero"> <h1>Bespoke Page Architecture</h1> <p>Demonstrating the absolute layout control enabled via <code>noStyle: true</code>.</p> </div> <div class="demo-card"> <h2>Logical Foundation</h2> <p> This demonstration utilises the <code>noStyle: true</code> frontmatter directive to bypass the global documentation layout (Sidebar, Header, and TOC). This provides a "Zero-Friction" canvas for creating marketing landing pages or custom product dashboards. </p> <h3>Enabled System Components</h3> <p>When in No-Style mode, you explicitly opt-in to the documentation engine's core features:</p> <ul> <li><strong>SEO Meta Engine</strong>: Structured tags and social graph data are retained.</li> <li><strong>Project Branding</strong>: Global favicon injection remains active.</li> <li><strong>Foundational Typography</strong>: The processed <code>docmd-main.css</code> provides base styling.</li> <li><strong>Theme Synchronisation</strong>: Light/Dark mode state is fully preserved.</li> <li><strong>Interactive Capabilities</strong>: The SPA router and component logic remain available.</li> </ul> <h3>Technical Implementation</h3> <p> The layout for this page is authored using standard HTML wrappers and scoped CSS defined within the <code>customHead</code> frontmatter field. This ensures zero CSS leakage to the rest of the documentation site. </p> <a href="/content/no-style-pages/" class="demo-button">Analyse the Implementation Guide →</a> </div> </div> --- ## [No-Style Pages](https://docs.docmd.io/content/no-style-pages/) --- title: "No-Style Pages" description: "Create custom landing pages and unique layouts by disabling the default docmd theme." --- docmd allows you to bypass the standard documentation layout (Sidebar, Header, Footer) on a per-page basis. This is ideal for creating landing pages or custom dashboards while retaining access to the engine's components. ## Enabling No-Style Mode To disable the global UI, add `noStyle: true` to the page's frontmatter. ```yaml --- title: "Product Showcase" noStyle: true components: meta: true # Retain SEO and OpenGraph tags favicon: true # Retain site favicon css: true # Inject docmd-main.css for typography --- <!-- Raw HTML or specialised Markdown goes here --> <div class="hero"> <h1>Next-Gen Documentation</h1> <p>Zero-config. Isomorphic. AI-Ready.</p> </div> ::: callout info "Infinite Nesting Support" icon:info Even with `noStyle: true`, all standard docmd containers like `::: card`, `::: tabs`, and `::: hero` are fully supported and can be nested infinitely. ::: ``` ## Component Opt-In When `noStyle` is active, you start with a blank canvas. Selectively re-enable core system components as needed: | Component | Description | | :--- | :--- | | `meta` | Injects `<title>`, SEO meta tags, and structured OpenGraph data. | | `favicon` | Injects the project-wide favicon. | | `css` | Injects `docmd-main.css`. Highly recommended for foundational grid and typography. | | `menubar` | Injects the site's top menubar. | | `theme` | Injects the active theme's CSS variables and appearance overrides. | | `scripts` | Injects interactive component logic (requires `mainScripts: true`). | | `spa` | Enables the single-page application router (requires `scripts: true`). | ## Composable Landing Pages The primary power of `noStyle` is using docmd components as high-fidelity "widgets" on a blank canvas. You aren't limited to raw HTML; you can build complex structural designs purely in Markdown. ### Building a Modern Entry Point ```yaml --- title: "Welcome" noStyle: true components: meta: true css: true menubar: true # Use the site's top navigation scripts: true # Enable interactive components mainScripts: true --- ::: hero layout:split glow:true # Build Documentation that Wows. The zero-config engine for modern engineering teams. ::: button "Get Started" ../getting-started/quick-start.md color:blue ::: button "GitHub" github:docmd-io/docmd color:gray == side ::: embed "https://www.youtube.com/watch?v=dQw4w9WgXcQ" ::: ::: ::: grids ::: card "Zero Configuration" Just write markdown. No complex React logic or build scripts. ::: ::: card "AI Optimised" Structure-aware parsing for the LLM era. ::: ::: card "Fast Without the Framework Tax" Static generation with isomorphic SPA navigation. ::: ::: ``` ::: callout tip "AI-Generated Layouts" icon:lightbulb Because `noStyle` pages support raw HTML alongside docmd containers, they are perfectly suited for **AI-driven UI design**. Prompt an AI: *"Design a modern hero section using utility classes and docmd buttons, wrapped in a noStyle container."* The AI can iterate within your static site pipeline with zero configuration. ::: ## String Replacement (i18n for noStyle) When your site has [i18n configured](../configuration/localisation/index.md), themed documentation pages get full server-side translations automatically. However, `noStyle` pages use custom HTML. docmd provides **string replacement** to translate HTML via `data-i18n` attributes and JSON translation files. ::: callout info "Why this only works for noStyle pages" icon:info String replacement finds elements with `data-i18n` attributes and swaps their text content. Standard Markdown content renders to plain `<p>`, `<h2>`, `<li>` tags without these attributes. For standard Markdown, use [Directory Mode](../configuration/localisation/translated-content.md). ::: ### How It Works There are two modes for string replacement: - **Server-side (recommended)**: With `stringMode: true` in your i18n config, docmd resolves `data-i18n` attributes **at build time**. It generates fully translated HTML in `/{locale}/` directories for search engines. - **Client-side**: The `docmd-i18n-strings.js` script loads translations at runtime via XHR. This is useful for in-place switching without page reloads. Both modes use the same `data-i18n` attribute syntax and JSON file format. 1. Place JSON translation files inside `assets/i18n/` - one per locale: ```text assets/ i18n/ en.json hi.json zh.json ``` 2. Each JSON file is a flat key-value map: ```json "assets/i18n/en.json" { "hero.title": "Markdown → Production Docs", "hero.subtitle": "The zero-config documentation engine.", "nav.docs": "Documentation", "nav.editor": "Live Editor", "cta.getStarted": "Get Started", "cta.install": "npm i @docmd/core" } ``` 3. Use `data-i18n` attributes on your HTML elements: ```html <h1 data-i18n="hero.title">Markdown → Production Docs</h1> <p data-i18n="hero.subtitle">The zero-config documentation engine.</p> <a data-i18n="nav.docs" href="/docs">Documentation</a> ``` The default language text serves as the fallback. When a non-default locale is active, the engine replaces the text. ### Attribute Translation To translate attributes like `placeholder`, `title`, or `aria-label`, use `data-i18n-{attr}`: ```html <input data-i18n-placeholder="search.placeholder" placeholder="Search..."> <button data-i18n-aria-label="nav.menuLabel" aria-label="Open menu">☰</button> <a data-i18n-title="nav.tooltip" title="Go to docs">Docs</a> ``` ### HTML Content For keys containing HTML markup, use `data-i18n-html` instead of `data-i18n`: ```html <p data-i18n-html="hero.desc">Static HTML for SEO. <br>SPA for speed.</p> ``` ### Switching Locales The i18n strings module exposes a global API at `window.DOCMD_I18N_STRINGS`: ```javascript // Switch language DOCMD_I18N_STRINGS.switchLocale("hi"); // Get active language console.log(DOCMD_I18N_STRINGS.locale); // Get all languages console.log(DOCMD_I18N_STRINGS.locales); ``` You can build a custom language switcher using this API: ```html <select onchange="DOCMD_I18N_STRINGS.switchLocale(this.value)"> <option value="en">English</option> <option value="hi">हिन्दी</option> </select> ``` ### Events Listen for the `docmd:i18n-applied` event to run custom logic after strings are applied: ```javascript document.addEventListener("docmd:i18n-applied", function(e) { console.log("Locale:", e.detail.locale); console.log("Strings:", e.detail.strings); }); ``` ::: callout info "Automatic Detection" icon:info The script detects the active locale from the URL path prefix. For the default locale, it checks `localStorage` for a previously saved preference. The `switchLocale()` function handles URL navigation automatically. ::: ### In-Place Mode For single-page sites, set `inPlace: true` in your i18n config to swap strings without URL redirects: ```json "docmd.config.json" { "i18n": { "default": "en", "locales": [ { "id": "en", "label": "English" }, { "id": "zh", "label": "中文" } ], "inPlace": true } } ``` With `inPlace: true`, calling `switchLocale()` reloads the JSON for the new locale and replaces all `data-i18n` strings instantly. No navigation occurs. --- ## [Advanced Markdown Syntax](https://docs.docmd.io/content/syntax/advanced/) --- title: "Advanced Markdown Syntax" description: "Extended formatting features: task lists, custom element attributes, footnotes, and semantic definitions." --- Beyond standard Markdown, docmd supports high-fidelity extensions derived from GitHub Flavored Markdown (GFM) and custom attribute plugins. These tools provide fine-grained control over document structure and styling. ## Task Lists Create interactive or read-only checklists for roadmap tracking and release planning. ```markdown - [x] Engine optimisation complete - [ ] Plugin API finalisation - [ ] Documentation audit ``` - [x] Engine optimisation complete - [ ] Plugin API finalisation - [ ] Documentation audit ## Emojis Use standard shortcodes to add visual personality. Emoji codes render inline with surrounding text. ```markdown We :heart: high-performance documentation! :rocket: :sparkles: ``` We :heart: high-performance documentation! :rocket: :sparkles: ## Custom Element Attributes Assign unique IDs and CSS classes to headings, images, and links using the `{}` syntax. ### Custom IDs Useful for deep-linking directly to technical subsections. ```markdown ## Performance Benchmarks {#benchmarks-2026} ``` ### CSS Classes Apply styling utilities to specific elements without touching your CSS. ```markdown ## Centre-Aligned Section {.text-centre .text-blue} ``` ### Button-Style Links Transform any standard Markdown link into a styled call-to-action button. ```markdown [Download Latest Release](#download){.docmd-button} ``` ## Footnotes Add citations or technical deep-dives as footnotes. The engine automatically collects and renders them at the page bottom. ```markdown Architectural decisions are documented in the RFC.[^1] [^1]: RFC-42: Isomorphic Rendering Pipeline. ``` Architectural decisions are documented in the RFC.[^1] [^1]: RFC-42: Isomorphic Rendering Pipeline. ## Definition Lists Perfect for API parameter descriptions and glossaries. ```markdown PropName : The unique identifier for the configuration key. DefaultValue : The value used when no override is specified. ``` PropName : The unique identifier for the configuration key. DefaultValue : The value used when no override is specified. ## Abbreviations Define abbreviations globally within a page. Hovering over the term reveals its full definition. ```markdown *[SPA]: Single Page Application The docmd router enables a seamless SPA experience. ``` *[SPA]: Single Page Application The docmd router enables a seamless SPA experience. ::: callout tip "Contextual Precision for AI" Definitions and abbreviations provide high-quality technical signals to AI agents. Explicit semantic definitions prevent lexical ambiguity in the `llms.txt` context stream. ::: --- ## [Code Blocks](https://docs.docmd.io/content/syntax/code/) --- title: "Code Blocks" description: "Document technical implementations with syntax highlighting, file titles, and one-click copying." --- docmd uses the ultra-fast `lite-hl` engine for automatic, context-aware syntax highlighting. Specify the language identifier on every fenced block to ensure the correct lexical rules apply. ## Syntax Highlighting Always name the language after the opening fence. The highlighter applies grammar rules specific to that ecosystem. ````markdown ```typescript async function build(config: string): Promise<void> { await initialise(config); } ``` ```` ```typescript async function build(config: string): Promise<void> { await initialise(config); } ``` ## Block Titles Follow the language identifier with a quoted filename to render a labelled header above the block. This is useful for referencing configuration files and source paths directly. ````markdown ```json "docmd.config.json" { "title": "My Documentation", "src": "docs/" } ``` ```` ```json "docmd.config.json" { "title": "My Documentation", "src": "docs/" } ``` ## Language Support docmd supports common technical ecosystems out of the box: * **Logic:** `javascript`, `typescript`, `python`, `rust`, `go`, `ruby`, `csharp` * **Web:** `html`, `css`, `markdown` * **Data & Shell:** `json`, `yaml`, `bash`, `powershell`, `dockerfile` * **Documentation:** `mermaid`, `changelog` ## AI Context Strategy When documenting code for AI agents, follow these practices: 1. **Label every block explicitly** - use `typescript`, `bash`, `json` rather than relying on auto-detection. This ensures the parser applies the correct grammar for the `llms.txt` stream. 2. **Embed intent in comments** - inline comments explain complex logic and provide critical reasoning context directly inside the code. ::: callout tip "One-Click Portability" Set `copyCode: true` in your configuration to enable a subtle copy button. It appears on the top-right of every block on hover, allowing readers to copy snippets instantly. ::: --- ## [Images & Visual Media](https://docs.docmd.io/content/syntax/images/) --- title: "Images & Visual Media" description: "Embed responsive images, apply styling attributes, and enable interactive lightbox zoom." --- docmd uses standard Markdown syntax for images. Centralise your media assets in the `assets/images/` directory within your project source for clean, consistent references. ```markdown ![Alt text](/assets/images/architecture.png "Optional tooltip title") ``` ![Advanced Styling Example](/assets/images/docmd-preview.png){.with-border .with-shadow .size-medium .align-centre} ## Sizing Apply a size class using the `{ }` attribute syntax. Three predefined sizes are available. ```markdown ![Small icon](/assets/icon.png){ .size-small } ![Standard view](/assets/preview.png){ .size-medium } ![Full width banner](/assets/banner.png){ .size-large } ``` ## Alignment & Decoration Combine alignment and decoration classes in a single attribute block. ```markdown ![Centred diagram](/assets/img.png){ .align-centre } ![Floating right with shadow](/assets/img.png){ .align-right .with-shadow .with-border } ``` ## Figure Captions Use the standard HTML5 `<figure>` element for precise, accessible image captioning. ```html <figure> <img src="/assets/diagram.png" alt="Cloud Infrastructure Diagram"> <figcaption>Figure 1.1: Core System Infrastructure Architecture.</figcaption> </figure> ``` ## Image Galleries Wrap multiple figures in a `div.image-gallery` to produce a responsive, balanced grid. ```html <div class="image-gallery"> <figure> <img src="/assets/screen1.jpg" alt="User Dashboard View"> <figcaption>Live Performance Monitor</figcaption> </figure> <figure> <img src="/assets/screen2.jpg" alt="Configuration Panel View"> <figcaption>Project Global Settings</figcaption> </figure> </div> ``` ## Lightbox Zoom When `mainScripts` is active, docmd automatically applies a full-screen zoom effect to any image tagged with the `.lightbox` class or placed inside a gallery. ```markdown ![Deep texture analysis](/assets/sample.png){ .lightbox } ``` ::: callout tip "AI Context & Accessibility" icon:sparkles Always provide descriptive **alt text** for every image. Meaningful alt text is a direct, high-fidelity signal for AI agents parsing the `llms.txt` stream and improves accessibility for screen reader users. ::: --- ## [Markdown Syntax Foundation](https://docs.docmd.io/content/syntax/) --- title: "Markdown Syntax Foundation" description: "The baseline formatting rules for all docmd content: typography, structure, lists, and tables." --- `docmd` adheres to standard **GitHub Flavored Markdown (GFM)** specifications. This page covers the core formatting primitives that apply across every page in your project. ## Typography | Style | Syntax | Renders As | | :--- | :--- | :--- | | **Bold** | `**text**` | **Strong emphasis** | | *Italic* | `*text*` | *Soft emphasis* | | ~~Strikethrough~~ | `~~text~~` | ~~Deprecated content~~ | | `Inline code` | `` `text` `` | `engine.initialise()` | ## Heading Hierarchy `docmd` derives the page `<h1>` automatically from the `title` field in your frontmatter. Begin your heading structure at `##`. ```markdown ## Level 2 - Major Section ### Level 3 - Feature Detail #### Level 4 - Sub-Detail ``` ::: callout tip "Logical Integrity for AI" AI models and search indexers rely on a strict heading hierarchy to build an accurate mental model of your project. Avoid skipping levels (e.g., jumping from `##` to `####`) to keep the `llms-full.txt` context stream logically sound. ::: ## Lists Use unordered lists for scannable bullet points and ordered lists for sequential steps. For numbered tutorials, consider the higher-impact [Steps container](../containers/steps.md). ```markdown * Unordered item * Another item 1. First step 2. Second step ``` ## Blockquotes The standard `>` syntax highlights external quotes or background context. ```markdown > The docmd engine redefines the boundaries between static site generation and dynamic application delivery. ``` > The docmd engine redefines the boundaries between static site generation and dynamic application delivery. ## Tables ```markdown | Parameter | Type | Default | | :--- | :--- | :--- | | `name` | `string` | `undefined` | | `active` | `boolean` | `true` | ``` | Parameter | Type | Default | | :--- | :--- | :--- | | `name` | `string` | `undefined` | | `active` | `boolean` | `true` | ## Embedded HTML docmd has raw HTML parsing enabled. Inject custom layouts or unique styling directly within Markdown files for specialised UI requirements. ```html <div style="padding: 2rem; border: 1px solid var(--border-colour); border-radius: 12px; text-align: centre;"> Bespoke UI elements live here. </div> ``` --- ## [Linking & Referencing](https://docs.docmd.io/content/syntax/linking/) --- title: "Linking & Referencing" description: "Master internal cross-linking, external resources, new-tab behaviour, and static asset referencing." --- docmd provides a reliable, filesystem-aware linking system. Write links to your source `.md` files naturally in any format - the engine normalises them into clean, SEO-optimised URLs automatically. ::: callout info "Write Naturally, Ship Perfectly" You do not need special linking conventions. Write `overview.md`, `overview/`, or `overview` - the build engine produces the exact same clean, trailing-slash URL in every case. ::: ## URL Normalisation During the build process, the engine normalises every internal link automatically. This applies to Markdown text, button containers, tags, and navigation configuration. | What You Write | What Gets Rendered | Why | | :--- | :--- | :--- | | `overview.md` | `overview/` | `.md` extension stripped, trailing `/` added. | | `overview` | `overview/` | Trailing `/` added automatically. | | `overview/` | `overview/` | Already correct. No change. | | `api/commands.md` | `api/commands/` | Subdirectory link normalised. | | `localisation/index.md` | `localisation/` | `index` stripped, the folder is the canonical URL. | | `../index.md` | `../` | Parent directory index resolved cleanly. | | `overview.md#settings` | `overview/#settings` | Hash fragment preserved. | | `https://example.com` | `https://example.com` | External links pass through untouched. | ## Internal Links Link to other pages using relative paths to the source `.md` files. The engine resolves them correctly regardless of directory depth. | Target | Example | | :--- | :--- | | Sibling page | `[System Overview](overview.md)` | | Subdirectory page | `[API Reference](api/node-api.md)` | | Subdirectory index | `[Localisation](localisation/index.md)` | | Parent directory | `[Back to Home](../index.md)` | ## Section Anchors Navigate directly to a heading using standard URL hash fragments. ```markdown <!-- Intra-page anchor --> [Jump to Roadmap](#project-roadmap) <!-- Cross-page anchor --> [Review CLI Flags](../api/cli-commands.md#available-flags) ``` Hash fragments are preserved through normalisation. The cross-page link above renders as `../api/cli-commands/#available-flags` in production. ## Opening in a New Tab Prepend `external:` to any link URL to force it to open in a new browser tab. This works in standard Markdown links, buttons, and tags. ```markdown [Open in New Tab](external:./configuration/overview.md) [GitHub](external:https://github.com/docmd-io/docmd) ``` The `external:` prefix is stripped from the rendered URL. By default, all links open in the same window. ## Linking to Raw Files Use the `raw:` prefix to bypass normalisation and link directly to a downloadable file. The extension and path are preserved exactly as written. ```markdown [View Raw Source](raw:docs/readme.md) ``` ## Buttons & Tags The `::: button` and `::: tag` containers support all standard linking conventions, including `external:` and `raw:` prefixes. ```markdown ::: button "Get Started" ./getting-started/quick-start.md icon:rocket ::: button "View on GitHub" external:https://github.com/docmd-io/docmd icon:github ::: button "Download Source" raw:docs/readme.md icon:download ::: tag "v0.8.2" link:release-notes/0-8-2.md icon:tag color:#22c55e ::: tag "Open Externally" link:external:./configuration/overview.md icon:external-link ``` ## Navigation Configuration Paths defined in `navigation.json` and `docmd.config.json` are normalised at build time. Write them in any format - all three entries below produce the identical canonical URL. ```json "navigation.json" [ { "title": "Overview", "path": "configuration/overview" }, { "title": "Overview", "path": "configuration/overview.md" }, { "title": "Overview", "path": "configuration/overview/" } ] ``` For items that should open in a new tab, set the `external` flag. ```json "navigation.json" [ { "title": "GitHub", "path": "https://github.com/docmd-io/docmd", "external": true } ] ``` ::: callout warning "Index Pages in Navigation" When linking to a directory's index page, use the folder path rather than explicitly referencing `index.md`. Both work identically, but the folder path is cleaner. ```markdown <!-- Preferred --> [Localisation](localisation/) <!-- Also works --> [Localisation](localisation/index.md) ``` ::: ## Protocols & External Resources The engine respects standard browser protocols for external resources and never modifies these links. * **HTTPS** - `[docmd Homepage](https://docmd.io)` - opens in the same tab. * **Mail** - `[Support](mailto:help@docmd.io)` - opens the email client. * **Assets** - `[Download CLI Binary](/assets/bin/docmd-mac.zip)` - not normalised. ## Static Assets Place downloadable files within your project's `assets/` directory. The builder moves these files to the production root without path modifications. ```markdown [Download Documentation PDF](/assets/pdf/handbook.pdf) [View Raw Global Config](/assets/config/docmd.config.json) ``` ::: callout tip "Semantic Linkage for AI" Prefer **descriptive anchor text** (e.g., `[Optimise PWA caching](../plugins/pwa.md)`) over generic labels (e.g., `[Read more](../plugins/pwa.md)`). Detailed link labels give AI agents a high-fidelity map of semantic relationships in the `llms.txt` stream. ::: --- ## [Caddy](https://docs.docmd.io/deployment/caddy/) --- title: "Caddy" description: "Deploy docmd with a production-ready Caddyfile." --- [Caddy](https://caddyserver.com/) is a modern web server that handles HTTPS provisioning and certificate renewals automatically. ## Generate a Caddyfile ```bash npx @docmd/core deploy --caddy ``` This generates a `Caddyfile` personalised to your project: - **Site address** is set to the hostname from your `url` config. Caddy automatically provisions an SSL certificate for it. It falls back to `:80` if no URL is configured. - **Root directory** uses your configured `out` directory (not hardcoded). - **SPA fallback** is only included when `layout.spa` is `true` in your config. ### What Gets Generated ```caddy "Caddyfile" docs.example.com { root * ./site file_server # SPA Routing Fallback (only when layout.spa is true) try_files {path} {path}/ /index.html # Security Headers header { X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" -Server } # Custom 404 handle_errors { rewrite * /404.html file_server } # Cache Static Assets (6 months) @static { file path *.ico *.css *.js *.gif *.jpg *.jpeg *.png *.webp *.avif *.svg *.woff *.woff2 *.eot *.ttf *.otf } header @static Cache-Control "public, max-age=15552000, immutable" } ``` When you use a real domain as the site address (e.g., `docs.example.com` instead of `:80`), Caddy automatically provisions a free SSL certificate via Let's Encrypt. Zero HTTPS configuration is needed. ## Deployment Steps 1. Build your site: `npx @docmd/core build` 2. Transfer your output folder and the generated `Caddyfile` to your server. 3. Run `caddy start` or `caddy run` in the directory containing your Caddyfile. ### Re-Generating Changed your site URL or output directory? Run `npx @docmd/core deploy --caddy` again. The engine regenerates the Caddyfile to match your current `docmd.config.json`. --- ## [Cloudflare Pages](https://docs.docmd.io/deployment/cloudflare-pages/) --- title: "Cloudflare Pages" description: "Deploy your docmd documentation to Cloudflare Pages using its global edge network. CI/CD-ready with automatic builds." --- [Cloudflare Pages](https://pages.cloudflare.com/) hosts your docmd site on Cloudflare's global edge network with zero-configuration CI/CD. Connect your repository, and every push triggers an automatic build and deployment. ## Dashboard Setup 1. Go to the [Cloudflare Dashboard](https://dash.cloudflare.com/) and navigate to **Workers & Pages → Create → Pages**. 2. Connect your git provider (GitHub or GitLab) and select your repository. 3. Configure the build settings: | Setting | Value | |---------|-------| | Framework preset | `None` | | Build command | `npx @docmd/core build` | | Build output directory | `site` | 4. Click **Save and Deploy**. Cloudflare Pages detects the static output and distributes it across its edge network automatically. ## Custom Domain Add a custom domain under **Pages → your project → Custom domains**. Cloudflare provisions an SSL certificate automatically. Set the `url` field in `docmd.config.json` to match your domain. This ensures canonical tags, sitemaps, and the LLMs plugin generate correct absolute URLs. ## CI/CD Notes Cloudflare Pages runs a fresh CI/CD build on every commit pushed to the connected branch. You do not need a separate GitHub Actions workflow. Cloudflare manages the build pipeline. ::: callout info "Why `npx @docmd/core`?" In CI/CD environments where docmd is not globally installed, `npx @docmd/core` fetches and runs the package directly. If your project lists `@docmd/core` as a `devDependency`, running `npx @docmd/core build` after `npm install` works perfectly. ::: ## SPA Routing docmd generates each page as its own `index.html`. Direct URL access works without any rewrite rules. No additional Cloudflare configuration is needed. --- ## [Deployer](https://docs.docmd.io/deployment/deployer/) --- title: "Deployer" description: "Generate provider-specific deployment configuration files from your docmd project config with a single command." --- The `deploy` command reads your `docmd.config.json` and generates deployment configuration files tailored to your exact project — output directory, site URL, SPA routing, and Node.js version are all reflected automatically. No generic templates. ## Supported Providers | Provider | Flag | Files Generated | | :------- | :--- | :-------------- | | Docker + Nginx | `--docker` | `Dockerfile`, `.dockerignore` | | Nginx | `--nginx` | `nginx.conf` | | Caddy | `--caddy` | `Caddyfile` | | GitHub Pages | `--github-pages` | `.github/workflows/deploy.yml` | | Vercel | `--vercel` | `vercel.json` | | Netlify | `--netlify` | `netlify.toml` | ## Usage Run from your project root (where `docmd.config.json` lives): ```bash # Single provider npx @docmd/core deploy --github-pages # Multiple providers at once npx @docmd/core deploy --docker --nginx # Overwrite existing files npx @docmd/core deploy --vercel --force ``` ## What Gets Personalised The deploy command reads your configuration (or zero-config defaults) and injects: | Config Field | Used In | |:--|:--| | `title` | Comment headers in every generated file | | `out` | `COPY` paths in Dockerfile, `root` directives in Nginx/Caddy | | `url` | `server_name` in Nginx, site address in Caddy | | `layout.spa` | Controls whether SPA routing fallback is included | | Config path | Dockerfile build step uses `--config` when non-default | No `docmd.config.json`? No problem. The command uses the same zero-config defaults as `npx @docmd/core dev` and `npx @docmd/core build`. ## Always In Sync Every run regenerates your deployment files to match your current config. Changed your site URL or output directory? Just re-run the deploy command. Use `--force` to overwrite existing files without prompts. ## Provider Details ### GitHub Pages ```bash npx @docmd/core deploy --github-pages ``` Generates `.github/workflows/deploy.yml` with a complete build-and-deploy pipeline. The workflow checks out your repository, installs Node.js, runs `npx @docmd/core build`, and uploads the output to GitHub Pages. ::: callout tip "Using the GitHub Action instead?" If you want to deploy to GitHub Pages without generating a workflow file yourself, use the [GitHub Action](./github-action) directly — it handles everything in one composable step. ::: ### Docker ```bash npx @docmd/core deploy --docker ``` Generates a `Dockerfile` using a multi-stage build: 1. **Build stage** — installs your exact pinned `@docmd/core` version and runs the build. 2. **Serve stage** — copies the output into a minimal `nginx:alpine` image. If an `nginx.conf` already exists in your project root, the Dockerfile automatically copies it into the container. ```bash # Generate Docker and Nginx configs together npx @docmd/core deploy --docker --nginx ``` ::: callout tip "Official Docker Image" Looking to run docmd in a container without building a custom image? See the [Docker Image](./docker) page for the official pre-built image. ::: ### Nginx ```bash npx @docmd/core deploy --nginx ``` Generates `nginx.conf` with SPA routing, gzip compression, and correct `root` path for your output directory. See the [NGINX](./nginx) page for the full generated config. ### Caddy ```bash npx @docmd/core deploy --caddy ``` Generates a `Caddyfile` with automatic HTTPS, SPA routing, and file serving from your output directory. See the [Caddy](./caddy) page for the full generated config. ### Vercel ```bash npx @docmd/core deploy --vercel ``` Generates `vercel.json` with SPA routing rules and your configured output directory. See the [Vercel](./vercel) page for deployment steps. ### Netlify ```bash npx @docmd/core deploy --netlify ``` Generates `netlify.toml` with your build command, publish directory, and SPA redirect rules. See the [Netlify](./netlify) page for deployment steps. ## Trade-offs Generated configs are opinionated starting points. They are correct for the majority of docmd deployments but may require adjustments for advanced scenarios such as custom domains, CDN rewrites, or multi-region deployments. Always review generated files before deploying to production. --- ## [Docker](https://docs.docmd.io/deployment/docker/) --- title: "Docker" description: "Run docmd in a Docker container — use the official pre-built image or generate a custom Dockerfile from your project config." --- docmd generates static HTML, making it ideal for lightweight, reproducible Docker containers. There are two distinct approaches depending on your use case. ## Official Docker Image The official image lets you build and serve your documentation without installing anything locally. It supports multiple architectures (`linux/amd64` and `linux/arm64`). ### Quick Start ```bash # Pull a specific version (recommended — substitute the version you need) docker pull ghcr.io/docmd-io/docmd:0.8.8 # Build your documentation (mounts local docs and outputs to ./site) docker run -v $(pwd)/docs:/docs -v $(pwd)/site:/site ghcr.io/docmd-io/docmd:0.8.8 build # Run the built-in demo site docker run -p 3000:3000 ghcr.io/docmd-io/docmd:0.8.8 ``` ::: callout tip "Pinning a version" We recommend pinning a specific version (e.g. `0.8.8`) for reproducible builds. The `:latest` tag is published automatically starting with 0.8.8, but for production pipelines you should always pin a specific release. ::: ### Docker Compose Use Docker Compose to build and serve in a single workflow: ```yaml "docker-compose.yml" version: '3.8' services: docs: image: ghcr.io/docmd-io/docmd:0.8.8 command: build volumes: - ./docs:/docs - ./site:/site - ./docmd.config.json:/docmd.config.json:ro serve: image: nginx:alpine ports: - "8080:80" volumes: - ./site:/usr/share/nginx/html:ro depends_on: - docs ``` ### Image Details | Property | Value | |:--|:--| | Base | Alpine Linux (minimal footprint) | | User | Starts as root, remaps to host uid automatically via `su-exec` | | Working directory | `/docs` (mount anywhere; use `-w` to override) | | Health checks | Built-in container health monitoring | | SBOM | Software Bill of Materials attestation included | | Architectures | `linux/amd64`, `linux/arm64` | ### Custom working directory and file ownership The image is configured with `WORKDIR /docs`, but you can mount and run from any path inside the container. Pass `-w` to override the working directory and use a mount path that matches your project layout: ```bash # Run from a custom working directory inside the container docker run -v $(pwd):/workspace -w /workspace ghcr.io/docmd-io/docmd:0.8.8 init ``` The entrypoint automatically detects the uid:gid that owns the mounted directory and re-execs as that identity before running any command. Files written by `docmd init`, `docmd build`, or `docmd dev` are always owned by the correct host user — no `-u` flag required. ::: callout warning "Read-only bind mounts" When using a read-only bind mount (`:ro`) for the config file, make sure the working directory and other mount points remain writable, or `docmd` will fail with a permission error. ::: ## Custom Dockerfile (via Deployer) For production self-hosting, generate a `Dockerfile` tailored to your project configuration using the [Deployer](./deployer): ```bash npx @docmd/core deploy --docker ``` This generates a `Dockerfile` using a multi-stage build: 1. **Build stage** — installs your exact pinned `@docmd/core` version and runs the build. 2. **Serve stage** — copies the output into a minimal `nginx:alpine` image. Generate both Docker and Nginx configs together for a complete self-hosted setup: ```bash npx @docmd/core deploy --docker --nginx ``` ### Build and Run ```bash docker build -t my-docs . docker run -p 8080:80 my-docs ``` Your documentation will be live at `http://localhost:8080`. ::: callout tip "Re-generating" Changed your config? Re-run `npx @docmd/core deploy --docker` to regenerate. Use `--force` to overwrite existing files. ::: --- ## [Firebase Hosting](https://docs.docmd.io/deployment/firebase/) --- title: "Firebase Hosting" description: "Deploy your docmd documentation to Firebase Hosting. Works manually or via GitHub Actions." --- [Firebase Hosting](https://firebase.google.com/products/hosting) delivers your docmd static site over a global CDN with SSL included. It integrates cleanly into CI/CD pipelines via the Firebase CLI or GitHub Actions. ## Prerequisites Install the Firebase CLI: ```bash npm install -g firebase-tools firebase login ``` ## Setup 1. Build your site: ```bash npx @docmd/core build ``` 2. Initialise Firebase Hosting in your project root: ```bash firebase init hosting ``` When prompted: - Select your Firebase project (or create a new one). - Set the **public directory** to `site`. - Configure as a single-page app: **No** (docmd generates individual `index.html` files per page. No catch-all rewrite is needed). - Do not overwrite `site/index.html`. 3. Deploy: ```bash firebase deploy --only hosting ``` ## CI/CD with GitHub Actions To deploy automatically on every push, create `.github/workflows/firebase.yml`: ```yaml ".github/workflows/firebase.yml" name: Deploy to Firebase Hosting on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - run: npm install - run: npx @docmd/core build - uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: ${{ secrets.GITHUB_TOKEN }} firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }} channelId: live ``` Set `FIREBASE_SERVICE_ACCOUNT` in your repository's **Settings → Secrets** using a Firebase service account JSON key. ::: callout info "Why `npx @docmd/core`?" In CI/CD environments where docmd is not globally installed, `npx @docmd/core` fetches and runs the package directly. If your project lists `@docmd/core` as a `devDependency`, running `npx @docmd/core build` after `npm install` works perfectly. ::: ## Custom Domain Add a custom domain in the Firebase Console under **Hosting → Add custom domain**. Firebase provisions SSL automatically. Set the `url` field in `docmd.config.json` to match your domain. This ensures canonical tags and sitemaps generate correct absolute URLs. --- ## [GitHub Action](https://docs.docmd.io/deployment/github-action/) --- title: "GitHub Action" description: "Use the official docmd GitHub Action to build and deploy your documentation to GitHub Pages — zero config, one composable step." --- The `docmd-io/deploy` action builds your documentation site and outputs the path to the compiled assets, ready for upload to GitHub Pages or any other hosting target. It handles Node.js setup, config detection, dependency installation, and the build step in a single composable action. ::: button "View on GitHub Marketplace" external:https://github.com/marketplace/actions/build-and-deploy-documentation-with-docmd icon:github ::: button "Source Code" external:https://github.com/docmd-io/deploy icon:code ::: callout tip "Starting a new project?" Use the [Starter Template](./starter-template) — it includes a pre-configured workflow file and a ready-to-go repository structure. The GitHub Action is best for adding docmd deployment to an **existing** repository. ::: ## Quick Start Add the action to any workflow file in your repository: ```yaml ".github/workflows/docs.yml" # .github/workflows/docs.yml name: Deploy Docs on: push: branches: [main] permissions: contents: write pages: write id-token: write jobs: docs: runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deploy.outputs.page_url }} steps: - uses: actions/checkout@v4 - uses: docmd-io/deploy@v1 id: build - uses: actions/upload-pages-artifact@v3 with: path: ${{ steps.build.outputs.site-dir }} - uses: actions/deploy-pages@v4 id: deploy ``` ## Reusable Workflow For the absolute minimum boilerplate, use the hosted reusable workflow. It handles permissions, checkout, build, upload, and deploy in one call: ```yaml ".github/workflows/docs.yml" # .github/workflows/docs.yml on: push: branches: [main] jobs: docs: uses: docmd-io/deploy/.github/workflows/deploy.yml@v1 ``` ## Inputs | Input | Default | Description | |-------|---------|-------------| | `node` | `20` | Node.js version to use during the build | ## Outputs | Output | Description | |--------|-------------| | `site-dir` | Relative path to the compiled site directory (e.g. `site/`) | ## What the Action Does The action runs the following steps internally: 1. **Sets up Node.js** using the specified version. 2. **Detects your config** — searches the repository tree (up to two levels deep) for `docmd.config.json`, `docmd.config.js`, or `docmd.config.ts`. Subdirectory configs are fully supported. 3. **Initialises docmd** — if no config is found, runs `npx @docmd/core init` to scaffold one automatically. 4. **Installs dependencies** — runs `npm ci` if a `package.json` is present, otherwise installs `@docmd/core` directly. 5. **Builds the site** — runs `npx @docmd/core build` and reads the output directory from your config. 6. **Outputs the path** — exposes `site-dir` so the upload step knows where to find the compiled assets. ## First-Time Setup GitHub Pages must be configured to deploy from **GitHub Actions** (not from a branch). This is a one-time step per repository: 1. Go to your repository on GitHub. 2. Navigate to **Settings → Pages**. 3. Under **Source**, select **GitHub Actions**. 4. Save. After this, every push to `main` triggers a deployment automatically. ## Nested Config Support If your `docmd.config.json` lives in a subdirectory — for example, `packages/docs/docmd.config.json` in a monorepo — the action detects it and passes `--cwd` to docmd automatically. No manual path configuration is required. ## Project Pages (Subpath Deployment) GitHub Pages serves project sites at `https://<username>.github.io/<repo-name>/`, not at the domain root. docmd handles this automatically — set `url` to your full GitHub Pages URL and docmd derives the correct asset paths from it: ```json "docmd.config.json" { "url": "https://username.github.io/my-repo" } ``` That's it. docmd reads the `/my-repo/` subpath from your URL and uses it for every internal link and asset reference. No additional configuration is needed. ::: callout tip "How docmd knows your deployment path" docmd derives the asset base path from your `url` config. The `url` you set for SEO and sitemaps is the same value docmd uses to figure out where your assets live. Set it once, everything follows. If your deployment path ever differs from your URL path (rare, e.g. a CDN that strips a prefix), you can override with `base`. docmd normalises slashes for you, so any of these work: `"my-repo"`, `"/my-repo"`, `"/my-repo/"`. You don't have to remember which slashes are required. ::: ## Custom Domain To use a custom domain: 1. Add a `CNAME` file to your `docs/` directory (or your configured assets folder) containing your domain, e.g. `docs.example.com`. 2. Set the `url` field in `docmd.config.json` to your custom domain so sitemaps and canonical tags are correct. 3. Configure the domain in **Settings → Pages → Custom domain**. ## Pinning the Action Version For production documentation sites, pin to a specific release tag rather than `@v1`: ```yaml ".github/workflows/docs.yml" - uses: docmd-io/deploy@v1.0.0 id: build ``` This prevents unexpected behaviour from future minor updates. ## Troubleshooting **`Error: Dependencies lock file is not found`** This occurs when `actions/setup-node` is configured with `cache: 'npm'` but no `package-lock.json` exists. The `docmd-io/deploy` action handles caching internally — do not add a separate `actions/setup-node` step with `cache: 'npm'` when using this action. **Build succeeds but the site is not live** Ensure GitHub Pages is set to deploy from **GitHub Actions**, not from a branch. See [First-Time Setup](#first-time-setup) above. **Config not detected** The action searches up to two directory levels. If your config is deeper, pass `--cwd` manually in a custom workflow step or use the [Deployer](./deployer) to generate a tailored workflow file. --- ## [Deployment Overview](https://docs.docmd.io/deployment/) --- title: "Deployment Overview" description: "Choose how to deploy your docmd documentation site — from zero-config templates to self-hosted servers and cloud platforms." --- docmd builds a fully static site. The output is a self-contained folder (default: `site/`) that can be hosted anywhere — no server-side runtime required. ```bash npx @docmd/core build ``` ## Choosing a Deployment Method There are three main paths depending on your situation: | Method | Best For | |:--|:--| | [Starter Template](./starter-template) | Starting a new project from scratch | | [GitHub Action](./github-action) | Adding automated deployment to an existing repository | | [Deployer](./deployer) | Generating server configs (Docker, Nginx, Caddy, Vercel, Netlify) | ## Starter Template The fastest way to get started. Clone the official template repository — it includes a `docmd.config.json`, a sample page, and a pre-configured GitHub Actions workflow that deploys to GitHub Pages on every push. → [Starter Template](./starter-template) ## GitHub Action The `docmd-io/deploy` action builds your site and outputs the compiled path, ready for upload to GitHub Pages or any other target. Use this to add docmd deployment to an existing repository without changing your project structure. → [GitHub Action](./github-action) ## Deployer The `deploy` command reads your `docmd.config.json` and generates provider-specific configuration files tailored to your project. No generic templates — every file reflects your actual output directory, site URL, and SPA settings. ```bash # Self-hosted npx @docmd/core deploy --docker # Dockerfile + .dockerignore npx @docmd/core deploy --nginx # Production nginx.conf npx @docmd/core deploy --caddy # Production Caddyfile # Cloud / CI npx @docmd/core deploy --github-pages # GitHub Actions workflow npx @docmd/core deploy --vercel # vercel.json npx @docmd/core deploy --netlify # netlify.toml ``` → [Deployer Reference](./deployer) ## Cloud Platforms For managed hosting without running your own server: - [Docker Image](./docker) — Official multi-arch image for containerised deployments - [NGINX](./nginx) — Self-hosted with generated config - [Caddy](./caddy) — Self-hosted with automatic HTTPS - [Vercel](./vercel) — Zero-config cloud deployment - [Netlify](./netlify) — Git-connected continuous deployment - [Cloudflare Pages](./cloudflare-pages) — Edge-native hosting with built-in CI/CD - [Firebase Hosting](./firebase) — Google CDN with GitHub Actions integration ## Production Checklist 1. **Site URL** — Set `url` in `docmd.config.json`. This drives canonical tags, sitemaps, social previews, and generated deployment files. 2. **Redirects** — Migrating from another tool? Use the `redirects` config to preserve SEO rankings. 3. **Analytics** — Enable the `analytics` plugin to track engagement and search queries. 4. **AI Context** — Enable the `llms` plugin to generate `llms.txt` for AI agent ingestion. ::: callout tip "Custom 404 Pages" docmd writes a `404.html` into your output directory. Most static hosts serve it automatically for missing routes. ::: --- ## [Netlify](https://docs.docmd.io/deployment/netlify/) --- title: "Netlify" description: "Deploy your docmd documentation to Netlify using a generated netlify.toml." --- `npx @docmd/core deploy --netlify` generates a `netlify.toml` file at the root of your project. It is pre-configured with the correct build command, publish directory, cache headers, and SPA redirects. ```bash npx @docmd/core deploy --netlify ``` ## What Gets Generated The `netlify.toml` configures: - **Build command** - installs `@docmd/core` and runs `npx @docmd/core build`. - **Publish directory** - set to your configured `out` directory. - **Node version** - pinned to Node 20. - **Cache headers** - immutable for assets, no-cache for HTML pages. - **SPA redirects** - a `/*` → `/index.html` rewrite when `layout.spa` is enabled. ## Deploying Connect your repository to Netlify from the [Netlify dashboard](external:https://app.netlify.com). It detects the `netlify.toml` automatically and deploys on every push. Alternatively, use the [Netlify CLI](external:https://docs.netlify.com/cli/get-started/): ```bash npm install -g netlify-cli netlify deploy --prod ``` ## Re-generating Re-run `npx @docmd/core deploy --netlify` any time you change `out` or other config fields. This keeps `netlify.toml` in sync. --- ## [NGINX](https://docs.docmd.io/deployment/nginx/) --- title: "NGINX" description: "Deploy docmd with a production-ready NGINX configuration." --- NGINX is one of the most reliable web servers available. Because docmd output is entirely static, NGINX can serve it with near-zero latency. ## Generate nginx.conf ```bash npx @docmd/core deploy --nginx ``` This generates an `nginx.conf` personalised to your project: - **`server_name`** is set to the hostname extracted from your `url` config. It falls back to `localhost` if not set. - **SPA fallback** (`try_files ... /index.html`) is only included when `layout.spa` is `true` in your config. - **Security headers**, GZIP compression, and immutable asset caching are included by default. ### What Gets Generated ```nginx "nginx.conf" server { listen 80; server_name docs.example.com; root /usr/share/nginx/html; index index.html; # Security server_tokens off; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; # GZIP Compression gzip on; gzip_vary on; gzip_min_length 256; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; # SPA Routing Fallback (only when layout.spa is true) location / { try_files $uri $uri/ /index.html; } # Custom 404 error_page 404 /404.html; # Cache Static Assets (6 months, immutable) location ~* \.(?:ico|css|js|gif|jpe?g|png|webp|avif|woff2?|eot|ttf|otf|svg)$ { expires 6M; access_log off; add_header Cache-Control "public, immutable"; } } ``` ## Deployment Steps 1. Build your site: `npx @docmd/core build` 2. Upload the contents of your output directory to your server's web root (e.g., `/var/www/html/` or `/usr/share/nginx/html/`). 3. Place the generated `nginx.conf` into your server's configuration (e.g., `/etc/nginx/conf.d/default.conf`). 4. Restart NGINX: `sudo systemctl restart nginx` ### Re-Generating Changed your site URL or switched off SPA mode? Just run `npx @docmd/core deploy --nginx` again. The config file automatically regenerates to match your current `docmd.config.json`. --- ## [Starter Template](https://docs.docmd.io/deployment/starter-template/) --- title: "Starter Template" description: "Use the official docmd starter template to create a pre-configured documentation site with GitHub Pages deployment in under a minute." --- # docmd Starter Template The `docmd-template` repository is the fastest way to start a new documentation site. It includes a working `docmd.config.json`, a sample page, a `package.json` for local development, and a pre-configured GitHub Actions workflow that deploys to GitHub Pages automatically on every push. ::: button "Use this Template" external:https://github.com/docmd-io/docmd-template/generate icon:github color:#2ea44f ::: button "View Repository" external:https://github.com/docmd-io/docmd-template icon:external-link ## Getting Started ### 1. Create Your Repository Click **[Use this template](https://github.com/docmd-io/docmd-template/generate)** on GitHub. Give your repository a name and click **Create repository**. You do not need to fork it — the template creates a clean, independent copy. ### 2. Configure Your Site Open `docmd.config.json` in your new repository and update the `title` and `url` fields: ```json "docmd.config.json" { "title": "My Docs", "url": "https://username.github.io/repo-name" } ``` Replace `username` and `repo-name` with your GitHub username and repository name. ### 3. Enable GitHub Pages This is a one-time step per repository: 1. Go to **Settings → Pages**. 2. Under **Source**, select **GitHub Actions**. 3. Save. ### 4. Push and Deploy Push any change to `main`. The included workflow builds your site and deploys it to GitHub Pages automatically. Your documentation will be live at: ``` https://<username>.github.io/<repo-name>/ ``` ## What's Included ``` .github/ workflows/ docs.yml # Automated build and deploy on push to main docmd.config.json # Site title, URL, and output directory docs/ index.md # Your first documentation page package.json # Local development scripts ``` ## Local Development Clone your repository and run the development server: ```bash npm install npm run dev ``` The site is available at `http://localhost:3000` with live reload. Changes to Markdown files are reflected immediately. To build a production copy locally: ```bash npm run build ``` The compiled site is written to `site/` by default. ## Included Workflow The template ships with `.github/workflows/docs.yml`: ```yaml ".github/workflows/docs.yml" name: Docs on: push: branches: [main, master] workflow_dispatch: permissions: contents: write pages: write id-token: write concurrency: group: docs cancel-in-progress: false jobs: deploy: runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deploy.outputs.page_url }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: 20 - name: Install run: npm install @docmd/core - name: Build run: npx @docmd/core build - uses: actions/upload-pages-artifact@v3 with: path: ./site - name: Deploy id: deploy uses: actions/deploy-pages@v4 ``` The workflow installs `@docmd/core` directly without a lock file, which is intentional — the template has no committed `package-lock.json` so `actions/setup-node` caching is not used. This keeps the template dependency-free whilst still deploying reliably. ## Adding Your First Page Create a new Markdown file in `docs/`: ```bash docs/ index.md # Home page getting-started.md api-reference.md ``` Add a `navigation.json` to control the sidebar: ```json "navigation.json" [ { "title": "Home", "path": "/" }, { "title": "Getting Started", "path": "/getting-started" }, { "title": "API Reference", "path": "/api-reference" } ] ``` See [Navigation Configuration](../configuration/navigation.md) for the full navigation schema. ## Custom Domain To use a custom domain (e.g. `docs.example.com`): 1. Update the `url` field in `docmd.config.json`: ```json { "url": "https://docs.example.com" } ``` 2. Add a `CNAME` file to your `docs/` directory containing your domain. 3. Configure the domain in **Settings → Pages → Custom domain**. ## Starter Template vs GitHub Action The template gives you full ownership of the workflow file and config from the start. The [GitHub Action](./github-action) is better suited for adding docmd deployment to an existing repository without restructuring it. | | Starter Template | GitHub Action | |---|---|---| | Starting point | New repository | Existing repository | | Workflow file | Included, yours to edit | You write it, action handles build | | Config | Pre-configured | Detected or scaffolded automatically | | Best for | New projects | Adding docs to existing repos | --- ## [Vercel](https://docs.docmd.io/deployment/vercel/) --- title: "Vercel" description: "Deploy your docmd documentation to Vercel using a generated vercel.json." --- `npx @docmd/core deploy --vercel` generates a `vercel.json` file at the root of your project. It is automatically configured for your site's output directory and SPA routing settings. ```bash npx @docmd/core deploy --vercel ``` ## What Gets Generated The `vercel.json` configures: - **Build command** - runs `npx @docmd/core build`. - **Output directory** - set to the `out` property in your config. - **Install command** - installs the exact `@docmd/core` version used. - **Cache headers** - immutable caching for assets, no-cache for HTML. - **SPA routing** - a catch-all route to `index.html` when `layout.spa` is enabled. ## Deploying After generating the file, deploy using the [Vercel CLI](external:https://vercel.com/docs/cli): ```bash npm install -g vercel vercel ``` Alternatively, connect your repository to Vercel from the dashboard. It detects the `vercel.json` automatically. ## Re-generating If you change your `out` directory or `url` in `docmd.config.json`, re-run the command to regenerate the file. This keeps the configuration in sync. --- ## [Building Plugins](https://docs.docmd.io/development/building-plugins/) --- title: "Building Plugins" description: "A comprehensive guide to extending docmd with custom logic, data injection, and interactive features." --- Plugins are the primary extension mechanism for docmd. They allow you to inject HTML, modify Markdown parsing, inject build-time data, and automate post-build tasks. This guide outlines the plugin API. ## Plugin Descriptor Every plugin must export a `plugin` descriptor declaring its identity and capabilities. This enables the engine to validate and isolate boundaries at load time. ```javascript "plugin": { "name": "my-analytics", "version": "1.0.0", "capabilities": ["head", "body", "post-build"] }, "generateScripts": (config, opts) => { ... }, "onPostBuild": async (ctx) => { ... } ``` > **Note:** The descriptor is strictly required. Plugins without it will fail to load. ## The `docmd` Namespace (new in 0.8.9) In addition to the runtime `plugin` descriptor, every official plugin **must** declare a `docmd` namespace in its `package.json`. This namespace is the build-time contract that the registry generator reads to build the single source of truth that the runtime loader consumes. ```json "package.json" { "name": "@docmd/plugin-foo", "version": "1.0.0", "docmd": { "key": "foo", "kind": "plugin", "displayName": "Foo", "tagline": "What this plugin does in one line", "capabilities": ["head", "body", "post-build"] } } ``` | Field | Required | Description | | :--- | :--- | :--- | | `key` | Recommended | The user-facing identifier (`config.plugins.<key>`). Derived from the package name if omitted. | | `kind` | Recommended | One of `plugin`, `template`, `engine`. Derived from the directory layout if omitted. | | `displayName` | Recommended | Human-readable name shown in catalogs and `docmd doctor` output. | | `tagline` | Recommended | One-line description; used as a fallback for the npm description. | | `capabilities` | Required for plugins and templates | The same hook capabilities the JS descriptor declares. The build-time cross-check warns if the two diverge. | | `preview` | Optional | Path to a preview asset (template only); shown in catalogs. | Engines have the same `docmd` namespace but **no `capabilities`** — they don't participate in the hook system, only in the engine loader. The build-time cross-check (also new in 0.8.9) surfaces drift between the JS descriptor and the manifest, including the "implemented hook without declared capability" silent-drop bug that was previously invisible. ::: callout warning "Bundled registry removal in 0.9.0" The hand-maintained `packages/plugins/installer/registry/plugins.json` that used to be the catalog of official plugins is **deprecated** as of 0.8.9 and will be **removed in 0.9.0**. The build-time registry generator is now the single source of truth — your plugin only needs a correct `docmd` namespace in its `package.json`, and the generator picks it up on the next `pnpm build` of `@docmd/api`. No code changes required for existing official plugins. ::: ## Core Capabilities The `capabilities` array dictates which hooks your plugin is allowed to use. | Capability | Allowed Hooks | Phase | | :--- | :--- | :--- | | `init` | `onConfigResolved` | Init | | `markdown` | `markdownSetup` | Setup | | `head` | `generateMetaTags`, `generateScripts` (head) | Render | | `body` | `generateScripts` (body) | Render | | `build` | `onBeforeParse`, `onAfterParse`, `onBeforeBuild`, `onBeforeRender`, `onPageReady` | Build | | `post-build`| `onPostBuild` | Post-Build | | `dev` | `onDevServerReady` | Dev Server | | `assets` | `getAssets` | Output | | `actions` | `actions` | Interactive | | `events` | `events` | Interactive | | `translations`| `translations` | i18n | | `template` *(new in 0.8.7)* | `templates`, `templateAssets` | Render | > **Note:** the `template` capability is exclusive — if a plugin declares it, it cannot also declare `head`, `build`, `post-build`, etc. Templates ship slots and assets only; they do not run lifecycle hooks. If you need both, ship two separate packages. ## Plugin API Reference A docmd plugin is a standard JavaScript object that implements one or more of the following hooks. | Hook | Description | | :--- | :--- | | `markdownSetup(md, opts)` | Extend the `markdown-it` instance. Synchronous. | | `generateMetaTags(config, page, root)` | Inject `<meta>` or `<link>` tags into the `<head>`. | | `generateScripts(config, opts)` | Return an object containing `headScriptsHtml` and `bodyScriptsHtml`. | | `getAssets(opts)` | Define external files or CDN scripts to be injected. | | `onPostBuild(ctx)` | Run logic after the generation of all HTML files. | | `translations(localeId)` | Return an object of translated strings for the given locale. | | `actions` | An object of named action handlers for WebSocket RPC calls. | | `events` | An object of named event handlers for browser messages. | | `templates[]` *(new in 0.8.7, capability: `template`)* | Array of `TemplateHook` entries — each `{ type, templatePath }` overrides one EJS slot. | | `templateAssets[]` *(new in 0.8.7, capability: `template`)* | Array of `TemplateAssetHook` entries — each `{ type, path, priority?, position? }` ships the template's CSS/JS bundle. | ### Building a template plugin (new in 0.8.7) A template is a plugin with `capabilities: ['template']`. It ships a `templates[]` array (slot overrides) and a `templateAssets[]` array (CSS/JS bundle). See the dedicated [Templates guide](../theming/templates.md) and [Theming → Templates](../theming/templates.md) for the full authoring walkthrough, slot table, and resolution chain. The minimum viable template looks like: ```javascript export default { plugin: { name: 'template-foo', version: '1.0.0', capabilities: ['template'], }, templates: [ { type: 'menubar', templatePath: '/abs/path/to/templates/partials/menubar.ejs' }, { type: 'footer', templatePath: '/abs/path/to/templates/partials/footer.ejs' }, ], templateAssets: [ { type: 'css', path: '/abs/path/to/assets/css/foo.css', priority: 10, position: 'head' }, ], }; ``` ## Creating a Local Plugin Creating a plugin is as simple as defining a JavaScript file. For example, `my-plugin.js`: ```javascript import path from "path"; export default { plugin: { "name": "my-plugin", "version": "1.0.0", "capabilities": ["head", "post-build"] }, markdownSetup: (md, options) => { // Add custom parser rules }, generateMetaTags: async (config, page, relativePathToRoot) => { return `<meta name="x-build-id" content="${config._buildHash}">`; }, onPostBuild: async ({ config, pages, outputDir, log, options }) => { log(`Custom Plugin: Verified ${pages.length} pages.`); } }; ``` To enable your plugin, reference its **full package name** in your `docmd.config.json`: ```json "docmd.config.json" "plugins": { "my-awesome-plugin": {} } ``` > **Note:** Shorthand names (e.g. `math`, `search`) are reserved for official `@docmd/plugin-*` packages. Third-party plugins must always use their full npm package name. ### Plugin Resolution The docmd engine resolves plugin names as follows: - **Official shorthands** (`math`, `search`) expand to `@docmd/plugin-<name>`. Only official packages can exist under the `@docmd` scope. - **Third-party plugins** must use their full package name (e.g. `my-awesome-plugin`, `@myorg/docmd-extras`). There is no alias system for external plugins. This eliminates supply-chain attack vectors. ### Plugin Isolation Every hook invocation is wrapped in a try/catch block. A broken plugin cannot crash the build or interfere with other plugins. Errors are logged and collected into a summary. ### Scoping Plugins (`noStyle`) Plugins inject their CSS/JS universally by default. Developers can explicitly prevent their plugin from rendering on `noStyle` pages by exporting a `noStyle` boolean: ```javascript export default { noStyle: false, generateScripts: () => { ... } } ``` Users can override this via configuration (`plugins: { math: { noStyle: false } }`) or dynamically via Markdown frontmatter (`plugins: { math: true }`). ## Lifecycle Hooks Docmd provides deep integration hooks. They allow plugins to manipulate configuration, raw sources, and page data. | Hook | Description | Expected Return | | :--- | :--- | :--- | | **`onConfigResolved(config)`** | Reads or modifies the active config right after initialisation. | `void` or `Promise<void>` | | **`onDevServerReady(server, wss)`** | Exposes the raw Node.js server during `npx @docmd/core dev`. | `void` or `Promise<void>` | | **`onBeforeParse(src, frontmatter, filePath?)`** | Pre-processes raw markdown string data immediately before parsing. | `string` or `Promise<string>` | | **`onAfterParse(html, frontmatter, filePath?)`** | Post-processes generated HTML representing the markdown body. | `string` or `Promise<string>` | | **`onBeforeBuild(ctx)`** | Called after all markdown is parsed but before HTML generation. Used for heavy pre-computation. | `void` or `Promise<void>` | | **`onBeforeRender(page)`** | Called before template rendering. Mutations to `frontmatter` and `html` are reflected in output. | `void` or `Promise<void>` | | **`onPageReady(page)`** | Accesses fully assembled page metadata just before it is written to the destination file. | `void` or `Promise<void>` | ### Engine Acceleration & Background Tasks (`runWorkerTask`) docmd executes intensive operations via a **Pluggable Engine Architecture**. Plugins can easily offload custom heavy I/O or CPU-bound subroutines through the configured build engine (e.g., JavaScript or native Rust workers). The `runWorkerTask` method is injected transparently into `PageContext`, `PostBuildContext`, and `ActionContext`. ```javascript { "plugin": { "name": "my-plugin", "version": "1.0.0", "capabilities": ["post-build"] }, "onPostBuild": async (ctx) => { // Pass a registered engine action name or absolute script path const result = await ctx.runWorkerTask('/path/to/worker.js', 'parseData', [ctx.outputDir]); } } ``` ### Data Fetching and Indexing (`onBeforeBuild`) The `onBeforeBuild` hook runs *after* markdown parsing but *before* the HTML rendering loop begins. It is optimal for heavy data indexing or API calls. It receives the `BeforeBuildContext`, containing all `pages` and the `tui` instance. This allows plugins to show isolated progress bars. ```typescript export async function onBeforeBuild({ pages, tui }) { tui.step('Fetching remote plugin data', 'WAIT'); let processed = 0; for (const page of pages) { if (page.sourcePath) { page.frontmatter.remoteData = await fetchHeavyData(page.sourcePath); } processed++; if (processed % 10 === 0 || processed === pages.length) { tui.progress('Fetching remote plugin data', processed, pages.length); } } tui.step('Fetching remote plugin data', 'DONE'); } ``` ### `onBeforeRender` and `PageContext` Use `onBeforeRender` to inject build-time data derived from the source file. ```typescript interface PageContext { sourcePath: string; frontmatter: Record<string, any>; html: string; localeId?: string; versionId?: string; relativePathToRoot?: string; runWorkerTask<T = any>(modulePath: string, functionName: string, args: any[]): Promise<T>; } ``` ```javascript export default { plugin: { name: "my-metadata-plugin", version: "1.0.0", capabilities: ["build"] }, onBeforeRender: async (page) => { const stats = fs.statSync(page.sourcePath); page.frontmatter.wordCount = page.html.split(/\s+/).length; page.frontmatter.fileSize = stats.size; } } ``` ## Deep Dive: Asset Injection The `getAssets()` hook allows your plugin to bundle client-side logic securely. ```javascript export default { getAssets: (options) => { return [ { url: "https://example.com/script.js", type: "js", location: "head" }, { src: path.join(__dirname, "plugin-init.js"), dest: "assets/js/plugin-init.js", type: "js", location: "body" } ]; } } ``` ## Translating Plugins (i18n) Plugins rendering client-side UI should expose strings via the `translations(localeId)` hook. The engine merges these with core strings automatically. The standard pattern stores a JSON file for each language in an `i18n/` directory: ```javascript import fs from "fs"; import path from "path"; export default { plugin: { name: "my-plugin", version: "1.0.0", capabilities: ["translations", "body"] }, translations: (localeId) => { try { const p = path.join(__dirname, "i18n", `${localeId}.json`); return JSON.parse(fs.readFileSync(p, "utf8")); } catch { } return {}; } } ``` ## WebSocket RPC Actions Plugins can register **action handlers** and **event handlers** that run on the dev server. They are callable from the browser via the `window.docmd` API. ```javascript export default { plugin: { name: "my-live-plugin", version: "1.0.0", capabilities: ["actions", "events"] }, actions: { "my-plugin:save-note": async (payload, ctx) => { const content = await ctx.readFile(payload.file); const updated = content + "\n\n> " + payload.note; await ctx.writeFile(payload.file, updated); return { "saved": true }; } }, events: { "my-plugin:page-viewed": (data, ctx) => { console.log(`Page viewed: ${data.path}`); } } }; ``` The `ctx` (ActionContext) provides: | Method | Description | | :--- | :--- | | `ctx.readFile(path)` | Read a file relative to the project root. | | `ctx.writeFile(path, content)` | Write a file (triggers rebuild + reload). | | `ctx.readFileLines(path)` | Read a file as an array of lines. | | `ctx.broadcast(event, data)` | Push an event to all connected browsers. | | `ctx.runWorkerTask(module, fn, args)` | Offload heavy CPU tasks to the worker pool. | | `ctx.source` | Source editing tools for block-level markdown manipulation. | | `ctx.projectRoot` | Absolute path to the project root. | | `ctx.config` | Current docmd site configuration. | All file operations are sandboxed to the project root. ::: callout info "Dev Mode Only 🛡️" The WebSocket RPC system is only active during `npx @docmd/core dev`. Production builds do not include the API client or server-side action handling. ::: ## Best Practices 1. **Declare Capabilities**: Always export a `plugin` descriptor with declared capabilities. 2. **Use `onBeforeRender` for data injection**: If your plugin computes frontmatter fields, use `onBeforeRender`. 3. **Async/Await**: Always use `async` functions for `onPostBuild`, `onBeforeRender`, and action handlers. 4. **Statelessness**: Avoid maintaining state within the plugin object. The engine may re-initialise plugins dynamically. 5. **Naming Convention**: Prefix community package names with `docmd-plugin-`. 6. **Action Namespacing**: Prefix action names with your plugin name (e.g., `my-plugin:save-note`). 7. **Action Validation**: Define and require an explicit payload schema in your actions. 8. **Logging**: Use the provided `log()` helper in `onPostBuild` to respect user verbosity settings. ::: callout tip "AI-Ready Design 🤖" The docmd plugin API is **LLM-Optimal**. Because the hooks use standard JavaScript objects, AI agents can generate bug-free plugins with minimal instruction. ::: ## ESM Exports — the `default` Condition Your plugin's `package.json` **must** include a `"default"` condition in `exports["."]`, alongside the `import` condition: ```json "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "default": "./dist/index.js" } } ``` If you declare only `import`, the auto-installer's first attempt throws `ERR_PACKAGE_PATH_NOT_EXPORTED` because Node's CommonJS resolver cannot match any condition. The retry path will still succeed (it uses dynamic `import()` directly), but the build will print a redundant "Plugin installed" TUI line every time. This convention matches what `@docmd/plugin-git`, `@docmd/plugin-openapi`, and `@docmd/plugin-threads` already ship with. Templates (`@docmd/template-*`) have the same requirement. --- ## [Building Templates](https://docs.docmd.io/development/building-templates/) --- title: "Building Templates" description: "Author a docmd template package — directory layout, descriptor, EJS context, asset priorities, and API reference." --- # Building Templates ::: callout info **For template authors.** If you want to *use* a template in your docs site, see [Templates](/theming/templates) instead. ::: A template is a regular npm package that declares `capabilities: ['template']` and ships a `templates[]` array of `.ejs` file overrides. The template resolver in `@docmd/ui` handles the per-page lookup, honours frontmatter / config overrides, and falls back to the default if anything goes wrong. ## Package layout ``` @docmd/template-summer/ ├── package.json ├── index.js # Plugin entry — exports templates[] + templateAssets[] ├── templates/ │ ├── layout.ejs │ ├── partials/ │ │ ├── menubar.ejs # Only the partials you need to override │ │ └── footer.ejs └── assets/ ├── css/ │ └── summer.css # Layers on top of docmd-main.css; does not replace it. └── js/ └── summer.js ``` ## `package.json` ```json "package.json" { "name": "@docmd/template-summer", "version": "0.1.0", "type": "module", "main": "index.js", "peerDependencies": { "@docmd/core": ">=0.8.7" }, "docmd": { "kind": "template", "displayName": "Summer", "description": "A bright summer-inspired layout for the 0.8.7+ template system." } } ``` ## ESM Exports — the `default` Condition Your template's `package.json` **must** include a `"default"` condition in `exports["."]`, alongside the `import` condition: ```json "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "default": "./dist/index.js" } } ``` If you declare only `import`, the auto-installer's first attempt throws `ERR_PACKAGE_PATH_NOT_EXPORTED` because Node's CommonJS resolver cannot match any condition. The retry path will still succeed (it uses dynamic `import()` directly), but the build will print a redundant "Plugin installed" TUI line every time. Plugins (`@docmd/plugin-*`) have the same requirement — see the [plugin development guide](building-plugins.md#esm-exports--the-default-condition) for the full context. ## `index.js` ```js "index.js" import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); export default { plugin: { name: 'template-summer', version: '0.1.0', capabilities: ['template'], }, templates: [ // Only the slots you actually want to override. { type: 'layout', templatePath: path.join(__dirname, 'templates/layout.ejs') }, { type: 'menubar', templatePath: path.join(__dirname, 'templates/partials/menubar.ejs') }, { type: 'footer', templatePath: path.join(__dirname, 'templates/partials/footer.ejs') }, ], templateAssets: [ { type: 'css', path: path.join(__dirname, 'assets/css/summer.css'), priority: 10, // higher than theme (5), lower than customCss (15) position: 'head', }, { type: 'js', path: path.join(__dirname, 'assets/js/summer.js'), priority: 10, position: 'body', }, ], }; ``` ## `layout.ejs` context Templates receive the same EJS context as the default layout. The most common locals: | Local | Description | |---|---| | `config` | The normalised site config. | | `frontmatter` | Per-page frontmatter. | | `relativePathToRoot` | E.g. `./` or `../` — use this to build relative URLs. | | `renderIcon(name, opts)` | Render a Lucide icon. | | `t(key, params?)` | Translation function. | | `buildRelativeUrl(url)` | Resolve a URL relative to the current page. | | `pageTitle`, `siteTitle`, `appearance` | Common strings. | | `_template` | Metadata about the resolved template (new in 0.8.7). | You can include default partials from `@docmd/ui` by reading them at build time. The simplest pattern is to keep a copy of the partials you reuse; templates do not inherit partial paths automatically. ## Asset priority chain CSS and JS load in this order (lower loads first, higher wins cascade ties): | Priority | Layer | Notes | |---|---|---| | 0 | Base (`docmd-main.css`, `docmd-main.js`) | Always present. | | 5 | Theme colour overlay (`docmd-theme-sky.css`, etc.) | From `theme.name`. Skipped when the name auto-promoted to a template (see `_noCssOverlay`). | | 10 | **Template structure** (default) | Your template's CSS — this is the default if you omit `priority`. | | 15 | User `customCss` / `customJs` | Always wins — that's the contract. | | 20 | Plugin CSS/JS | lightbox, search, analytics, etc. | | 25+ | Higher template priority | **Use only when you must override plugins.** The official Summer template declares `priority: 25` so it loads after plugin CSS. Higher values cascade later. | Templates may declare a higher priority than 10 — Summer itself uses **25** so it overrides plugin styles. The recommended band is **10–20** for "user-overridable" templates and **20+** for "opinionated layout" templates. ::: callout warning "Do not use !important" Templates should write CSS that can be overridden by `customCss` at priority 15. Using `!important` breaks the contract and means users can't restyle your template without forking it. (Summer's CSS file header enforces this — `!important` is removed during 0.8.7 cleanup so users can finally override Summer without resorting to `!important` themselves.) ::: ## Auto-promotion of `theme.name` The `theme.name` → `theme.template` promotion happens inside `normalizeConfig()`, not the resolver: - When `theme.name` is a non-reserved value and `theme.template` is unset, the config is rewritten to `theme.template = theme.name` and `theme._noCssOverlay = true` (so the generator skips the `docmd-theme-${name}.css` lookup that would 404). - At resolve time the resolver only ever sees `theme.template`. This is why a non-reserved `theme.name` automatically loads your template — no need to also list it in `config.plugins`. ## Template localisation The `i18n` config still applies — the active locale is passed to your template as a normal local. Translations are looked up via the `t(key)` helper as in the default templates. ## API reference ### `resolveTemplate(ctx)` from `@docmd/ui` ```ts import { resolveTemplate } from '@docmd/ui'; const resolved = resolveTemplate({ type: 'layout', // any TemplateSlot pagePath: '/guide/intro.html', frontmatter: page.frontmatter, // may carry `template: "..."` config, // normalised site config localeId: 'en', // optional versionId: '0.8', // optional }); // resolved.templatePath → absolute path to the .ejs file // resolved.source → 'default' | 'frontmatter' | 'config' | 'plugin' // resolved.pluginName → plugin name (when source === 'plugin') // resolved.type → the resolved slot ``` ### Types from `@docmd/api` ```ts import type { TemplateSlot, // union of 12 slot names TemplateHook, // { type, templatePath, priority?, pages?, exclude? } TemplateAssetHook, // { type: 'css'|'js', path, priority?, position? } ResolvedTemplate, TemplateResolutionContext, Capability, // now includes 'template' } from '@docmd/api'; ``` ## Troubleshooting ### "Template declared slot X but file not found" The template's `index.js` listed a `templatePath` that does not exist on disk. The resolver fell back to the default. Check the path is absolute (use `fileURLToPath(import.meta.url)`) and the file is included in the published package's `files` field. ### My template's CSS is being overridden by something else CSS priority is final. User `customCss` (priority 15) always wins. If you want users to be able to override specific selectors without overriding the whole template, document the public CSS class names and let users target them with `customCss`. ### Per-page template override not working Make sure the frontmatter `template` value matches a registered plugin. The resolver matches against the plugin's `descriptor.name`, stripping `@docmd/` and `template-` prefixes. So all of these are equivalent: - `template: "summer"` - `template: "template-summer"` - `template: "@docmd/template-summer"` If none of those match, the resolver falls through to `config.theme.template` and then the default. --- ## [JavaScript Engine](https://docs.docmd.io/development/engines/js/) --- title: "JavaScript Engine" description: "Deep explore docmd's native JavaScript execution engine: use cases, portability, capabilities, and limits." --- The **JavaScript Engine** is the foundational execution engine bundled into docmd. It runs easily on modern JavaScript runtimes. It delivers excellent performance without external dependencies or complex compilers. By default, every docmd repository relies on the JavaScript engine. It provides highly reliable file traversal, metadata indexing, and build generation. ## Configuration To explicitly instruct docmd to utilise the JavaScript backend, define the `engine` property as `"js"` inside `docmd.config.json`. ```json "docmd.config.json" { "title": "Developer Handbook", "engine": "js", "src": "docs", "out": "site" } ``` ## Ideal Use Cases & Where It Shines The JavaScript engine is exceptionally versatile. It shines under the following conditions: - **Standard Repositories**: Sites containing up to several hundred pages build extremely fast. It leverages optimised JIT compilation and native JSON parsing. - **Maximum Portability**: If your team uses diverse operating systems or restricted enterprise networks, the JavaScript engine guarantees flawless builds everywhere. - **Rapid Prototyping**: Local development builds benefit from instantaneous hot-reloading (`npx @docmd/core dev`) with low initialisation latency. - **Custom Scripting**: Configuration fallbacks and plugin integrations execute naturally within JavaScript. Standard string parsing avoids cross-boundary serialisation costs. ## Available Devices & Host Compatibility Because it operates entirely within native runtime environments, the JavaScript engine supports an exhaustive array of target platforms: - **Operating Systems**: macOS, Linux, Windows, FreeBSD, and OpenBSD. - **Hardware Architectures**: x64, ARM64 (Apple Silicon, AWS Graviton), ARMv7, and RISC-V. - **Container Environments**: Alpine Linux, standard Debian/Ubuntu, serverless build runners (Vercel, Netlify), and embedded CI pipelines. ## Capabilities & Limitations | Dimension | JavaScript Engine Profile | Operational Impact | | :--- | :--- | :--- | | **Concurrency Model** | Node.js Event Loop + Native Worker Threads | Excellent asynchronous scheduling for network responses. Disk-heavy blocks operate smoothly. | | **Git Metadata Handling** | Subprocess Orchestration (`child_process.execFile`) | Safely spawns native Git binaries to harvest commit histories. Includes persistent disk caching. | | **Setup & Initialisation** | Zero-Configuration | Boots instantaneously. No package postinstall compilation required. | | **Scalability Ceiling** | Highly Performant up to ~1,000 documents | On monolithic repositories exceeding a thousand complex files, sequential subprocess overhead may introduce minor latencies. | ## Feature Completeness The JavaScript engine is **exclusive in its universal feature support**. Every core feature, advanced syntax, templating zone, and official plugin is engineered to run easily here. Whether compiling mathematical formulas, rendering live search indices, or generating static site maps, the JavaScript engine guarantees deterministic builds. --- ## [Engines Overview](https://docs.docmd.io/development/engines/overview/) --- title: "Engines Overview" description: "Understand the pluggable build engine architecture and select the best processing backend." --- The compiler features a highly modular, multi-threaded **Pluggable Engine Architecture**. It decouples orchestration from computational tasks to execute heavy workloads efficiently. Choose between the zero-configuration **JavaScript Engine** and the accelerated **Rust Engine**. Select the engine based on your repository size, platform, and performance needs. ## Available Engines | Engine | Identifier | Default | Target Use Case | Key Strength | | :--- | :--- | :---: | :--- | :--- | | **JavaScript Engine** | `"js"` | ✅ Yes | Standard websites, rapid local prototyping, portability. | Runs universally on any device supporting Node.js. | | **Rust Engine (Preview)** | `"rust"` | ❌ No | Massive repositories (1,000+ files), enterprise CI/CD builds. | Maximises parallel file I/O via Tokio. | ## Configuration Options Configure your build engine in the `docmd.config.json` file. Set the `engine` parameter directly. ```json "docmd.config.json" { "title": "Enterprise Reference", "engine": "js", "src": "docs", "out": "site" } ``` ### Complete Options Reference | Key | Supported Values | Default | Description | | :--- | :--- | :--- | :--- | | `engine` | `"js"`, `"rust"` | `"js"` | The execution layer processing file discovery and batch reads. | ## High-Level Capabilities & Limitations Both engines share a rigorous execution boundary. The core API layer enforces uniform security and deterministic output. ### Shared Capabilities - **Thread Isolation**: Engines execute asynchronous tasks securely inside isolated worker threads. This prevents blocking the primary server loop. - **Task Verification**: Strict allowlists prevent unauthorised disk access or unverified execution patterns. - **Seamless Interoperability**: Plugins request data via standardised interfaces (`runWorkerTask`). They remain unaware of the underlying backend. ### Architectural Limitations - **Serialisation Overhead**: Data crosses native runtime boundaries (N-API). Highly iterative tasks passing large JSON objects incur a small serialisation penalty. - **Binary Compatibility**: The JavaScript engine runs natively everywhere. The Rust engine relies on OS-specific platform binaries distributed via npm. ## How the Engine Loader Works When `@docmd/core` boots, the internal loader inspects your active configuration: 1. **Resolution**: If configured for `"rust"`, the engine lazy-loads the architecture-specific native package (e.g., `@docmd/engine-rust-darwin-arm64`). 2. **Graceful Fallback**: If the binary is missing or unsupported, the engine logs an advisory notice. It then transparently falls back to the JavaScript engine. Your build always succeeds. Explore the deep-dive documentation for each engine: - [JavaScript Engine Reference](js.md) - [Rust Engine Reference](rust.md) --- ## [Rust Engine](https://docs.docmd.io/development/engines/rust/) --- title: "Rust Engine" description: "Explore the optional native Rust engine: use cases, file I/O capabilities, supported packages, and limitations." --- The **Rust Engine** is an optional, high-performance execution engine. It accelerates heavy I/O workloads in massive documentation projects. By using native binaries through N-API, it bypasses standard event-loop constraints to deliver multi-threaded file reading and subprocess orchestration. Available as an **experimental preview**, the Rust engine targets enterprise scale. It shines where thousands of markdown files and exhaustive Git logs introduce compilation bottlenecks. ## Configuration To activate native Rust acceleration, configure the `engine` directive to `"rust"` within your `docmd.config.json` file. ```json "docmd.config.json" { "title": "Global API Registry", "engine": "rust", "src": "docs", "out": "site" } ``` ## Ideal Use Cases & Where It Shines The Rust engine solves specific compilation bottlenecks. It provides excellent efficiency gains under the following scenarios: - **Massive Repositories (1,000+ Files)**: Monolithic projects benefit immensely from asynchronous, parallel file system access orchestrated via Tokio. - **Intensive Git Metadata Harvesting**: Extracting deep commit logs across hundreds of pages requires heavy subprocess spawning. The Rust engine processes `git:log` tasks up to **1.24× faster** than JavaScript. - **Cold Build Acceleration in CI/CD**: In environments where warm disk caches are unavailable, raw file read throughput reduces total processing time. Real-world benchmarks demonstrate a **~25% speedup during cold builds** and a **~17% improvement on warm builds**. ## Supported Devices & Platform Packages The engine executes pre-compiled machine code. It requires dedicated native binaries tailored to your target host architecture. The foundational `@docmd/engine-rust` package automatically lazy-loads the correct platform binary during startup. The following platform packages are currently distributed: | Platform Package | Target Architecture | Host Operating System | | :--- | :--- | :--- | | `@docmd/engine-rust-darwin-arm64` | ARM64 (Apple Silicon) | macOS | | `@docmd/engine-rust-darwin-x64` | x64 (Intel) | macOS | | `@docmd/engine-rust-linux-x64-gnu` | x64 | Linux (glibc environments) | | `@docmd/engine-rust-linux-arm64-gnu` | ARM64 | Linux (glibc environments) | | `@docmd/engine-rust-win32-x64-msvc` | x64 | Windows | ::: callout info "Transparent Graceful Fallback" If your environment lacks an available pre-built binary, the engine logs a non-fatal notification and **automatically falls back** to the high-performance JavaScript engine. Your builds remain fully deterministic. ::: ## Capabilities & Strategic Limitations To achieve maximum utility, you must understand its architectural trade-offs. The engine excels at I/O-bound operations but incurs overhead during cross-boundary serialisation. | Capability / Task | Rust Engine Performance Profile | Architectural Verdict | | :--- | :--- | :--- | | **Batch File Discovery & Reads** | Accelerated via parallel Tokio workers. | ✅ Highly Effective for massive directories. | | **Git Commit Log Harvest** | Fast subprocess orchestration bypassing Node event loops. | ✅ Excellent for cold-start Git metadata extraction. | | **Persistent Disk Caching** | Native support for anchored disk caches to eliminate redundant reads. | ✅ Highly Effective for warm builds. | | **CPU-Bound Search Indexing** | **Slower than native JavaScript JIT**. | ❌ Inefficient due to double serialisation overhead. | ### The Double-Serialisation Tax Explained Communication between docmd's core orchestrator and the native Rust engine relies on stringified JSON passing across the N-API runtime boundary: ```text JS Worker → JSON.stringify() → NAPI Boundary → Serde Deserialisation → [Rust Task] → Serde Serialisation → NAPI Boundary → JSON.parse() ``` For I/O-heavy operations like querying Git histories or reading disk buffers, the processing time saved vastly outweighs the string conversion cost. However, for highly iterative, CPU-bound tasks like full-text search indexing (`search:index`), **the serialisation round-trip consumes more CPU resources than the underlying task itself**. Serialising large arrays of content back and forth causes the Rust implementation to run slower than Node's native JIT string manipulation. As a result, **the JavaScript engine remains the recommended runtime for semantic search pipelines**. Enable the Rust engine selectively for large-scale Git and file management workloads. --- ## [Node API Reference](https://docs.docmd.io/development/node-api-reference/) --- title: "Node API Reference" description: "Low-level Node API for plugin authors — URL utilities, action dispatchers, source tools, the engine loader, and TypeScript types." --- ::: callout info **For plugin authors.** If you just want to *call* docmd from a Node script, see [Build API](/reference/build-api) instead. This page covers the lower-level utilities exposed by `@docmd/api` for writing plugins. ::: The `@docmd/api` package is the dedicated home for the plugin system. It provides hook registration, WebSocket RPC dispatch, source editing tools, and centralised URL utilities. ```bash npm install @docmd/api ``` ::: callout tip **Note:** All exports from `@docmd/api` are also available from `@docmd/core`. New projects should import directly from `@docmd/api`. ::: ## URL Utilities Plugins should use these centralised utilities instead of rolling their own URL logic. ### `outputPathToSlug(outputPath)` Convert a build engine output path to a clean directory-style slug. ```javascript import { outputPathToSlug } from '@docmd/api'; outputPathToSlug('guide/index.html'); // → 'guide/' outputPathToSlug('index.html'); // → '/' outputPathToSlug('de/v1/api/index.html'); // → 'de/v1/api/' ``` ### `outputPathToPathname(outputPath)` Convert to a root-relative pathname. ```javascript import { outputPathToPathname } from '@docmd/api'; outputPathToPathname('guide/index.html'); // → '/guide/' outputPathToPathname('index.html'); // → '/' ``` ### `outputPathToCanonical(outputPath, siteUrl)` Build a full canonical URL. ```javascript import { outputPathToCanonical } from "@docmd/api"; outputPathToCanonical("guide/index.html", "https://docs.example.com"); ``` ### `sanitizeUrl(url)` Collapse double slashes (except after protocol). ```javascript import { sanitizeUrl } from "@docmd/api"; sanitizeUrl("https://docs.example.com//guide"); // → "https://docs.example.com/guide" sanitizeUrl("/foo//bar"); // → "/foo/bar" ``` ### `buildAbsoluteUrl(base, localePrefix, versionPrefix, pagePath)` Build an absolute URL with locale and version prefixes. ```javascript import { buildAbsoluteUrl } from '@docmd/api'; buildAbsoluteUrl('/', 'de/', 'v1/', 'guide/'); // → '/de/v1/guide/' ``` ### `resolveHref(href)` Normalise user-written hrefs to clean URLs. Handles `.md` stripping, trailing slashes, `external:` and `raw:` prefixes. ```javascript import { resolveHref } from "@docmd/api"; resolveHref("overview.md"); // → "overview/" resolveHref("external:https://github.com"); // → "https://github.com" resolveHref("raw:docs/readme.md"); // → "docs/readme.md" ``` ## Pre-computed Page URLs Every page object includes pre-computed URL data. Plugins can read these directly with zero computation needed. ```javascript export async function onPostBuild({ pages, config }) { for (const page of pages) { console.log(page.urls.slug); console.log(page.urls.canonical); console.log(page.urls.pathname); } } ``` | Property | Type | Description | |:---------|:-----|:------------| | `slug` | `string` | Clean directory-style slug (e.g., `guide/` or `/`) | | `canonical` | `string` | Full canonical URL (only if `config.url` is set) | | `pathname` | `string` | Root-relative path (e.g., `/guide/`) | ## Action & Event Dispatch ### `createActionDispatcher(hooks, options)` Creates a dispatcher that routes WebSocket RPC messages to plugin action/event handlers. ```javascript import { createActionDispatcher } from "@docmd/api"; const dispatcher = createActionDispatcher( { "actions": myPlugin.actions, "events": myPlugin.events }, { "projectRoot": "/path/to/project", config, broadcast } ); const { result, reload } = await dispatcher.handleCall("my-action", payload); ``` ### `createSourceTools({ projectRoot })` Creates source editing utilities for markdown file manipulation. ```javascript import { createSourceTools } from "@docmd/api"; const source = createSourceTools({ "projectRoot": "/path/to/project" }); const block = await source.getBlockAt("docs/page.md", [10, 12]); await source.wrapText("docs/page.md", [10, 12], "important", 0, "**", "**"); ``` ### `loadPlugins(config, options)` Loads, validates, and registers all plugins declared in the config. Returns the populated hooks registry. ```javascript import { loadPlugins, hooks } from "@docmd/api"; const registeredHooks = await loadPlugins(config, { "resolvePaths": [__dirname] }); ``` ## Engine Loader API The pluggable engine architecture allows programmatic resolution and instantiation of acceleration layers directly via `@docmd/api`. ### `loadEngine(engineName)` Resolves and initialises the requested build engine backend. If native architecture binaries are unavailable, it gracefully falls back to the high-performance JavaScript engine. ```javascript import { loadEngine } from "@docmd/api"; const engine = await loadEngine("rust"); const gitLogResult = await engine.runWorkerTask("git:log", { "paths": ["docs/guide.md"] }); ``` ### `registerEngine(engineName, engineInstance)` Allows custom tools or third-party integrators to register custom execution engines programmatically. ```javascript import { registerEngine } from "@docmd/api"; registerEngine("custom", myCustomEngineImpl); ``` ## Type Exports For TypeScript plugin authors, the following types are available: ```typescript import type { PluginModule, PluginDescriptor, PluginHooks, PageContext, BeforeBuildContext, PostBuildContext, Capability, ActionContext, ActionHandler, EventHandler, SourceTools, BlockInfo, TextLocation, Engine, } from '@docmd/api'; ``` ## What's Next - [Building Plugins](/development/building-plugins) — start here. - [Plugin Examples](/development/plugin-examples) — see a full plugin walkthrough. - [Engines & Architecture](/development/engines/overview) — Rust engine, N-API, and engine loader internals. --- ## [Extending docmd with Custom Plugins](https://docs.docmd.io/development/plugin-examples/) --- title: "Extending docmd with Custom Plugins" description: "How to use docmd's lifecycle hooks to build custom functionality and extend the documentation engine." --- ## 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](../../plugins/building-plugins.md). 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. ```javascript // 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. ```javascript 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. --- ## [Setup](https://docs.docmd.io/development/setup/) --- title: "Setup" description: "Run this docs site locally, link to your global docmd install, and run the full verification pipeline." --- # Setup ::: callout info **For docs-site contributors.** Want to *contribute* to docmd itself (the framework)? See the [GitHub Contributing guide](https://github.com/docmd-io/docmd?tab=contributing-ov-file) instead — that's where the framework development workflow lives. ::: This page covers working on **this documentation site** (`docmd-io/docs`), not on the docmd framework (`docmd-io/docmd`). ## Prerequisites - **Node.js**: v22.x or later (LTS recommended) - **pnpm**: v10.x or later ## Local Development ```bash git clone https://github.com/docmd-io/docs.git cd docs pnpm install npx @docmd/core dev ``` The site is served at `http://localhost:3000` with live reload. ### Watching the framework locally If you're editing framework code in `docmd-io/docmd` and want to see changes reflected in this docs site: ```bash # In the framework repo pnpm build # In this docs repo, link the local build npx @docmd/core link ../docmd/packages/core ``` Then restart `npx @docmd/core dev`. Your changes to the framework will be picked up after a framework rebuild. ## Quality Gates Before opening a Pull Request: ```bash # Lint Markdown and check for broken links pnpm lint # Full verification pipeline (lint + build + dead-link check) pnpm verify ``` The verification pipeline mirrors what the maintainers run on every PR. A green run is required for merge. ## Translations Translation workflow for adding/updating `de/` and `zh/` content: 1. Edit the EN source in `docmd-main/v08/en/...`. 2. Mirror the change in `de/` and `zh/` (same path, translated prose, preserved frontmatter keys, preserved container markers, code blocks unchanged). 3. Preserve all file titles on codeblocks (e.g. ` ```json "docmd.config.json"`). 4. Run `pnpm verify` to confirm links and structure still hold. See the project memory for the translation house style and codeblock file-title rule. ## Project Layout ``` docs/ ├── docmd-main/v08/ │ ├── en/ # Canonical English source │ ├── de/ # German translations (mirrors en/) │ ├── zh/ # Chinese translations (mirrors en/) │ └── navigation.json # Single nav, replicated per locale ├── docmd-search/ # Search index assets ├── docs/ # Other doc projects (docmd-search, docmd-main, etc.) └── package.json ``` ## What's Next - [Building Plugins](/development/building-plugins) — write a custom docmd plugin. - [Plugin Examples](/development/plugin-examples) — see a complete plugin walkthrough. - [Building Templates](/development/building-templates) — author a docmd template. - [Node API Reference](/development/node-api-reference) — programmatic build API. --- ## [Installation](https://docs.docmd.io/getting-started/installation/) --- title: "Installation" description: "Install @docmd/core globally, locally within a project, or run containerised via the official Docker image. Requires Node.js 18+." --- Choose the installation method that fits your workflow. Node.js 18 or higher is required for local builds. ## 1. Local Installation (Recommended) Running `docmd` locally keeps your documentation configuration versioned with your source code. ::: tabs == tab "npm" icon:box ```bash # Install as a development dependency npm install -D @docmd/core # Initialise a new project npx docmd init ``` == tab "pnpm" icon:boxes ```bash # Install as a development dependency pnpm add -D @docmd/core # Initialise a new project pnpm dlx docmd init ``` == tab "yarn" icon:scroll ```bash # Install as a development dependency yarn add -D @docmd/core # Initialise a new project yarn dlx docmd init ``` == tab "Bun" icon:zap ```bash # Install as a development dependency bun add -D @docmd/core # Initialise a new project bunx docmd init ``` == tab "Docker" icon:container ```bash # Pull the official multi-architecture image docker pull ghcr.io/docmd-io/docmd:latest # Build documentation from local docs/ to site/ docker run -v $(pwd)/docs:/docs -v $(pwd)/site:/site ghcr.io/docmd-io/docmd:latest build ``` See the [Docker Deployment Guide](../deployment/docker.md) for Docker Compose and Kubernetes configurations. ::: <img width="500" class="with-border" src="/assets/previews/terminal-npx-init.webp"> ::: callout tip "Shorthand Scripts" icon:sparkles Once installed locally, you can use `npx docmd dev` to start the live preview server, or add scripts directly to your `package.json`. ::: ## 2. Global Installation Install the package globally to create or preview sites anywhere on your system without creating a local project. ::: tabs == tab "npm" icon:box ```bash npm install -g @docmd/core ``` == tab "pnpm" icon:boxes ```bash pnpm add -g @docmd/core ``` == tab "yarn" icon:scroll ```bash yarn global add @docmd/core ``` == tab "Bun" icon:zap ```bash bun add -g @docmd/core ``` ::: Once installed, the `docmd` binary is available everywhere: ```bash docmd dev # Start a dev server locally docmd build # Build static output ``` ## 3. Browser-Only Integration Embed the engine directly inside an existing web application via CDN. ::: callout info "Specialised Library Integration" icon:help-circle This bypasses the CLI and loads the parsing engine in the reader's browser. Use this for dynamic portals, not static SEO websites. ::: Add the stylesheet and JavaScript engine to your HTML. ```html <!-- Core Stylesheet --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- Isomorphic Rendering Engine --> <script src="https://unpkg.com/@docmd/live/public/docmd-live.js"></script> ``` See the [Browser API Guide](../api/browser-api.md) for full integration details. ## 4. Troubleshooting ### Permission Denied (`EACCES` Errors) Do not use `sudo` for global installs on macOS or Linux. Fix permission conflicts using a Node.js version manager like [nvm](external:https://github.com/nvm-sh/nvm) or [fnm](external:https://github.com/Schniz/fnm). ### PowerShell Execution Policies (Windows) If Windows blocks execution, open PowerShell as administrator and enable current-user script execution. ```powershell Set-ExecutionPolicy RemoteSigned -Scope CurrentUser ``` --- ## [Project Structure](https://docs.docmd.io/getting-started/project-structure/) --- title: "Project Structure" description: "Learn how `@docmd/core` maps physical folders and Markdown files to dynamic URLs and clean navigation." --- The compiler uses your local filesystem as the source of truth. Folders become navigation sections. Markdown files become content pages. Your directory hierarchy translates directly into web URLs. ## 1. Standard Project Scaffold Run `npx @docmd/core init` to establish a minimal workspace layout. This structure keeps source content separated from assets and production builds. ```text my-docs/ ├── docs/ ← Source directory containing your Markdown (.md) pages │ └── index.md ← The landing page (resolves to /) ├── assets/ ← Static web assets loaded directly by the engine │ ├── css/ ← Custom stylesheets for customising page layout │ ├── js/ ← Custom scripts to extend browser-side logic │ └── images/ ← Brand logos, icons, and inline illustrations ├── docmd.config.json ← Central configuration schema ├── package.json ← Node dependency manifest and scripts └── site/ ← Optimised production build output folder ``` ::: callout info "Configuration File Resolution" icon:settings `docmd.config.json` (or `docmd.config.ts`) is the recommended, primary configuration format. The legacy `docmd.config.js` format remains supported but acts strictly as a fallback when `.json` or `.ts` configuration files are missing. ::: ## 2. Directory and URL Mapping The compiler maps files within your source folder directly to public URLs. There are no trailing `.html` extensions or complex routing rules. | Source File | Resolved URL Path | Purpose | | :--- | :--- | :--- | | `docs/index.md` | `/` | Home Landing Page | | `docs/api.md` | `/api` | Main API Reference | | `docs/guides/setup.md` | `/guides/setup` | Sub-section Technical Guide | | `docs/getting-started/quick-start.md` | `/getting-started/quick-start` | Multi-level deep page | ::: callout tip "Automatic Header Parsing" icon:info If a file lacks a `title` in its YAML frontmatter, the engine extracts the first `H1` tag (`# Heading`). This title represents the page in breadcrumbs and search. ::: ## 3. Workspace Monorepo Structure For complex layouts or large projects with multiple distinct products (such as a core platform, an SDK, and a CLI tool), `docmd` natively supports a **Workspace Monorepo** directory structure. This allows you to manage multiple independent documentation sites from a single root repository while maintaining unified branding. ```text my-docs-monorepo/ ├── docmd.config.json ← Root configuration (defines global settings) ├── assets/ ← Shared global assets (inherited by all projects) │ ├── css/ ← Shared global stylesheets │ └── images/ ← Shared logos and icons ├── package.json ← Root dependency manifest ├── main-site/ ← Root project directory │ ├── docmd.config.json ← Project-specific config overrides │ └── docs/ ← Content for main-site (resolves to /) │ └── index.md └── sdk-reference/ ← Secondary project directory ├── docmd.config.json ← Project-specific config overrides └── docs/ ← Content for sdk-reference (resolves to /sdk) └── index.md ``` ### Key Workspace Directory Patterns * **Global Configuration Cascading:** Any configuration defined in the root `docmd.config.json` (such as `theme` or `menubar`) acts as a fallback default. Individual projects can selectively override these defaults in their own local config files. * **Asset Sharing and Priority:** Shared logos, global custom styles, and common scripts are placed in the root `assets/` directory. Projects can also define their own local `assets/` directories; in the event of filename conflicts, project-specific assets always take precedence. * **Output Consolidation:** During the build process (`npx @docmd/core build`), the engine automatically merges all projects into a single consolidated production output directory (e.g. `./site/` and `./site/sdk/`), negating the need for complex reverse proxy setups or isolated build pipeline configuration. For complete setup steps and advanced cascading rules, refer to the [Workspaces Configuration Guide](../configuration/workspaces.md). --- ## [Quick Start](https://docs.docmd.io/getting-started/quick-start/) --- title: "Quick Start" description: "Go from an empty folder to a running documentation site in under a minute." --- Run docmd inside any folder with Markdown files. No config file, setup, or framework knowledge required. ## 1. Start a dev server ::: tabs == tab "npm" icon:box ```bash npx @docmd/core dev ``` == tab "Bun" icon:zap ```bash bunx @docmd/core dev ``` ::: This opens `http://localhost:3000`. Your documentation is live. <img width="500" class="with-border" src="/assets/previews/terminal-npx-dev.webp"> ::: callout tip "Automatic Port Failover" icon:info If port `3000` is in use, docmd automatically finds the next available port (e.g., `3001`). ::: ## 2. Automatic features The engine sets up everything automatically: 1. **Directory Detection**: Scans for `docs/`, `src/docs/`, `documentation/`, `content/`, or any `.md` files in the project root. 2. **Navigation Structuring**: Builds a nested sidebar from your folder tree. 3. **Title Resolution**: Extracts page titles from the first `H1` tag automatically. 4. **Search Indexing**: Enables built-in full-text search immediately. 5. **Smart Caching**: Triggers sub-200ms rebuilds instantly on file save. No `docmd.config.json` is required. Add one later to customise layouts, plugins, or versions. ## 3. Build for production Compile your Markdown files into a static, production-ready site. ::: tabs == tab "npm" icon:box ```bash npx @docmd/core build ``` == tab "Bun" icon:zap ```bash bunx @docmd/core build ``` ::: The compiler outputs a static site to `./site/`. Host this static output anywhere. Deploy to GitHub Pages, Vercel, Netlify, or any static host. --- ## [Context Preservation for AI-Friendly Documentation](https://docs.docmd.io/guides/ai-optimisation/context-preservation/) --- title: "Context Preservation for AI-Friendly Documentation" description: "How to ensure that AI models can understand and utilise the relationships between different parts of your documentation." --- ## Problem Human readers can click hyperlinks to learn more. AI models often process documentation in isolated "chunks". When an AI encounters a hyperlink, it cannot "click" it to fetch context. If critical information is hidden behind a link, the AI may fail to provide accurate answers. This leads to hallucinations. ## Why it matters AI models rely on immediate surrounding text to determine meaning. If your documentation is highly fragmented with poor context preservation, AI-driven search tools (like RAG systems) will struggle to provide high-quality responses. ## Approach Use **Inline Context Unrolling** to provide the minimum viable context alongside every major link. Use docmd's [LLMs Plugin](../../plugins/llms.md) to provide a unified, machine-readable view of your entire documentation set. ## Implementation ### 1. Descriptive Linking and Summaries Avoid generic link text. Provide a brief, one-sentence summary of the linked concept alongside the link. - **❌ Poor (Context Lost)**: To configure the timeout, refer to the [General Configuration](../../configuration/overview.md). - **✅ Better (Context Preserved)**: You can configure the `timeoutMs` parameter within the [General Configuration](../../configuration/overview.md), which defines how long the engine waits before failing a network request. ### 2. Using Collapsible Sections for Detail [Collapsible Containers](../../content/containers/collapsible.md) are excellent for AI optimisation. The content remains part of the raw Markdown source for the AI, but it is visually tucked away for human readers. ```markdown ### Database Connection Connect using the primary URI. ::: collapsible "What is the URI format?" The URI follows the standard PostgreSQL format: `postgresql://user:password@host:port/database`. ::: ``` ### 3. Enabling the LLMs Plugin Enable the [LLMs Plugin](../../plugins/llms.md) in your `docmd.config.json`. This plugin generates a `llms-full.txt` file after every build. It concatenates your entire documentation set into a single, high-context file that LLMs consume easily. ## Trade-offs Inline context unrolling makes documentation slightly more verbose and introduces minor redundancy. However, this is a small price to ensure your documentation is "AI-ready" and capable of powering high-quality automated support. --- ## [Creating Deterministic and Chunkable Documentation](https://docs.docmd.io/guides/ai-optimisation/deterministic-chunkable-docs/) --- title: "Creating Deterministic and Chunkable Documentation" description: "How to structure your documentation to optimise it for Retrieval-Augmented Generation (RAG) and AI ingestion." --- ## Problem When AI pipelines ingest documentation, they slice the Markdown into smaller "chunks". If a document consists of long paragraphs with unclear boundaries, the algorithm splits context mid-thought. This destroys the chunk's utility and leads to incorrect AI responses. ## Why it matters If an AI retrieves a code block but misses the preceding paragraph explaining *when* to use it, the answer lacks conditionality. Structuring your documentation for chunkability ensures each segment contains enough context to be useful on its own. ## Approach Structure your pages as a hierarchy of deterministic, atomic blocks. Use Markdown headers to clearly delineate concepts. Ensure related information (like a warning and the code it applies to) is kept physically close together in the source file. ## Implementation ### 1. Atomic Header Sections Ensure every `##` or `###` header encapsulates a single, atomic concept. A well-structured section should stand alone as a useful chunk for an AI model. - **✅ Good**: A header "Authentication via OAuth" followed by a brief explanation and a code example. - **❌ Poor**: A massive "Getting Started" page with 15 different concepts and no sub-headers. ### 2. Tight Proximity for Critical Information Do not separate a critical warning from the code it applies to with long paragraphs. Use [Callouts](../../content/containers/callouts.md) to bind them together vertically. This increases the probability that they remain in the same vector chunk during ingestion. ```markdown ::: callout warning "Destructive Action" Running this command will permanently delete all logs. ::: `npx @docmd/core logs --clear` ``` ### 3. Automated Concatenation The [LLMs Plugin](../../plugins/llms.md) facilitates chunking by generating a `llms-full.txt` file. This uses standard separators (`---`) between pages. It helps ingestion pipelines recognise natural document boundaries while preserving global context. ## Trade-offs This approach favours a modular, segmented writing style over long, flowing narratives. While it may feel repetitive to a human reader, it significantly improves the performance of AI-powered search and automated support agents. --- ## [Generating AI-Ready Documentation with docmd](https://docs.docmd.io/guides/ai-optimisation/generating-ai-ready-docs/) --- title: "Generating AI-Ready Documentation with docmd" description: "How to use the llms.txt standard and docmd's built-in tools to provide optimised context for AI assistants." --- ## Problem Developers increasingly rely on AI coding assistants to read and interpret documentation. If your documentation is only accessible via a web browser - cluttered with navigation elements, trackers, and complex HTML - AI agents consume excessive tokens on irrelevant data. This quickly exhausts their context windows. ## Why it matters Providing a clean, token-optimised text version of your documentation is the modern equivalent of providing a high-quality REST API. It ensures AI agents can quickly ingest your entire documentation set. This results in more accurate code suggestions and better support. ## Approach Use docmd's built-in **LLMs Plugin**. This plugin natively implements the emerging `llms.txt` standard. It automatically generates token-optimised summaries and full-context files during every build process. ## Implementation Configure the `llms` plugin in your [Plugin Configuration](../../plugins/llms.md). ### 1. Configure the Site URL Ensure the `url` property is correctly set in your `docmd.config.json`. This allows the plugin to generate absolute URLs for all pages in the `llms.txt` file. ```json "docmd.config.json" { "title": "My Project Docs", "url": "https://docs.example.com", "plugins": { "llms": {} } } ``` ### 2. Output Files During the build process, docmd generates two key files in your site root: - **`llms.txt`**: A concise, structured Markdown summary of all your pages, including their titles, descriptions, and full URLs. - **`llms-full.txt`**: A comprehensive file containing the raw Markdown content of your entire site, concatenated with standard separators (`---`). This provides the ultimate "source of truth" for AI models. ### 3. Controlling Ingestion You can exclude specific pages from the AI-ready output using the `llms` property in the [Page Frontmatter](../../content/frontmatter.md). ```yaml --- title: "Internal Debugging Guide" llms: false --- ``` ## Trade-offs Generating `llms-full.txt` creates a large single file. For exceptionally large documentation sites, this file could exceed several megabytes. While ideal for modern LLMs with large context windows (like Gemini 1.5 Pro or Claude 3.5 Sonnet), it may be too large for smaller models. Ensure you organise your [Navigation](../../configuration/navigation.md) logically so the AI can prioritise important sections. --- ## [MCP & Agent Skills](https://docs.docmd.io/guides/ai-optimisation/mcp-and-agent-skills/) --- title: "MCP & Agent Skills" description: "Optimise your documentation workspace for AI development agents using the Model Context Protocol and custom Skills." --- Integrating AI development agents into your workflow requires structured interfaces that allow models to query, read, and write documentation context efficiently. `docmd` satisfies this need via a native **Model Context Protocol (MCP)** server and an extensible **Agent Skills** database. ## Model Context Protocol (MCP) Setup The Model Context Protocol connects LLM environments directly to your local workspace tools. ### 1. Claude Desktop Integration Add the following to your desktop configuration file (typically at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\Claude\claude_desktop_config.json` on Windows): ```json "claude_desktop_config.json" { "mcpServers": { "docmd": { "command": "npx", "args": ["@docmd/core", "mcp"], "cwd": "/path/to/your/docs/project" } } } ``` ### 2. IDE Integration (Cursor / Windsurf) In your editor's MCP settings panel, add a new server using the `stdio` transport: - **Command**: `npx @docmd/core mcp` - **Transport**: `stdio` ## Available MCP Tools Once connected, the following tools become available to the agent: 1. `search_docs(query)`: Performs a workspace-wide full-text search. 2. `list_docs(subdir?)`: Lists every markdown file in the project, optionally scoped to a subdirectory (a locale, a version, a guide section). Use this to navigate the docs tree before reading individual files. 3. `read_doc(route)`: Retrieves the raw Markdown contents of a specific route. The route must resolve inside the project root. 4. `get_config()`: Returns the resolved `docmd.config` — title, source and output directories, locales, versions, and enabled plugins. Sensitive values (API keys, analytics IDs) are stripped from the response. 5. `validate_docs()`: Lints the entire documentation and returns validation errors (e.g., broken links). 6. `get_llms_context()`: Fetches the consolidated `llms-full.txt` context file. ## Leveraging Agent Skills (`SKILL.md`) When you run `docmd init` in your project, the engine automatically generates a `SKILL.md` file in your root workspace. This file serves as a prompt instruction card for any AI agent working on your repository. ### Best Practices for AI Agents 1. **Read SKILL.md First**: Instruct your agents to read the `SKILL.md` file at the start of a coding session. This teaches the model about custom Callouts, OpenAPI markup, and file structures. 2. **Validate After Edits**: Whenever an agent modifies Markdown files, it should call the `validate_docs` tool (or run `npx @docmd/core validate`) to verify that no relative links or anchor paths are broken. 3. **Synchronize Locales**: If the project uses versioning or multiple languages, agents should use the comparison matrix to ensure all translations stay in sync. --- ## [Minimising AI Hallucinations via Documentation](https://docs.docmd.io/guides/ai-optimisation/minimising-ai-hallucinations/) --- title: "Minimising AI Hallucinations via Documentation" description: "How to write explicit, self-contained documentation that prevents AI models from inventing incorrect information." --- ## Problem AI models are predictive engines, not reasoning engines. If an API usage example is incomplete, uses ambiguous placeholders, or relies on implicit knowledge, the AI will "hallucinate". It invents missing pieces based on general training patterns. These inventions are frequently incorrect, leading to developer frustration. ## Why it matters Hallucinated code destroys user trust. When a developer asks an AI for help and receives broken code, they blame the software for being "buggy" or "poorly documented". Minimising hallucinations is critical for maintaining your project's professional reputation. ## Approach Practice **Defensive Documentation**. Write extremely explicit, fully instantiated code blocks that leave no room for ambiguity. Never assume the reader (or the AI) knows the necessary imports, environment variables, or prerequisite configurations. ## Implementation ### 1. Fully-Qualified Code Blocks Always include the necessary imports or setup code in every snippet. This ensures that when an AI chunks your documentation, the code block remains a self-contained unit of truth. - **❌ Hallucination Risk**: ```javascript const config = loadConfig(); ``` - **✅ Hallucination Proof**: ```javascript import { loadConfig } from "@docmd/core"; const config = loadConfig(); ``` ### 2. Concrete Examples Over Placeholders Avoid using vague placeholders like `your-api-key` or `env-name`. Provide concrete, valid examples or use comments to specify strict enum requirements. ```javascript // Valid environments: "development", "staging", "production" const app = init({ env: "production" }); ``` ### 3. Inline Code Comments Place critical requirements *inside* the code block as comments, rather than only in surrounding paragraphs. AI models weigh comments within code highly when generating similar snippets. ```javascript // REQUIRED: Must be an absolute path outputPath: "/var/www/html/docs" ``` ### 4. Categorised Warnings Use [Callouts](../../content/containers/callouts.md) to clearly mark deprecated features or breaking changes. AI models are more likely to respect a `::: callout warning` block than a simple sentence in a paragraph. ## Trade-offs Defensive documentation makes code blocks longer and more repetitive. Human readers may find seeing the same `import` statements tedious. However, the benefit of having "AI-proof" documentation that reduces support tickets far outweighs the minor cost of verbosity. --- ## [OKF Bundles — Deep Dive](https://docs.docmd.io/guides/ai-optimisation/okf-bundles/) --- title: "OKF Bundles — Deep Dive" description: "How to organise your docmd content for the best OKF bundle — typed concepts, cross-links, and the discipline that makes an AI-agent-friendly knowledge base." --- The [`@docmd/plugin-okf`](../../plugins/okf.md) generates an [Open Knowledge Format][okf-spec] bundle from your docmd site. This guide explains what the bundle looks like, how to organise your content for the best AI-agent consumption, and how OKF differs from the [`llms.txt`](../../plugins/llms.md) flat-list format. [okf-spec]: https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing ## The mental model: a wiki, not a sitemap A traditional docs site is a tree — sections and subsections, with pages hanging off each one. A user navigates the tree top-down to find what they need. An OKF bundle is a **wiki** — a flat directory of typed concept files with cross-links between them. An AI agent navigates the graph horizontally, following links from one concept to its neighbors. The two structures look the same on disk (markdown files in directories), but the navigation model is different. The OKF spec's [three design principles][okf-principles] are worth quoting in full: > 1. **Minimally opinionated.** OKF requires exactly one thing of every concept: a `type` field. Everything else (what types exist, what other fields to include, what sections the body has) is left to the producer. > 2. **Producer/consumer independence.** A bundle hand-authored by a human can be consumed by an AI agent. A bundle generated by a metadata export pipeline can be browsed in a visualizer. A bundle synthesized by one LLM can be queried by another. The format is the contract; the tooling at each end is independently swappable. > 3. **Format, not platform.** OKF is not tied to any specific cloud, database, model provider, or agent framework. [okf-principles]: https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing ## What an OKF bundle looks like ```text site/okf/ ├── okf.yaml ← typed manifest ├── index.md ← Karpathy-style catalog ├── graph/ ← opt-in: only when plugins.okf.graph: true │ ├── index.html ← interactive force-directed viewer │ ├── graph.json ← graph data │ ├── graph.js ← viewer runtime │ └── graph.css ← viewer styles ├── concepts/ │ ├── weekly-active-users.md │ ├── orders-table.md │ └── api-authentication.md └── _meta/ ├── bundle.json └── lint-report.txt ``` Each `concepts/<slug>.md` file carries a `type` field in frontmatter plus the full markdown body of the page. The `okf.yaml` manifest lists every concept with its type, path, locale, version, and tags — the catalog that an AI agent uses to decide which concepts to read. ## What goes in a `type` The `type` field is the only required frontmatter key. It tells the agent what kind of knowledge this concept represents. The `@docmd/plugin-okf` plugin has a path-prefix type-inference map: | URL prefix | Inferred type | | :--- | :--- | | `/api/` | `api` | | `/guides/` | `guide` | | `/reference/` | `reference` | | `/concepts/` | `concept` | | `/runbooks/` | `runbook` | | `/datasets/` | `dataset` | | `/metrics/` | `metric` | | `/tables/` | `table` | | (anything else) | `concept` (default) | You can override the inferred type with explicit frontmatter: ```markdown --- type: api title: "Authentication API" description: "OAuth 2.0 + JWT auth flow for the user API." --- # Authentication API ... ``` Or use the nested `okf.type` form: ```markdown --- okf: type: api title: "Authentication API" --- ``` The agent reads the `type` field first. A concept with `type: runbook` is treated as a step-by-step playbook (e.g. "how to recover from a partial outage"); a concept with `type: api` is treated as API reference; a concept with `type: dataset` is treated as a data dictionary. ## Cross-links make the graph OKF is a graph, not a tree. The relationships between concepts are inferred from internal markdown links. If `api-authentication.md` links to `users-table.md`, the OKF bundle records that edge in `graph.json` and the graph viewer draws a line between the two nodes. The `okf-bundle` (read: "graph of concepts") is more useful than a tree because it lets the agent find related concepts the author didn't think to put in a sub-section. The LLM-wiki pattern that OKF formalises explicitly assumes the agent will follow links to discover adjacent knowledge. Best practices for cross-links: - **Link forward** — when introducing a concept, link to the concepts it depends on. "To use this, see [users table](../tables/users.md)". - **Link backward** — in the concept that depends on this one, link back. "Used by [API auth](../api/auth.md)". - **Don't over-link** — every link should add information. Linking every word dilutes the graph and confuses the agent. ## Per-page opt-out Some pages aren't useful to AI agents — legal boilerplate, internal "about the team" pages, marketing copy. Use `frontmatter.okf: false` to exclude a single page from the OKF bundle: ```markdown --- okf: false --- # Internal Roadmap (Q3 2026) ... ``` Or use `noindex: true` to exclude a page from every downstream consumer (sitemap, search, llms.txt, OKF). The two flags differ: - `okf: false` — excluded from OKF only; still in search and llms.txt - `noindex: true` — excluded from every downstream consumer ## How OKF differs from `llms.txt` The [`llms.txt` plugin](../../plugins/llms.md) produces a flat list of pages: ```text - [Page 1](https://example.com/page-1) - [Page 2](https://example.com/page-2) - [Page 3](https://example.com/page-3) ``` The OKF plugin produces a typed graph: ```yaml concepts: - id: api-authentication type: api title: "Authentication API" path: /api/auth/ file: concepts/api-authentication.md tags: [auth, security] - id: users-table type: table title: "Users table" path: /tables/users/ file: concepts/users-table.md tags: [schema, data] ``` The two complement each other: - **llms.txt** is for **flat consumption** — "give me everything". An agent reads the file and has the full text in its context window. - **OKF** is for **typed consumption** — "give me the schema for table X". An agent reads the manifest, picks the concepts it needs, and loads them selectively. For projects with under 50 pages, llms.txt alone is often enough. For projects with 50+ pages, OKF is the more efficient format — the agent doesn't have to load every page just to find the one it needs. ## Common mistakes ### 1. Skipping the `type` field The OKF manifest is most useful when every concept has a distinct `type`. If 80% of your pages are inferred as `concept`, the agent can't tell which are reference docs, which are tutorials, and which are runbooks. Set `type: <name>` explicitly for every page that has a clear category. ### 2. Pages with no cross-links If a page is a dead end (no internal links to or from it), the graph viewer shows it as an isolated node. The agent will read it in isolation, missing the context. Add at least one inbound link (referenced from another page) for every page you want surfaced. ### 3. Putting internal jargon in `description` The `description` field is shown in the manifest and in `llms.txt` summaries. An AI agent uses it to decide whether a concept is relevant. Use plain English the agent can match against a user query: "weekly active users for the marketing site, computed from the events stream", not "WAU (ms)". ### 4. OKF for non-AI-agent sites If your docs site has no AI-agent audience, OKF adds nothing. The `@docmd/plugin-okf` is enabled by default, so disable it explicitly: ```json { "plugins": { "okf": false } } ``` The `llms.txt` plugin is the right tool for "AI-searchable flat text"; OKF is the right tool for "AI-agent typed knowledge graph". ## How to verify After `docmd build`, inspect the bundle at `site/okf/`: ```bash # The manifest (every concept, type, path) cat site/okf/okf.yaml | head -30 # The catalog (Karpathy-style grouped by type) open site/okf/index.md # The interactive graph (force-directed, theme-aware) open site/okf/graph.html # Warnings the plugin produced cat site/okf/_meta/lint-report.txt ``` The lint report is the first thing to check — it lists pages without a `type` field, pages with broken internal links, and orphaned concepts (no inbound links). Fix any of those for a cleaner agent experience. ## See also - [OKF Bundle Plugin docs](../../plugins/okf.md) — the plugin reference: every config option, the per-page opt-out flags, the type resolution precedence. - [Open Knowledge Format — Google Cloud blog post](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing) — the spec announcement with the design rationale. - [LLM Context Plugin](../../plugins/llms.md) — the complementary flat-list format. LLMS is "give me everything", OKF is "give me the schema for table X". - [Building AI-ready docs](../generating-ai-ready-docs.md) — broader guide on AI-agent consumption. - [Structure for LLMs](../structure-for-llms.md) — how to organise content for machine consumption. --- ## [Designing for Semantic Search and RAG](https://docs.docmd.io/guides/ai-optimisation/semantic-search-design/) --- title: "Designing for Semantic Search and RAG" description: "How to structure your documentation to optimise it for vector-based search and Retrieval-Augmented Generation." --- ## Problem Traditional keyword search relies on exact text matches. If a user searches for "authentication", a basic keyword engine fails to find "Integrating OAuth2" if the exact word is absent. Semantic search uses vector embeddings to understand query meaning. It solves this problem but requires specific documentation structures. ## Why it matters Modern developers expect intuitive, intent-based search. If documentation fails to surface relevant content because of terminology differences, users abandon your site. Designing for semantic search ensures documentation remains discoverable regardless of the vocabulary used. ## Approach Structure your documentation to be easily consumed by Retrieval-Augmented Generation (RAG) pipelines. Create "semantically dense" content where concepts are clearly defined. Replace pronouns with explicit entities to preserve context during chunking and vectorisation. ## Implementation ### 1. Rich Frontmatter Metadata Use [Frontmatter](../../content/frontmatter.md) to provide explicit keywords and descriptions that might not appear naturally in the body text. This gives the search engine extra "hooks" into your content. ```yaml --- title: "Integrating OAuth2" description: "Learn how to implement secure user authentication and SSO." keywords: ["login", "authentication", "sso", "security", "identity"] --- ``` ### 2. The "Semantic Density" Strategy RAG systems slice documents into small vector chunks. The first paragraph of every section should contain the highest density of relevant nouns and verbs related to that topic. This ensures the section's primary "meaning" is captured in the initial vector. - **✅ Good**: "This guide explains how to implement **OAuth2 Single Sign-On (SSO)** to provide secure **authentication** for your documentation site." - **❌ Poor**: "In this section, we'll talk about how it works and how you can set it up easily." ### 3. Avoiding Pronoun Ambiguity In a chunked database, a sentence like "It works with any provider" is useless if the preceding paragraph defining "It" was sliced into a different chunk. Be explicit. - **❌ Ambiguous**: "It is highly scalable." - **✅ Explicit**: "The **docmd Search Engine** is designed to be highly scalable." ## Trade-offs Writing for semantic density can feel more formal or repetitive than traditional narrative writing. However, the resulting improvement in discoverability and AI response accuracy makes this a vital practice for enterprise-grade documentation. --- ## [Structuring Documentation for AI Agents](https://docs.docmd.io/guides/ai-optimisation/structure-for-llms/) --- title: "Structuring Documentation for AI Agents" description: "How to move from visual formatting to semantic structuring to improve the accuracy of AI coding assistants." --- ## Problem Human readers rely on visual cues and inferred context. AI agents consume raw text streams. Without rigorous semantic structure, models struggle to map relationships between concepts. This leads to poor reasoning and inaccurate coding suggestions. ## Why it matters If your documentation is not optimised for LLMs, developers using tools like GitHub Copilot or Cursor face more hallucinations. This degrades the developer experience. Users often blame your product for errors generated by their AI assistants. ## Approach Transition from a "visual-first" to a **"semantic-first"** mindset. Use standard Markdown features - strict header hierarchies, explicit code block tags, and descriptive alt text - to provide a machine-readable roadmap. docmd processes this structure into optimised outputs via the [LLMs Plugin](../../plugins/llms.md). ## Implementation ### 1. Strict Header Hierarchy Avoid skipping header levels for visual effects. A consistent hierarchy allows LLMs to understand the scope and relationships of different sections. - **`#` Title**: The primary subject of the page. - **`##` Major Concept**: An atomic, high-level topic. - **`###` Detail**: A specific sub-task or property. * **❌ Poor**: Using `###` immediately after `#` for a smaller font size. * **✅ Good**: `# Installation` followed by `## Prerequisites` and `### System Requirements`. ### 2. Descriptive Metadata for Media LLMs cannot "see" images or diagrams. Provide architectural context in the alternative text or an adjacent paragraph. ```markdown ![System Architecture: The frontend React app communicates with the Node.js API via REST, which queries a Redis cache and a PostgreSQL database.](../../static/img/architecture.png) ``` ### 3. Explicit Code Block Labelling Specify the language for every fenced code block using [Syntax Highlighting](../../content/syntax/index.md). This allows LLMs to parse the Abstract Syntax Tree (AST) correctly. ```json "plugins": { "llms": {} } ``` ### 4. Semantic Containers Use [Callouts](../../content/containers/callouts.md) rather than generic blockquotes to provide intent. docmd's semantic containers help AI models distinguish core instructions from supplementary warnings. ## Trade-offs Semantic rigour requires discipline. You cannot use Markdown features purely as decorative elements. However, this discipline produces documentation that is significantly more accessible to both AI agents and human readers using assistive technologies. --- ## [Alongside Other Tools](https://docs.docmd.io/guides/integrations/alongside-other-tools/) --- title: "Alongside Other Tools" description: "Strategies for integrating docmd into a multi-tool documentation ecosystem to create a seamless user experience." --- ## Problem Large organisations rarely use a single tool for documentation. You might use Confluence for internal specs, Stoplight for APIs, and GitHub for code. Integrating disparate sources into a unified user journey is a challenge. Users often jump between disconnected portals with different styles and navigation. ## Why it matters A fragmented documentation experience ruins developer trust and increases cognitive load. If a user switches between completely different interfaces to follow a tutorial, they lose context or abandon your product. Unifying your tools ensures a professional, cohesive experience that encourages exploration. ## Approach Use docmd as your primary documentation hub. By using the [Menubar](../../configuration/menubar.md) for unified navigation and [Embed Containers](../../content/containers/embed.md) for third-party content, you can create a seamless interface that hides multi-tool complexity. ## Implementation ### 1. Unified Global Navigation Use the `menubar` configuration to link your various documentation portals together. This ensures users can always find their way back to the main guides, regardless of which subdomain they are on. ```json "layout": { "menubar": { "left": [ { "text": "Guides", "url": "/" }, { "text": "API Reference", "url": "https://api.example.com" }, { "text": "Community", "url": "https://forum.example.com" } ] } } ``` ### 2. Seamless Embedding For tools that provide a web interface (like interactive API explorers or dashboard previews), use the `::: embed` container. This displays them directly within your docmd pages, keeping users within your branded environment. ```markdown # Interactive API Explorer ::: embed "https://api.example.com/v1/explorer" ::: ``` For more information, see the [Embed Reference](../../content/containers/embed.md). ### 3. Content Aggregation For external content that must be searchable alongside core documentation, consider a build step that fetches data from other sources and converts it into Markdown. This allows docmd to index all information in a single, unified [Search Index](../../plugins/search.md). ## Trade-offs While embedding provides a unified look, it can introduce performance overhead or "scroll-nesting" issues on mobile devices. Content within an iframe is not natively indexed by docmd's search engine. If search parity is critical, prioritising [OpenAPI Generation](openapi-generation.md) or other Markdown-based ingestion methods is recommended. --- ## [Choosing Your Deployment Method](https://docs.docmd.io/guides/integrations/choosing-deployment-method/) --- title: "Choosing Your Deployment Method" description: "A practical guide to choosing between the docmd GitHub App, GitHub Action, Starter Template, and Deployer Package — with a decision matrix and real-world scenarios." --- # Choosing Your Deployment Method docmd offers four ways to get your documentation live. They all produce the same output — a static site deployed to GitHub Pages or a hosting provider of your choice — but they differ in how much control you want and where you are starting from. ## Quick Decision Matrix | | [GitHub App](../../integrations/github-app.md) | [Starter Template](../../integrations/starter-template.md) | [GitHub Action](../../integrations/github-action.md) | [Deployer Package](../../deployment/deployer-package.md) | |---|---|---|---|---| | **Starting point** | Existing repo | New repo | Any | Any | | **Setup effort** | One click | Two clicks | Write YAML | Run a command | | **Workflow file** | Auto-generated | Included | You write it | Auto-generated | | **Customisable** | After generation | From the start | Fully | Fully | | **Hosting target** | GitHub Pages | GitHub Pages | GitHub Pages | Any provider | | **Monorepo support** | ✓ Auto-detected | — | Manual `--cwd` | ✓ | | **Non-GitHub hosting** | ✗ | ✗ | Adaptable | ✓ Docker, Nginx, Vercel, Netlify… | ## Scenario Guide ### "I want docs live in under two minutes with zero setup" Use the **[GitHub App](../../integrations/github-app.md)**. Install it, select your repository, done. It detects your config, generates the workflow, enables GitHub Pages, and deploys — without you touching a single file. ::: button "Install GitHub App" external:https://github.com/apps/docmd/installations/new icon:github color:#2ea44f --- ### "I'm starting a brand-new documentation site" Use the **[Starter Template](../../integrations/starter-template.md)**. Click "Use this template" on GitHub, update `docmd.config.json` with your title and URL, enable GitHub Pages once, and push. Everything is pre-wired. ::: button "Use Starter Template" external:https://github.com/docmd-io/docmd-template/generate icon:github --- ### "I have an existing CI/CD pipeline and want to add docs to it" Use the **[GitHub Action](../../integrations/github-action.md)**. Drop `docmd-io/deploy@v1` into your existing workflow. It composes cleanly with other steps — run tests, build your app, then build docs, all in one job. --- ### "I'm deploying to Vercel, Netlify, Docker, or my own server" Use the **[Deployer Package](../../deployment/deployer-package.md)**. Run `npx @docmd/core deploy --vercel` (or `--netlify`, `--docker`, `--nginx`) to generate provider-specific config files tailored to your `docmd.config.json`. --- ### "I'm in a monorepo with docs in a subdirectory" Both the **GitHub App** and the **Deployer Package** handle this automatically. The App detects configs anywhere in the repository tree and injects the correct `--cwd` flag. The Deployer Package reads your config from the current working directory. If you prefer the GitHub Action, pass `--cwd` manually: ```yaml - run: npx @docmd/core build --cwd packages/docs ``` --- ### "I want to preview docs on every pull request" Use the **GitHub Action** combined with a PR preview service (e.g. Cloudflare Pages preview deployments or a self-hosted preview environment). See [Previewing Changes](../workflows-teams/previewing-changes.md) for a full walkthrough. --- ## How They Fit Together These methods are not mutually exclusive. A common progression looks like this: ``` Start with the GitHub App (fastest path to live) ↓ Customise the generated workflow file as your needs grow ↓ Add the Deployer Package to generate Nginx/Docker configs for self-hosting ↓ Integrate the Action into a broader CI/CD pipeline ``` You can also mix them: use the Starter Template for a new project, then add the Deployer Package later to generate a Docker image for your staging environment. ## Comparing Build Triggers | Method | Triggers on push | Manual trigger | PR preview | |---|---|---|---| | GitHub App | ✓ (auto-configured) | ✓ `workflow_dispatch` | Requires extra step | | Starter Template | ✓ `main` / `master` | ✓ `workflow_dispatch` | Requires extra step | | GitHub Action | You configure | You configure | You configure | | Deployer Package | Generates the file; triggers depend on your workflow | — | — | ## Further Reading - [GitHub Action reference](../../integrations/github-action.md) - [GitHub App reference](../../integrations/github-app.md) - [Starter Template reference](../../integrations/starter-template.md) - [Deployer Package reference](../../deployment/deployer-package.md) - [GitHub Actions CI/CD guide](./github-actions-cicd.md) - [Previewing Changes](../workflows-teams/previewing-changes.md) --- ## [Existing Markdown Repos](https://docs.docmd.io/guides/integrations/existing-markdown-repos/) --- title: "Existing Markdown Repos" description: "How to instantly generate a professional documentation site from your existing Markdown files with zero configuration." --- ## Problem You have an established repository with hundreds of raw Markdown files - perhaps a legacy wiki, an Obsidian vault, or technical notes. Manually converting frontmatter, fixing broken links, and restructuring files for a new engine is a difficult task that often prevents modernisation. ## Why it matters Your content should remain portable and tool-agnostic. A high-quality documentation engine adapts to your existing files, rather than forcing files to adapt to the engine. Avoiding vendor lock-in ensures your intellectual property remains standard, readable, and future-proof. ## Approach docmd adheres to strict CommonMark specifications and is designed to be **zero-config** by default. Point the docmd CLI at any directory containing Markdown files, and it intelligently bootstraps a full-featured documentation site without modifying a single line of source content. ## Implementation ### 1. Instant Bootstrapping Navigate to your existing Markdown folder and run the development server. docmd scans your directory structure and builds a functional site in memory instantly. ```bash cd my-existing-docs/ npx @docmd/core dev ``` ### 2. Automatic Navigation (Auto-Router) If no `navigation.json` or `docmd.config.json` is found, docmd triggers its [Auto-Router](../../configuration/navigation.md#automatic-sidebar-generation). It recursively maps your folder structure, prettifies directory names (e.g., `getting-started` becomes `Getting Started`), and generates a logical sidebar taxonomy automatically. ### 3. Intelligent Title Inference You don't need to add `title` frontmatter to every file. docmd uses a cascading resolution strategy to determine page titles: 1. **Frontmatter**: Checks for a `title` or `h1` key. 2. **First Heading**: Extracts the first `# Heading` found in the file content. 3. **Filename**: Prettifies the filename as a fallback (e.g., `install-guide.md` becomes `Install Guide`). ### 4. Resilient Syntax Handling docmd is built to be resilient. If existing files contain proprietary syntax or legacy shortcodes from other engines, they render safely as raw text or are skipped. This ensures your build never fails due to unmigrated content. ## Trade-offs Automatic sidebars are typically sorted alphabetically by filename. While naming files like `01-intro.md` and `02-setup.md` works well, descriptive filenames may appear in an unintuitive order. For production-ready sites, we recommend transitioning to manual [Navigation Configuration](../../configuration/navigation.md) for full control over the user journey. --- ## [GitHub Actions CI/CD](https://docs.docmd.io/guides/integrations/github-actions-cicd/) --- title: "GitHub Actions CI/CD" description: "How to automate your documentation builds and deployments using GitHub Actions and docmd for a high-velocity workflow." --- ## Problem Building and deploying documentation manually from a local machine is prone to errors, environment inconsistencies, and security risks. It creates a bottleneck, as deployments depend on a single individual's availability. ## Why it matters Continuous Deployment (CD) ensures your documentation is always in sync with your software. When a technical update is merged, it should reach users within minutes. Automation guarantees every build happens in a clean, reproducible environment, maintaining quality and reliability. ## Approach Use GitHub Actions to run the docmd build pipeline on every push or Pull Request. The resulting static assets can be automatically deployed to hosting providers like GitHub Pages, Cloudflare Pages, or containerised environments using Docker. ## Implementation ### 1. Standard GitHub Pages Workflow Create `.github/workflows/docs.yml` to automate the build and deployment process. ```yaml ".github/workflows/docs.yml" name: Deploy Docs on: push: branches: [main] permissions: contents: read pages: write id-token: write jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'npm' - run: npm install # Build the site into the 'site/' directory - run: npx @docmd/core build - name: Upload Artifact uses: actions/upload-pages-artifact@v3 with: path: site/ - name: Deploy to GitHub Pages uses: actions/deploy-pages@v4 ``` ### 2. Containerised Deployment (Docker) If you host your own documentation, use the [Deploy Command](../../deployment/index.md) to generate a production-ready `Dockerfile` and server configurations. ```bash # Generate Docker and Nginx configs locally npx @docmd/core deploy --docker --nginx ``` You can update your GitHub Action to build and push this Docker image to a registry (like Docker Hub or GitHub Container Registry) whenever you release a new version. ### 3. Pull Request Previews Enhance your workflow by generating ephemeral preview environments for every Pull Request. This allows reviewers to see the rendered documentation before merging it into the main branch. See the [Previewing Changes Guide](../workflows-teams/previewing-changes.md) for more details. ## Trade-offs Automated CI/CD requires initial setup time and management of secrets (e.g., API tokens). However, the long-term benefits of a "hands-off" deployment process - including reduced human error and faster update cycles - far outweigh the initial investment. For large sites, ensure your workflow only triggers when files in your documentation directory change to save CI minutes. --- ## [OpenAPI Generation](https://docs.docmd.io/guides/integrations/openapi-generation/) --- title: "OpenAPI Generation" description: "How to integrate OpenAPI/Swagger schemas into your docmd workflow for automated and synchronised API reference documentation." --- ## Problem Manually maintaining REST API documentation is an operational risk. When an engineer modifies an endpoint or updates a schema in code, documentation becomes obsolete. Keeping these in sync manually is tedious, error-prone, and frequently leads to integration failures for consumers. ## Why it matters Inaccurate API references cause developer frustration and increase support tickets. Automation ensures your documentation remains the "source of truth", reflecting the actual state of your API at every build. This allows engineers to focus on building features rather than updating tables manually. ## Approach Implement an asynchronous build pipeline that converts your `openapi.json` or `swagger.yaml` schema into standard Markdown files. Because docmd excels at rendering Markdown with complex [Containers](../../content/containers/index.md), the resulting API reference feels integrated and visually consistent with the rest of your documentation. ## Implementation ### 1. Build Pipeline Integration Use a tool like `widdershins` or a custom script to generate Markdown from your OpenAPI schema as a pre-build step in your CI/CD pipeline. ```json "package.json" // package.json { "scripts": { "docs:generate-api": "npx widdershins --search false openapi.yaml -o docs/api/reference.md", "docs:build": "npm run docs:generate-api && npx @docmd/core build" } } ``` ### 2. Optimising API Layouts API references are often content-dense, with large tables for parameters and nested schemas. Use [Frontmatter](../../content/frontmatter.md) to optimise the page layout for readability. ```markdown --- title: "REST API Reference" layout: "full" # Maximises horizontal space for dense tables --- ``` Setting `layout: "full"` removes the right-hand Table of Contents sidebar, providing more room for wide code blocks and response examples. ### 3. Enhancing with docmd Containers Post-process the generated Markdown to inject docmd features like [Tabs](../../content/containers/tabs.md) for multi-language code samples or [Callouts](../../content/containers/callouts.md) for authentication warnings. ````markdown ::: tabs == tab "cURL" ```bash curl -X GET "https://api.example.com/v1/users" ``` == tab "Node.js" ```javascript const users = await client.getUsers(); ``` ::: ```` ## Trade-offs Machine-generated documentation is excellent for technical accuracy but lacks the "human touch" required for effective learning. We recommend using OpenAPI generation for the **Technical Reference** (endpoints, parameters, schemas) while providing handwritten **Tutorials** and **Conceptual Guides** to explain the context and use cases. --- ## [Guides Overview](https://docs.docmd.io/guides/overview/) --- title: "Guides Overview" description: "Pick the right guide cluster for what you're trying to do — writing quality, workflows, search, performance, AI optimisation, or integrations." --- # Guides Overview Guides are intermediate-to-advanced "how do I do X well" content. Pick the cluster that matches your goal. Most users start with **Writing Quality** — those guides apply to every docmd site regardless of stack or feature focus. ::: grids ::: grid ::: card "Writing Quality" icon:pen-tool For every docmd user. Covers scalable technical writing, readability, task-vs-concept, and avoiding anti-patterns. Most universally relevant cluster. [Start with Writing Quality →](./writing-quality/scalable-technical-writing) ::: ::: ::: grid ::: card "Workflows & Teams" icon:users For documentation leads and teams. Git-based workflows, preview environments, consistency at scale, and release workflows. [Explore Workflows & Teams →](./workflows-teams/setting-up-workflow) ::: ::: ::: grid ::: card "Search" icon:search For everyone with a search box. Improve relevance, speed, local-first indexing, and add semantic search. [Tune your search →](./search/improving-search-relevance) ::: ::: ::: grid ::: card "Performance" icon:gauge For teams that care about Time to Interactive. Sub-100ms navigation, CDN deployment, JS payload reduction, low-end devices, caching. [Speed up your site →](./performance-delivery/sub-100ms-navigation) ::: ::: ::: grid ::: card "AI & LLMs" icon:brain-circuit For teams that want their docs to be readable by AI agents and LLMs. MCP, agent skills, llms.txt, semantic search design, chunking, context preservation. [Make docs AI-ready →](./ai-optimisation/mcp-and-agent-skills) ::: ::: ::: grid ::: card "Integrations" icon:plug For connecting docmd to the rest of your stack. OpenAPI generation, GitHub Actions, existing Markdown repos, parallel tooling. [See integrations →](./integrations/choosing-deployment-method) ::: ::: ::: ::: callout tip "Not sure where to start?" If you're brand new to docmd, skip the Guides and read [Getting Started](/getting-started/quick-start) first. Guides assume you're already comfortable with the basics. ::: --- ## [Caching Strategies](https://docs.docmd.io/guides/performance-delivery/caching-strategies/) --- title: "Caching Strategies" description: "How to optimise your documentation site's performance using immutable caching, Etag revalidation, and production-ready server configurations." --- ## Problem When a documentation site is served without proper cache-control headers, browsers unnecessarily re-download images, CSS, and JavaScript bundles. This results in visual stuttering, increased bandwidth consumption, and a poor experience for returning users. ## Why it matters Effective caching is highly impactful for improving perceived performance. Storing static assets locally in the user's browser eliminates the latency of repeated network requests. This makes navigation feel fluid and reliable, even on unstable connections. ## Approach Implement a two-tier caching strategy: **Immutable Caching** for static assets (CSS, JS, images) and **Etag Revalidation** for dynamic content (HTML, JSON). docmd facilitates this by generating production-ready configurations that handle cache-busting automatically. ## Implementation ### 1. Production-Ready Server Configs The easiest way to implement optimal caching is by using the [Deploy Command](../../deployment/index.md) to generate your server configuration. ```bash # Generate an optimised Nginx configuration npx @docmd/core deploy --nginx ``` ### 2. Immutable Assets For assets that don't change frequently (like theme styles and core scripts), use long-term caching. docmd appends version hashes to these assets to ensure users only download new versions when you update your documentation. ```nginx # Example Nginx rule for immutable assets location ~* \.(?:css|js|webp|png|svg|woff2)$ { expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; } ``` ### 3. HTML & Navigation Revalidation Your HTML files and `navigation.json` should always be checked for updates. This ensures users see the latest content immediately. Use the `no-cache` directive to force the browser to revalidate with the server using Etags. ```nginx # Example Nginx rule for HTML files location ~* \.html$ { add_header Cache-Control "no-cache, must-revalidate"; } ``` ## Trade-offs ### Stale Content vs. Performance Setting long cache times for assets is highly performant but requires a reliable "cache-busting" strategy. docmd handles this automatically for core files. If you manually add assets to your `static/` directory, you must update their references (e.g., by changing the filename or adding a query parameter) when content changes. ### CDN Integration If you use a CDN (like Cloudflare or AWS CloudFront), ensure it honours your server's `Cache-Control` headers. Most modern CDNs provide "instant purge" capabilities. We recommend triggering this as part of your CI/CD pipeline whenever you deploy a new version. --- ## [CDN & Edge Deployment](https://docs.docmd.io/guides/performance-delivery/deploying-cdn-edge/) --- title: "CDN & Edge Deployment" description: "How to minimise global latency by deploying your static documentation to a Content Delivery Network (CDN) or Edge Network." --- ## Problem Hosting documentation on a single server in one geographic region (e.g., US-East) creates significant network latency for users elsewhere. Every page load, image, and script travels thousands of miles. This makes your documentation feel sluggish for a global audience. ## Why it matters High latency directly harms the developer experience. Even if your documentation is well-written and lightweight, the "Time to First Byte" (TTFB) is limited by physics. If your site feels slow, developers lose focus or abandon your tool in favour of faster alternatives. ## Approach The optimal solution is to deploy your site to an Edge CDN. docmd generates pure static assets (HTML, CSS, JS), making it perfectly suited for edge distribution. CDNs replicate files across globally distributed "Edge Nodes" to serve users from the closest data centre. ## Implementation ### 1. Choose a Platform docmd natively supports all modern static hosting and edge platforms. We recommend the following for their global performance and ease of use: * **Cloudflare Pages**: Extremely fast global edge network with built-in DDoS protection. * **Vercel**: Optimised for performance with excellent developer workflow integration. * **Netlify**: Powerful automation features and a reliable global CDN. ### 2. Automate the Build Use a CI/CD pipeline to build and deploy your site automatically whenever you push changes. See the [GitHub Actions Guide](../../guides/integrations/github-actions-cicd.md) for detailed examples. ```yaml ".github/workflows/deploy.yml" # .github/workflows/deploy.yml jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 # Build the site into the default 'site/' directory - run: npm install && npx @docmd/core build # Example: Deploying to Cloudflare Pages - name: Deploy uses: cloudflare/pages-action@v1 with: apiToken: ${{ secrets.CF_API_TOKEN }} accountId: ${{ secrets.CF_ACCOUNT_ID }} projectName: my-docs directory: site ``` ### 3. Verification Once deployed, verify global performance using tools like PageSpeed Insights or global ping tests. You should see sub-100ms response times from almost any worldwide location. ## Trade-offs Global edge networks abstract away server management, which benefits documentation teams. However, debugging regional caching issues can occasionally be more complex than reviewing a single server log. Using platforms with reliable "instant cache invalidation" ensures users always see the latest version immediately after a deployment. --- ## [Low-End Device Optimisation](https://docs.docmd.io/guides/performance-delivery/low-end-devices/) --- title: "Low-End Device Optimisation" description: "How to build high-performance, accessible documentation that works easily on low-powered hardware and slow network connections." --- ## Problem Modern documentation sites often rely on heavy JavaScript runtimes to display static text. For users on older mobile phones or slow connections, these sites take several seconds to load. The processor struggles to parse large JS bundles, resulting in "input lag" and a poor reading experience. ## Why it matters Technical documentation should be universally accessible. Forcing users on constrained hardware to download a heavy framework creates an unnecessary barrier to learning. A lightweight site ensures product information is available to everyone, regardless of hardware or internet speed. ## Approach Adopt an **HTML-First** strategy. docmd uses a zero-framework architecture. The primary content is rendered into standard HTML during the build process. This keeps the browser's main thread unblocked, ensuring smooth scrolling and snappy navigation even on budget devices. ## Implementation ### 1. Minimal Runtime Footprint By default, docmd does not use React or Vue for its core UI. This pre-rendered approach ensures the initial "First Contentful Paint" happens almost immediately. To maintain this performance: * **Limit Custom Scripts**: Avoid adding large third-party libraries to your `customJs` configuration. * **Use Native Browser Features**: Rely on standard CSS and HTML5 elements. ### 2. Strategic Plugin Management While [Plugins](../../plugins/usage.md) add powerful features, they introduce performance overhead. For example, the [Mermaid Plugin](../../plugins/mermaid.md) requires a large engine to render diagrams. If your users are on low-end devices, use static images instead of client-side rendering. ### 3. Responsive and Optimised Media Avoid serving oversized images to mobile users. Use modern formats like WebP and consider the `<picture>` tag for granular control over responsive assets. ```html <picture> <source srcset="/assets/mobile-hero.webp" media="(max-width: 600px)"> <img src="/assets/desktop-hero.webp" alt="Feature Overview" loading="lazy"> </picture> ``` Using the `loading="lazy"` attribute ensures images are only downloaded as they enter the user's viewport, saving bandwidth. ### 4. Efficient Search Indexing docmd generates scoped search indices to keep the memory footprint low. However, for extremely large sites, the [Search Plugin](../../plugins/search.md) can still be memory-intensive. Optimise your index as described in the [Local-First Search Guide](../search/local-first-search.md). ## Trade-offs Prioritising performance for low-end devices means avoiding "heavy" interactive features like complex 3D visualisations. This is a deliberate design choice that values inclusivity and speed over visual complexity. It ensures your documentation remains useful for the widest audience possible. --- ## [Reducing JS Payload](https://docs.docmd.io/guides/performance-delivery/reducing-javascript-payload/) --- title: "Reducing JS Payload" description: "How to maintain a high-performance documentation site by optimising your JavaScript dependencies and using docmd's zero-framework architecture." --- ## Problem Many modern documentation tools rely on heavy JavaScript frameworks (like React or Vue) to render static text. These frameworks add several hundred kilobytes to the initial page load. The browser must download, parse, and execute large amounts of code before the site becomes fully interactive. This leads to slow loading times and "ghost clicks" on low-end devices. ## Why it matters A large JavaScript payload directly impacts "Time to Interactive" (TTI). In technical documentation, users need answers quickly. Any delay caused by heavy framework initialisation is a significant usability barrier. Keeping your payload small ensures that search, navigation, and theme switching are instantaneous. ## Approach docmd uses a **zero-framework** architecture for its core client-side logic. By utilising Vanilla JavaScript and native browser APIs instead of a heavy Virtual DOM, we keep the total JS payload for a standard site under **20KB**. This lightweight foundation ensures maximum performance across all devices. ## Implementation ### 1. Use Native Browser APIs Avoid importing heavy libraries like jQuery or Lodash for simple tasks. Modern browsers have reliable native APIs that handle almost any documentation-related requirement with zero overhead. ```javascript // Add custom scripts in docmd.config.json customJs: ["/static/js/my-custom-logic.js"] ``` ### 2. Strategic Plugin Management While [Plugins](../../plugins/usage.md) add powerful features, some significantly increase your JavaScript payload. For example, the [Mermaid Plugin](../../plugins/mermaid.md) requires a large client-side library to render diagrams. Only enable heavy plugins if they are essential to your content. ### 3. Defer Non-Critical Scripts If you include third-party services like analytics or feedback widgets, ensure they load asynchronously or are deferred. This prevents them from blocking the rendering of your documentation. ```html <!-- In your custom head injection --> <script src="https://analytics.com/script.js" async defer></script> ``` ### 4. Optimise Assets Ensure any custom JavaScript you provide is minified and compressed. docmd handles the minification of its core assets, but you are responsible for optimising any files you add to your `static/` directory. ## Trade-offs Building complex interactive features with Vanilla JavaScript requires more manual effort than using a declarative framework. However, for documentation - where 95% of the content is static text and images - the performance gains of a zero-framework approach far outweigh the convenience of a heavy framework. --- ## [Sub-100ms Navigation](https://docs.docmd.io/guides/performance-delivery/sub-100ms-navigation/) --- title: "Sub-100ms Navigation" description: "How docmd's native SPA router and intent-based prefetching deliver instant page transitions for an optimal reading experience." --- ## Problem Traditional multi-page navigation triggers a full browser reload on every click. This creates a disruptive "white flash" and breaks the reader's flow. The browser discards the current state, requests new HTML, and re-parses CSS and JavaScript - even if only the central content area changes. ## Why it matters Users frequently jump between tutorials, API references, and conceptual guides. If transitions take seconds, cognitive friction discourages exploration. Instant navigation makes documentation feel like a native application, significantly improving user satisfaction and engagement. ## Approach docmd utilises a high-performance **Single Page Application (SPA) Router** built on pre-generated static files. The browser intercepts link clicks, fetches only necessary content in the background, and updates the page dynamically without a full reload. This preserves the state of the sidebar, table of contents, and theme settings for near-instant transitions. ## Implementation The docmd SPA router uses advanced techniques to achieve sub-100ms navigation speeds: ### 1. Intent-Based Prefetching When a user hovers over a navigation link, docmd detects the intent and initiates a background fetch for the target page. By the time the user clicks, the data is often already in the browser's cache. Transitions feel instantaneous. ### 2. Partial DOM Updates Instead of re-rendering the entire page, docmd intelligently updates only necessary functional zones: * **Main Content**: The primary Markdown-rendered body. * **Table of Contents**: Refreshed to match new headers. * **Navigation State**: Updates active and expanded sidebar states. ### 3. Lifecycle Events for Custom Logic Because the browser avoids full reloads, standard events like `DOMContentLoaded` only fire once. To execute custom JavaScript after every navigation, listen for the `docmd:page-mounted` event. ```javascript document.addEventListener("docmd:page-mounted", (event) => { const currentPath = event.detail.path; console.log(`Successfully navigated to: ${currentPath}`); if (currentPath.includes("/api/")) { initApiConsole(); } }); ``` For more details, see the [Client-Side Events](../../api/client-side-events.md) documentation. ## Trade-offs ### Script Execution The SPA router automatically re-executes `<script>` tags found within the Markdown body of the new page. However, global scripts defined in your theme only run once during the initial load. Use the `docmd:page-mounted` event for logic that must execute on every page. ### SEO and Accessibility Despite SPA-like behaviour, docmd generates a complete `.html` file for every page. This ensures search engine crawlers see full content and the site remains functional for users with JavaScript disabled. This maintains excellent SEO and accessibility standards. --- ## [Fast & Accurate Search](https://docs.docmd.io/guides/search/fast-accurate-search/) --- title: "Fast & Accurate Search" description: "How docmd optimises search indexing for speed and accuracy, even in large-scale documentation projects." --- ## Problem As documentation grows, the compiled search index can become large. A monolithic index file blocks the browser's main thread during download and parsing. This delays the "Time to Interactive" and causes the search interface to feel sluggish. ## Why it matters The primary goal of documentation search is "Time to Answer". If a user waits several seconds for the index to load, the tool's utility is lost. Fast, accurate search results are essential for providing a professional developer experience. ## Approach docmd utilises an optimised indexing strategy powered by a high-performance search library. It employs **Scoping**, **Incremental Loading**, and **Field Optimisation** to ensure search results are delivered instantaneously, regardless of site size. ## Implementation ### 1. Scoped Search Indices docmd automatically generates separate search indices for every [Locale](../../configuration/localisation/index.md) and [Version](../../configuration/versioning.md). Users only download the index relevant to their current context. For example, a user browsing the Chinese version only downloads the Chinese search index, significantly reducing payload size. ### 2. Intelligent Field Stripping The [Search Plugin](../../plugins/search.md) lets you control exactly what content is indexed. By default, it prioritises headers and frontmatter metadata while stripping common "stop words". You can exclude specific pages from the index using the `search` property in your [Frontmatter](../../content/frontmatter.md). ```yaml --- title: "Internal Developer Guide" search: false # This page will not appear in search results --- ``` ### 3. Lazy Loading & Prefetching To keep initial page loads fast, docmd fetches the search index lazily in the background. It also triggers immediately when a user interacts with the search UI (e.g., clicking the search bar or using the `Cmd+K` / `Ctrl+K` shortcut). ### 4. Result Ranking Results are ranked based on a weighted scoring system. Keywords found in the page `title` or `h1` headers are weighted significantly higher than those in body text. This ensures the most relevant pages appear at the top. ## Trade-offs Excluding utility or internal pages from the search index makes them harder to discover. Use the `search: false` property sparingly to ensure valuable information remains findable. While lazy loading improves initial performance, users on slow connections may experience a brief delay the first time they trigger a search. --- ## [Search Relevance & Structure](https://docs.docmd.io/guides/search/improving-search-relevance/) --- title: "Search Relevance & Structure" description: "How to structure your Markdown content to improve search relevance and help users find information faster." --- ## Problem Search engines prioritise content based on structure. If a high-quality guide uses generic headers like "Introduction" or "Step 1", the search engine may not assign enough weight to core keywords. Relevant pages get buried in search results, frustrating users who expect instant answers. ## Why it matters Users typically search for specific technical terms (e.g., "authentication token" or "deployment limit") rather than full sentences. If your documentation structure doesn't emphasise these terms, the search engine cannot confidently rank your content. High search relevance prevents a high volume of support tickets. ## Approach Structure your Markdown so the search indexer automatically identifies and prioritises core concepts. docmd's search engine assigns higher weights to the page `title`, `description`, and `headers` compared to the body text. Optimising these structural elements significantly improves discoverability. ## Implementation ### 1. Optimise Frontmatter Metadata Use the [Frontmatter](../../content/frontmatter.md) block to provide explicit keywords and a descriptive summary. The [Search Plugin](../../plugins/search.md) indexes these fields to provide better results and useful snippets in the search UI. ```yaml --- title: "AWS S3 Storage Configuration" description: "How to configure IAM roles and bucket permissions for AWS S3 integration." keywords: ["aws", "s3", "storage", "iam", "cloud"] --- ``` ### 2. Use Semantic Headers Avoid generic header names. Include relevant keywords in your headers to provide context for both the user and the search engine. * **Low Relevance:** `## Step 1: Configuration` * **High Relevance:** `## Step 1: Configuring AWS IAM Roles` ### 3. Use Callouts for Key Information Using [Callout Containers](../../content/containers/callouts.md) for critical warnings or "Pro Tips" improves search relevance. Content within callouts is semantically isolated and weighted differently by the indexer to highlight important troubleshooting steps. ## Trade-offs Optimising for search relevance requires disciplined writing. As your product evolves, keywords in frontmatter become outdated if not reviewed regularly. In addition, including too many keywords in headers (keyword stuffing) makes documentation feel repetitive and unnatural. Aim for a balance between SEO and readability. --- ## [Local-First Search Optimisation](https://docs.docmd.io/guides/search/local-first-search/) --- title: "Local-First Search Optimisation" description: "How to optimise your documentation content for docmd's high-performance, client-side search engine." --- ## Problem Local-first search engines run entirely in the browser. They provide instant results without a server round-trip. However, they are constrained by browser memory and processing limits. An unoptimised search index consumes excessive RAM. This causes the browser tab to stutter or crash, especially on mobile devices. ## Why it matters A seamless search experience is essential for productivity. If the search tool causes performance issues or memory bloat, users abandon it. Optimising content for local-first search ensures documentation remains fast, responsive, and reliable across all devices and network conditions. ## Approach docmd's [Search Plugin](../../plugins/search.md) uses a build-time extraction pipeline to create an optimised index. By pruning unnecessary data and focusing on high-value semantic fields, the resulting index is comprehensive and lightweight. ## Implementation ### 1. Build-Time Extraction During the build process, docmd processes Markdown files to extract relevant text for indexing. It automatically strips out: * HTML tags and structural boilerplate. * Markdown syntax characters that lack semantic value. * Formatting-only elements that bloat the index. This ensures the indexer only receives clean, meaningful text, reducing the final index size significantly. ### 2. Strategic Indexing with Frontmatter Use [Frontmatter](../../content/frontmatter.md) to explicitly control how a page is indexed. If a page contains repetitive data (like raw JSON logs) that aren't useful for search, index only the headers and metadata. ```yaml --- title: "API Log Reference" search: indexBody: false # Only index the title and headers --- ``` ### 3. Client-Side Memory Management docmd manages the search index lifecycle carefully in the browser. It uses an on-demand loading strategy. The search engine is only initialised when the user first interacts with it. This keeps the initial page load footprint small and conserves system resources. ## Trade-offs Aggressively pruning content from the search index (e.g., excluding large code blocks) can cause missing niche results. You must balance the need for a lightweight index with thorough search coverage. We recommend prioritising headers and conceptual descriptions, as these are the most common search targets. --- ## [Semantic Search Integration](https://docs.docmd.io/guides/search/semantic-search/) --- title: "Semantic Search Integration" description: "How to configure and deploy client-side hybrid semantic search in docmd using local vector embeddings." --- ## Problem Traditional full-text search relies entirely on exact keyword matches. If a user searches for "authentication" but the page only uses terms like "OAuth2" or "login", a standard keyword search engine will fail to find it. This forces writers to perform unnatural keyword-stuffing and leaves readers frustrated when they cannot find what they need. ## Why it matters Modern developers expect natural language interfaces that understand intent, synonyms, and context. Implementing server-side semantic search typically requires setting up complex infrastructure like vector databases (e.g., Pinecone or pgvector), hosting models, and building APIs, which increases maintenance overhead, monthly hosting costs, and introduces security and privacy concerns. ## Approach Use docmd's native **Semantic Search Plugin**. It operates entirely client-side using a highly optimised browser runtime. It generates structured vector chunk indices at build time using local Hugging Face model pipelines, then re-ranks matches using hybrid BM25 keyword frequency and vector cosine similarity. No data is ever sent to third-party APIs. ## Implementation ### 1. Enable Semantic Search in Configuration Add the `search` plugin options within your `docmd.config.json`. Configure `semantic` to `true` and enable `showConfidence` to visually identify semantic matching in search results: ```json "docmd.config.json" { "plugins": { "search": { "semantic": true, "showConfidence": true } } } ``` ### 2. Choose the Right Embedding Model docmd supports both lightweight English-only models and comprehensive multilingual models. Update your model profile using `docmd-search --settings` or define it explicitly: | Model ID | Dimensions | Size | Languages | Best For | | :--- | :---: | :---: | :--- | :--- | | `Xenova/all-MiniLM-L6-v2` | 384 | ~90 MB | English only | Fast, high-accuracy English docs | | `Xenova/LaBSE` | 768 | ~470 MB | 100+ languages | Absolute best multilingual quality | | `Xenova/paraphrase-multilingual-MiniLM-L12-v2` | 384 | ~220 MB | 50+ languages | Excellent multi-language balance | ### 3. Pre-Building Index in CI/CD To prevent overhead in the browser during first-load, pre-generate the search chunks during your build or CI/CD pipeline using the CLI: ```bash # Build the semantic search index npx docmd-search --build # Run docmd build afterwards npx @docmd/core build ``` This generates highly optimised static Vecto-JSON chunks in `.docmd-search/`. When a user performs a search, the client progressively loads these chunks in the background, keeping the UI instantly interactive. ::: callout tip **Commit or Cache `.docmd-search/`:** Because `docmd-search` supports incremental indexing, committing the generated `.docmd-search/` directory to your git repository or caching it in your CI/CD workflow will make subsequent builds run instantly (under 300ms) by only re-indexing changed files. ::: ## Trade-offs ### Initial Asset Size Client-side vector embeddings require the browser to download a WebAssembly runtime and the pre-trained ONNX model file on the first search. Although these assets are persistently cached in the browser's Cache Storage, the first-load search latency may be slightly higher on slower connections (~1-2 seconds delay). ### Search Quality vs Payload Size Choosing larger models like `LaBSE` offers exceptional multilingual quality but results in larger downloads. For standard international documentation websites, the `paraphrase-multilingual-MiniLM-L12-v2` model is the recommended sweet spot between accuracy and network payload. --- ## [Git-Based Workflows](https://docs.docmd.io/guides/workflows-teams/git-based-workflows/) --- title: "Git-Based Workflows" description: "How to manage documentation contributions effectively using Git, Pull Requests, and automated CI/CD checks." --- ## Problem Allowing direct pushes to the main branch leads to broken links and unverified information. However, imposing too much friction - like requiring separate CMS accounts - discourages community members and internal developers from contributing. ## Why it matters Collaboration is the lifeblood of great documentation. If a developer finds a typo, they should be able to submit a fix in minutes. A Git-based workflow provides a familiar, transparent, and secure environment for contributions. It ensures every change is reviewed and validated before it goes live. ## Approach Implement a "Pull Request" (PR) model supported by automated validation and preview environments. docmd is designed for this workflow. It operates on standard Markdown files that are easy to diff, review, and merge using familiar Git tools. ## Implementation ### 1. Enable "Edit this Page" Links You can configure docmd to generate "Edit this page" links via the [Git Plugin](../../plugins/git.md). This allows users to jump directly from a documentation page to the corresponding source file in your repository. ```json "plugins": { "git": { "repo": "https://github.com/my-org/my-repo", "branch": "main", "editLink": true } } ``` ### 2. Contextual Reviews with Threads For complex updates requiring detailed feedback, use the [Threads Plugin](../../plugins/threads.md). This allows authors and reviewers to leave inline comments directly within the Markdown content during the review phase, keeping discussions contextualised. ```markdown ::: thread "Reviewer Name" Should we include a code example for the new authentication flow here? ::: ``` ### 3. Automated Validation in CI Integrate docmd into your CI/CD pipeline (e.g., [GitHub Actions](../../guides/integrations/github-actions-cicd.md)) to validate every PR. At a minimum, your pipeline should run the build command to ensure no syntax errors or broken configurations are introduced. ```bash # In your CI pipeline npm install npx @docmd/core build ``` ## Trade-offs Strict Git workflows can occasionally slow down minor updates, such as fixing a typo or updating a service status notice. For high-velocity teams, we recommend designating "Documentation Owners" who have authority to fast-track small changes while maintaining rigorous review standards for significant updates. --- ## [Maintaining Consistency](https://docs.docmd.io/guides/workflows-teams/maintaining-consistency/) --- title: "Maintaining Consistency" description: "How to ensure a unified voice and professional quality across large documentation teams using linting and standardised patterns." --- ## Problem In large teams, every technical writer has a different style. Some use bold text for emphasis; others use italics. Some prefer "Click the button"; others use "Select the option". Over time, documentation becomes a patchwork quilt of conflicting styles. This makes it harder for users to parse information and reduces professional trust. ## Why it matters Consistency breeds familiarity. When users learn complex APIs or workflows, they rely on consistent vocabulary and structural patterns to navigate effectively. A unified voice makes documentation feel like a cohesive, high-quality product, building confidence in the software itself. ## Approach Enforce consistency mechanically using [Standardised Containers](../../content/containers/index.md) and automated linting tools. Automating low-level style and syntax checks frees human editors to focus on the high-level quality, accuracy, and clarity of the content. ## Implementation ### 1. Use Standardised docmd Patterns Encourage all contributors to use docmd's built-in thematic containers instead of manual Markdown formatting. This ensures every warning, tip, or note looks and behaves identically across the entire site. ```markdown <!-- ❌ Avoid: inconsistent and unstyled --> **Note:** Please restart the service. <!-- ✅ Use: consistent, accessible, and thematic --> ::: callout info Please restart the service. ::: ``` Using [Callouts](../../content/containers/callouts.md) ensures your documentation maintains a professional appearance and meets accessibility standards without extra effort. ### 2. Implement Prose Linting Integrate tools like **Vale** or **Markdownlint** to enforce brand terminology, tone, and grammar. These tools automatically check for passive voice, biased language, or incorrect product spelling. ```ini ".vale.ini" # .vale.ini example MinAlertLevel = suggestion Packages = Google, Microsoft [*] BasedOnStyles = Vale, Google ``` ### 3. Automated Enforcement in CI/CD Include consistency checks in your [GitHub Actions](../../guides/integrations/github-actions-cicd.md) or other CI/CD pipelines. This ensures every Pull Request is audited for style and structural consistency before it can be merged. ```bash # Example CI step for linting - name: Lint Documentation run: vale docs/ ``` ## Trade-offs Strict linting can discourage community contributors if they face multiple "style errors" for a simple typo fix. We recommend setting your linter's sensitivity to `warning` for external contributions and reserving `error` status for internal team updates. This balances consistency with inclusivity. --- ## [Previewing Changes](https://docs.docmd.io/guides/workflows-teams/previewing-changes/) --- title: "Previewing Changes" description: "How to set up local and cloud-based preview environments to ensure your documentation renders perfectly before it goes live." --- ## Problem Writing Markdown without a live preview leads to formatting errors, broken containers, and incorrect image paths. These only become visible once the content is in production. This results in a frustrating user experience and forces maintainers to push hotfixes for rendering issues. ## Why it matters High-quality documentation is essential for developer trust. A broken warning box or unrendered syntax looks unprofessional and misleads users. Seeing the "real" documentation before it goes live is the best way to catch errors, improve readability, and ensure a seamless user experience. ## Approach Implement a multi-stage preview strategy: use docmd's [Local Development](../../getting-started/quick-start.md#local-development) server for immediate feedback while writing, and use ephemeral cloud environments (like Vercel or Cloudflare Pages) for final reviews within your Pull Requests. ## Implementation ### 1. Instant Local Previews The fastest way to see your changes is by running the `npx @docmd/core dev` server. It features Hot Module Replacement (HMR). This automatically refreshes your browser the moment you save a Markdown file. ```bash # Start the local development server npx @docmd/core dev ``` ### 2. Cloud-Based Preview Environments For collaborative reviews, configure your CI/CD platform to generate unique "Preview URLs" for every Pull Request. Since docmd outputs standard static files, it is compatible with all major hosting providers. * **Build Command**: `npx @docmd/core build` * **Output Directory**: `site` This allows reviewers to see exactly how changes look and behave in a production-like environment before merging them into the main branch. ### 3. Collaborative Reviews with Threads Combine your cloud previews with the [Threads Plugin](../../plugins/threads.md). This allows team members to leave feedback directly on the rendered preview page. It bridges the gap between the source Markdown and the final user experience. ## Trade-offs Building a full static site for every commit in a massive repository can be time-consuming and costly in terms of CI/CD resources. To optimise this, configure your CI pipeline to only trigger a documentation build when files within your source directory (e.g., `/docs`) have been modified. --- ## [Setting Up a Workflow](https://docs.docmd.io/guides/workflows-teams/setting-up-workflow/) --- title: "Setting Up a Workflow" description: "How to establish a high-velocity, multi-author documentation workflow using docmd and docs-as-code principles." --- ## Problem When teams lack a structured workflow, updates are delayed or forgotten. Without a clear process, content becomes fragmented and formatting becomes inconsistent. Technical writers spend more time resolving merge conflicts than writing high-quality content. ## Why it matters Without a formal process, documentation quickly becomes outdated. If updating documentation requires waiting on a slow software release cycle, guides will remain out of sync with product features. This leads to user frustration and increased support volume. ## Approach Decouple documentation deployments from software release cycles. Adopt the same reliable processes used in software engineering (Branches → Pull Requests → CI/CD Previews). docmd's lightweight nature allows teams to treat "documentation as code" with minimal overhead. ## Implementation ### 1. Repository Strategy Choose the strategy that best fits your organisational structure: * **Monorepo Strategy**: Keep a `/docs` folder within your main application repository. This ensures documentation changes merge in the same Pull Request as the code they describe. * **Separate Repository Strategy**: Best for large organisations or open-source projects where a dedicated team manages documentation independently. ### 2. Validation with CI/CD Integrate docmd into your CI/CD pipeline to ensure every update is technically sound. At a minimum, your pipeline should run the build command to check for syntax errors and configuration issues. ```bash # Example validation step in GitHub Actions - name: Validate Documentation run: npm install && npx @docmd/core build ``` See the [GitHub Actions Guide](../../guides/integrations/github-actions-cicd.md) for detailed setup instructions. ### 3. Collaborative Review Process Establish a culture of peer review for all documentation updates. Use Pull Requests to discuss changes, verify formatting, and ensure technical accuracy. Use the [Threads Plugin](../../plugins/threads.md) to facilitate discussions directly on the rendered content. ## Trade-offs Adopting a "docs-as-code" workflow can create a barrier for non-technical contributors who may find Git and Markdown intimidating. To mitigate this, consider using GitHub's built-in web editor for minor fixes. Alternatively, use the [Live Preview](../../content/live-preview.md) feature to provide a visual and intuitive authoring experience. --- ## [Versioning Workflows](https://docs.docmd.io/guides/workflows-teams/versioning-release-workflows/) --- title: "Versioning Workflows" description: "How to synchronise documentation releases with software deployment using docmd's versioning engine and promotion strategies." --- ## Problem Synchronising software releases with corresponding documentation updates is a coordination challenge. Frequently, documentation updates on the live site before new code deploys (confusing current users) or delays several days (frustrating early adopters). ## Why it matters Desynchronisation between software behaviour and its documentation causes developer friction. For documentation to be effective, it must strictly map to the software version the user is running. Providing correct context for every version ensures smooth onboarding and troubleshooting. ## Approach Isolate active development documentation using docmd's [Versioning Engine](../../configuration/versioning.md). This allows your team to draft content for upcoming features asynchronously in a separate directory (e.g., `docs-next/`). Promote it to "Stable" status only when the official software release occurs. ## Implementation ### 1. Structure Your Directories Maintain your stable documentation in the primary `docs/` folder. Create a dedicated directory for the upcoming release. ```text project-root/ ├── docs/ # Current Stable (v1.x) ├── docs-v2/ # Upcoming Release (v2.0) └── docmd.config.json ``` ### 2. Configure Versions Register both versions in your configuration. Label the upcoming version as "Beta" or "Next" to signal its status to users through the version switcher. ```json "versions": { "current": "v1.0", "all": [ { "id": "v1.0", "dir": "docs", "label": "v1.x (Stable)" }, { "id": "v2.0", "dir": "docs-v2", "label": "v2.0 (Beta)" } ] } ``` ### 3. The Promotion Process When you are ready to officially release the new version: 1. **Update Config**: Change the `current` version ID in `docmd.config.json` to `v2.0`. 2. **Update Labels**: Remove the "(Beta)" tag from the `label` in the `all` array. 3. **Archive Old Docs**: Keep the `v1.0` entry in the `all` array so users on older versions can still access relevant documentation. ## Trade-offs ### Maintenance Overhead Maintaining multiple versions of documentation requires discipline. If a critical typo or security warning is fixed in the stable version, ensure it is also applied to the upcoming version directory to prevent regressions. ### SEO and Search Multiple versions can occasionally lead to search results pointing to older documentation. Use the `seo` plugin and proper canonical tags to ensure the "Current" version is always prioritised by search engines. See [Handling Breaking Changes](../scaling-architecture/breaking-changes-deprecations.md) for more details. --- ## [Avoiding Anti-Patterns](https://docs.docmd.io/guides/writing-quality/avoiding-anti-patterns/) --- title: "Avoiding Anti-Patterns" description: "How to identify and eliminate common documentation mistakes that degrade the user experience and increase content debt." --- ## Problem Documentation repositories accumulate "quick fixes" that inadvertently erode the user experience. Anti-patterns - such as vague link text or bloated code samples - become entrenched. This makes documentation harder to maintain and less useful for developers. ## Why it matters Anti-patterns contribute to "content debt". They degrade search engine rankings (SEO), reduce accessibility, and increase cognitive load on readers trying to find quick solutions. High-quality documentation requires constant vigilance to keep it clean, concise, and professional. ## Approach Identify and ruthlessly eliminate common anti-patterns during the [Peer Review process](../workflows-teams/git-based-workflows.md). Use automated prose linters like Vale and manual reviews to ensure content remains high-quality, accessible, and consistent. ## Implementation ### 1. Non-Descriptive Hyperlinks Avoid generic text like "click here" or "read more" for links. This harms SEO and makes documentation inaccessible for screen reader users who navigate by skipping between links. * **❌ Bad**: To configure your server, [click here](../../configuration/overview.md). * **✅ Good**: Review the [General Configuration](../../configuration/overview.md) to set up your production server. ### 2. The "Wall of Boilerplate" In code examples, dozens of lines of standard imports and boilerplate distract the reader from the core logic. * **Solution**: Focus on the relevant code snippet. If boilerplate is necessary, use comments to indicate omissions or use [Callouts](../../content/containers/callouts.md) to explain the required setup. ### 3. Using FAQs as "Dumping Grounds" "Frequently Asked Questions" (FAQ) pages often become a repository for information that failed to integrate into main guides. If a question is truly "frequently asked," it indicates your core documentation failed to explain the concept effectively. * **Solution**: Instead of adding to an FAQ, refactor the relevant tutorial or conceptual guide to address the confusion where the user first encounters it. Use an [Important Callout](../../content/containers/callouts.md) if the information is critical. ## Trade-offs Eliminating FAQs requires writers to refactor and improve existing documentation hierarchies constantly. While this adds initial maintenance overhead, it results in a significantly more cohesive, professional, and useful documentation site. --- ## [Improving Readability](https://docs.docmd.io/guides/writing-quality/improving-readability/) --- title: "Improving Readability" description: "How to use visual rhythm, information hierarchy, and docmd's structural tools to create highly readable documentation." --- ## Problem Technical documentation is often dense, jargon-heavy, and difficult to scan. When readers encounter "walls of text" without visual relief, they skim over important details. Dense formatting increases cognitive friction, leading to user frustration and potential errors. ## Why it matters Readability is a functional requirement. If a developer misses a warning buried in a long paragraph, the consequences can be severe. A clear information hierarchy ensures users find information quickly, understand it accurately, and act safely. ## Approach Establish a predictable visual rhythm by breaking up long sections of text. Use [Thematic Containers](../../content/containers/index.md) to highlight critical information. By utilising docmd's built-in structural tools, you create a hierarchy that guides the reader's eye naturally toward the most important parts of the page. ## Implementation ### 1. The "Power of Brevity" Limit paragraphs to three or four sentences. Shorter paragraphs are easier to digest on screens and provide "breathing room" for complex technical concepts. If a paragraph feels too long, break it into a list or use a sub-heading. ### 2. Categorising with Callouts Use [Callouts](../../content/containers/callouts.md) consistently to categorise information. This allows skimming users to recognise the intent of a block based on its visual style: * **Info**: Background context or supplementary details. * **Tip**: Best practices, shortcuts, and "pro-tips". * **Warning/Danger**: Critical actions that could lead to errors, data loss, or security vulnerabilities. ```markdown ::: callout warning "Production Safety" Never execute this command on a live database without verifying backups first. ::: ``` ### 3. Sequential Instruction with Steps For tutorials, avoid narrative descriptions of actions. Instead, use the [Steps Container](../../content/containers/steps.md) to create a clear, numbered progression. ```markdown ::: steps 1. **Initialise**: Run `npx @docmd/core init` in your project root. 2. **Configure**: Update your `docmd.config.json` with your site title and navigation. 3. **Build**: Run `npx @docmd/core build` to generate your production-ready static files. ::: ``` ## Trade-offs Using specialised containers like `::: steps` or `::: callout` requires contributors to learn docmd-specific Markdown extensions. While this adds a small learning curve, the significant improvement in information density and clarity far outweighs the minimal effort required. --- ## [Scalable Technical Writing](https://docs.docmd.io/guides/writing-quality/scalable-technical-writing/) --- title: "Scalable Technical Writing" description: "How to use Progressive Disclosure and structural containers to manage growing documentation complexity without overwhelming your users." --- ## Problem In the early stages, documenting a feature takes a few paragraphs. As the product evolves, those paragraphs explode into a sea of edge cases, platform variations, and complex options. This results in "vertical bloat," where a page becomes an unreadable wall of text. ## Why it matters Vertical bloat destroys comprehension and increases cognitive load. When users scroll through pages of irrelevant content, they become overwhelmed. They often assume the product is more complex than it actually is. Scalable writing ensures users only see the information they need at any given moment. ## Approach Implement **Progressive Disclosure**. This technique involves presenting only the most critical information upfront (the "Happy Path"). You hide complex, technical, or specific details behind interactive UI structures. docmd provides built-in containers specifically designed to manage this complexity effectively. ## Implementation ### 1. Handling Variations with Tabs Instead of listing instructions sequentially for multiple package managers, use the [Tabs Container](../../content/containers/tabs.md). This allows the user to select their specific environment. It instantly hides irrelevant commands and reduces visual noise. ````markdown ::: tabs == tab "npm" ```bash npm install docmd ``` == tab "pnpm" ```bash pnpm add docmd ``` ::: ```` ### 2. Managing Edge Cases with Collapsibles If a troubleshooting step only applies to a small percentage of users, do not let it interrupt the main tutorial's logical flow. Use the [Collapsible Container](../../content/containers/collapsible.md) to bury these details while keeping them accessible. ```markdown 1. Start the development server by running `npx @docmd/core dev`. ::: collapsible "Troubleshooting: Port already in use" If you receive an `EADDRINUSE` error, you can specify a custom port using the `--port` flag: `npx @docmd/core dev --port 4000`. ::: ``` ### 3. Progressive Detail with Callouts Use [Callouts](../../content/containers/callouts.md) to provide supplementary information that isn't required for the primary task but offers valuable context for advanced users. ## Trade-offs Hiding content inside tabs or collapsibles can occasionally make it harder for users to find information using the browser's native `Ctrl+F` search. However, docmd's integrated [Search Engine](../../plugins/search.md) indexes all content within these containers. This ensures users can still find exactly what they need while enjoying a cleaner reading experience. --- ## [Task vs. Concept](https://docs.docmd.io/guides/writing-quality/task-vs-concept/) --- title: "Task vs. Concept" description: "How to apply the Diátaxis framework to separate 'How-To' guides from conceptual explanations for a more effective documentation structure." --- ## Problem A frequent mistake in technical writing is mixing the *Why* something works with the *How* to do it. A tutorial on "Configuring SSO", for example, can become bogged down with pages explaining the SAML protocol's history. This distracts the user from their immediate goal of getting the feature running. ## Why it matters User intent varies significantly. An engineer fixing a production issue at 2 AM needs specific, actionable steps - not architectural philosophy. Conversely, a technical leader evaluating your platform needs to understand the underlying logic before committing. Separating these concerns ensures both personas find the information they need without unnecessary friction. ## Approach Adopt the **Diátaxis framework**, which categorises documentation into four quadrants: Tutorials, How-to Guides, Explanation (Concepts), and Technical Reference. For this guide, we focus on the critical separation between **Task-oriented content** (actionable steps) and **Concept-oriented content** (deeper understanding). ## Implementation ### 1. The Task-Oriented Guide (How-To) Focus entirely on a specific, narrow objective. Strip out lengthy theoretical explanations and focus on the minimum steps required to achieve the goal. Use the [Steps Container](../../content/containers/steps.md) to provide a clear, unambiguous path forward. * **Title Example**: "How to Configure Webhooks" * **Structure**: * Prerequisites * Direct, actionable instructions * Verification steps (how to know it worked) ### 2. The Concept-Oriented Guide (Explanation) Focus on the "Big Picture", including architecture, design philosophy, and the "why" behind specific decisions. Avoid giving direct instructions or commands in these sections. * **Title Example**: "Understanding Webhook Delivery Architecture" * **Structure**: * High-level architecture diagrams * Retry logic and reliability philosophy * Security considerations ### 3. Effective Cross-Referencing Instead of merging the two types of content, use docmd's linking tools to provide a bridge for users who need more context or are ready to implement. * **In a How-To guide**: "For a deeper explore our retry logic, see [Webhook Architecture](../../guides/performance-delivery/caching-strategies.md)." * **In a Conceptual guide**: "Ready to get started? Follow our [Webhook Configuration Guide](../../guides/integrations/alongside-other-tools.md)." ## Trade-offs Separating tasks and concepts increases the number of pages in your navigation and requires rigorous cross-linking. However, this modular structure significantly improves the long-term maintainability, searchability, and overall professionalism of your documentation suite. --- ## [docmd docs: deploy production-ready docs from Markdown](https://docs.docmd.io/) --- title: "docmd docs: deploy production-ready docs from Markdown" description: "Build production-ready documentation from Markdown in seconds. Zero setup, fast by default, SEO-friendly, and AI-ready." titleAppend: false --- ::: hero # docmd Markdown to production docs in one command. Static HTML for SEO. SPA for speed. Works with AI tools out of the box. ::: button "Get Started" ./getting-started/quick-start.md icon:rocket ::: button "GitHub" external:https://github.com/docmd-io/docmd color:#24292e icon:github ::: ## Overview docmd is a zero-configuration documentation generator. It builds fast static websites directly from your Markdown files. ```bash npx @docmd/core dev ``` Run this single command. The engine builds your site, generates navigation, and enables search automatically. ## Core Capabilities Everything needed for solid documentation ships built in. No extra plugins required for the essentials. ::: grids ::: grid ::: card "Instant Setup" icon:rocket Start immediately without boilerplate. The engine auto-detects files and structures navigation in seconds. ::: ::: ::: grid ::: card "AI Context" icon:brain-circuit Generates `llms.txt` and `llms-full.txt` automatically. Your docs stay readable to AI assistants. ::: ::: ::: grid ::: card "OKF Bundles" icon:database Generates an Open Knowledge Format bundle, typed concept graph for AI agents. Read [more](external:https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing). ::: ::: ::: grid ::: card "Native MCP Server" icon:terminal Built-in Model Context Protocol server with native tools. AI agents query and validate your docs over a local stdio connection — no network, no remote service. ::: ::: ::: grid ::: card "Local-First Search" icon:search Fast, client-side full-text search powered by MiniSearch. Works out of the box across versions and locales. ::: ::: ::: grid ::: card "Live Previews" icon:monitor Render Markdown instantly in the browser with the `docmd.compile` API. Power live editors, CMS previews, and in-app docs. ::: ::: ::: grid ::: card "Custom Templates" icon:palette Personalise your documentation with templates or try built-in themes with custom CSS. Supports dark mode and system prefs. ::: ::: ::: grid ::: card "Native Translation" icon:globe First-class i18n support. Features locale-first routing, individual search indexes, and translated UI strings. ::: ::: ::: ::: callout info "Rich Content Containers" icon:info Go beyond standard Markdown. Use structured visual patterns like steps, tabs, cards, grids, and callouts directly in your text. ::: button "Explore Containers" ./content/containers/index.md icon:blocks ::: --- ## [Migrating from Docusaurus](https://docs.docmd.io/migration/docusaurus/) --- title: "Migrating from Docusaurus" description: "A comprehensive guide on moving your Docusaurus v2/v3 project to docmd." --- # Migrating from Docusaurus to docmd Docusaurus is a popular React-based documentation framework. docmd provides a fast, zero-config alternative. It compiles significantly faster and doesn't require React components to render rich features. ## Step 1: Run the Migration Engine Run the following command at the root of your existing Docusaurus project: ```bash npx @docmd/core migrate --docusaurus ``` ### What Happens Automatically 1. **Backup**: Your entire project (excluding `node_modules` and `.git`) is safely moved into a new `docusaurus-backup/` directory. 2. **Content Migration**: Your `docs/` folder is restored to the root directory for docmd to use. 3. **Config Generation**: A `docmd.config.json` is generated, extracting your site `title` from your Docusaurus configuration. ## Step 2: Test the Setup Once the command finishes, you can immediately preview your Markdown content in docmd: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration Docusaurus has complex programmatic configurations that docmd does not try to guess. You must map these manually. ### 1. Navigation Setup Docusaurus sidebars are often auto-generated or configured in `sidebars.js`. **Action required:** Create a `navigation.json` inside your new `docs/` directory to structure your docmd sidebar. See the [Navigation Guide](../configuration/navigation.md). ### 2. Replacing MDX Components Docusaurus relies heavily on MDX (`.mdx`) to render custom React components. docmd is purely Markdown-driven and does not use React. **Action required:** Convert any custom `<MyReactComponent />` tags into standard Markdown or use docmd's native [Containers](../content/containers/callouts.md). #### Example: Converting Admonitions **Docusaurus:** ```markdown :::tip My Tip This is a helpful tip. ::: ``` ::: callout success "Zero Changes Required" Docusaurus admonition syntax works **without any modification**. The following aliases are fully supported: - `:::note` → renders as `callout info` - `:::tip` → renders as `callout tip` - `:::info` → renders as `callout info` - `:::caution` → renders as `callout warning` - `:::danger` → renders as `callout danger` Spaceless syntax is also supported. Your existing Docusaurus admonitions will render correctly in docmd without changes. ::: **docmd native syntax** (optional, provides more features like custom icons): ```markdown ::: callout tip "My Tip" This is a helpful tip. ::: ``` #### Example: Converting Tabs **Docusaurus:** ```jsx import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; <Tabs> <TabItem value="apple" label="Apple" default> This is an apple. </TabItem> <TabItem value="orange" label="Orange"> This is an orange. </TabItem> </Tabs> ``` **docmd:** (Convert to the native docmd tabs container syntax) ```markdown ::: tabs == tab "Apple" This is an apple. == tab "Orange" This is an orange. ::: ``` ### 3. Localisation (i18n) If you used Docusaurus's `i18n` features, your translated files were likely in `i18n/locale/docusaurus-plugin-content-docs/current/`. **Action required:** Move these files into docmd's directory structure (`docs/en/`, `docs/es/`, etc.) and configure the locales in `docmd.config.json`. See the [Localisation Guide](../configuration/localisation/index.md). ## Next Steps - Explore the [Layout & UI](../configuration/layout-ui.md) settings to match your Docusaurus theme. - Convert React-based hero headers into docmd [Hero Containers](../content/containers/hero.md). --- ## [Migrating from MkDocs](https://docs.docmd.io/migration/mkdocs/) --- title: "Migrating from MkDocs" description: "A comprehensive guide on moving your MkDocs (or Material for MkDocs) project to docmd." --- # Migrating from MkDocs to docmd MkDocs is a popular Python-based generator. docmd provides a similar Markdown-first experience. It relies on Node.js/Bun for incredibly fast builds without complex Python extensions. ## Step 1: Run the Migration Engine Run the following command at the root of your existing MkDocs project: ```bash npx @docmd/core migrate --mkdocs ``` > **0.8.10 polish** — `package.json` and lockfiles stay in place during the backup; your original `site_dir` is preserved; the top-level `nav:` block is auto-translated to docmd's `navigation` format (with multi-level `children`). Add `--dry-run` to preview without writing, or `--upgrade` to translate a legacy `docmd.config` to the modern schema. ### What Happens Automatically 1. **Backup**: Your entire project is safely moved into a new `mkdocs-backup/` directory (lockfiles and `package.json` stay in place). 2. **Content Migration**: Your `docs/` folder is restored to the root directory for docmd to use. 3. **Config Generation**: A `docmd.config.json` is generated, extracting your `site_name` (and, since 0.8.10, your `site_dir`) from `mkdocs.yml`. 4. **Navigation**: A top-level `nav:` block is translated to docmd's `navigation` array automatically. ## Step 2: Test the Setup Once the command finishes, preview your content in docmd: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration MkDocs uses `mkdocs.yml` to define site navigation and extensions. You must translate this setup to docmd manually. ### 1. Navigation Setup In MkDocs, navigation is strictly defined in the `nav` key of `mkdocs.yml`. **As of 0.8.10:** a top-level `nav:` block is auto-translated to docmd's `navigation` array (multi-level sections become nested `children`). You only need to create a manual `navigation.json` if your nav is more complex than the simple form below (e.g. external links, anchors, conditional nav). **Action required (if needed):** Create a `navigation.json` inside your `docs/` folder. ```yaml "mkdocs.yml" nav: - Home: index.md - Guide: - Setup: setup.md - Usage: usage.md ``` ```json "navigation.json" [ { "title": "Home", "path": "/" }, { "title": "Guide", "collapsible": true, "children": [ { "title": "Setup", "path": "/setup" }, { "title": "Usage", "path": "/usage" } ] } ] ``` ### 2. Replacing Python Markdown Extensions If you used "Material for MkDocs", you likely relied on Python Markdown extensions for tabs or admonitions. **Action required:** Convert MkDocs-specific extension syntax to docmd's native [Containers](../content/containers/callouts.md). #### Example: Converting Admonitions **MkDocs (PyMdown):** ```markdown !!! note "Optional Title" This is an admonition content block. ``` ::: callout warning "Manual Conversion Required" MkDocs uses `!!!` syntax for admonitions, which differs from docmd's `:::` syntax. You must convert these manually or use a find-and-replace tool. **Mapping:** - `!!! note` → `::: callout info` or `:::note` - `!!! tip` → `::: callout tip` or `:::tip` - `!!! warning` → `::: callout warning` or `:::warning` - `!!! danger` → `::: callout danger` or `:::danger` - `!!! example` → `::: callout info` ::: **docmd:** ```markdown ::: callout info "Optional Title" This is an admonition content block. ::: ``` #### Example: Converting Tabs **MkDocs (SuperFences):** ```markdown === "Tab 1" Content for tab 1. === "Tab 2" Content for tab 2. ``` **docmd:** ```markdown ::: tabs == tab "Tab 1" Content for tab 1. == tab "Tab 2" Content for tab 2. ::: ``` ## Next Steps - docmd has native search. You do not need to configure a search plugin. - Explore the [Theming options](../theming/customisation.md) to customise colours to match your old Material theme. --- ## [Migration Overview](https://docs.docmd.io/migration/overview/) --- title: "Migration Overview" description: "Learn how to easily migrate your existing documentation to docmd." --- # Migrating to docmd docmd provides a fully automated **migration engine**. Transition from legacy platforms with a single command. The engine eliminates the tedious work of moving Markdown files and restructuring directories. ## How It Works The migration command will: 1. **Detect** your existing configuration file (e.g., `docusaurus.config.js`, `mkdocs.yml`). 2. **Extract** core metadata like your site's `title`. 3. **Backup** your existing files and directories safely into a `*-backup/` directory. 4. **Copy** your Markdown content into the standard docmd `docs/` directory. 5. **Generate** a fresh `docmd.config.json` tailored for your content. > **0.8.10 polish** — lockfiles (`package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock*`) stay in place during the backup; Docusaurus `staticDir` and MkDocs `site_dir` are preserved; MkDocs `nav:` is auto-translated to docmd's `navigation` (with multi-level `children`); and `--dry-run` previews the migration without writing. See the [0.8.10 release notes](../release-notes/0-8-10.md). You can then run `npx @docmd/core dev` immediately to see your content rendered. ## What is Migrated | Feature | Migrated Automatically? | | :--- | :--- | | **Markdown Files** | ✅ Yes, all `.md` and `.mdx` files are moved to `docs/` | | **Directory Structure** | ✅ Yes, your folder nesting is preserved | | **Site Title** | ✅ Yes, extracted from your config | | **Container Syntax** | ✅ Yes, VitePress/Docusaurus containers work without changes | | **Navigation / Sidebar** | ⚠️ Mostly — MkDocs `nav:` is auto-translated since 0.8.10; other sources still need manual mapping | | **Localisation (i18n)** | ⚠️ **No**, requires manual mapping | | **Versioning** | ⚠️ **No**, requires manual mapping | | **Custom React/Vue Components** | ❌ No, these must be replaced with docmd Containers | ::: callout success "Container Syntax Compatibility" Container syntax from **VitePress** (`:::tip`, `:::warning`, `:::danger`, `:::info`, `:::details`) and **Docusaurus** (`:::note`, `:::caution`) works without modification. Your existing admonitions and collapsible sections render correctly in docmd. **MkDocs** uses `!!!` syntax, which requires manual conversion to `:::` format. ::: ## Why Navigation and i18n Aren't Automatically Migrated Every platform handles navigation sidebars, translations, and multi-versioning differently. For example, Docusaurus uses complex JavaScript objects. MkDocs relies on strictly indented YAML structures. Rather than risking a broken migration by guessing complex configurations, docmd moves your content safely. You must configure navigation, localisation, and versioning natively using docmd's JSON-based APIs. - **Navigation:** Learn how to create a `navigation.json` in the [Navigation Setup](../configuration/navigation.md). - **Localisation:** See the [Localisation Guide](../configuration/localisation/index.md) for setting up multi-language docs. - **Versioning:** Refer to the [Versioning Setup](../configuration/versioning.md). ## Supported Platforms Select your current platform for specific migration instructions: - [Migrating from Docusaurus](./docusaurus.md) - [Migrating from MkDocs](./mkdocs.md) - [Migrating from VitePress](./vitepress.md) - [Migrating from Astro Starlight](./starlight.md) --- ## [Migrating from Astro Starlight](https://docs.docmd.io/migration/starlight/) --- title: "Migrating from Astro Starlight" description: "A comprehensive guide on moving your Astro Starlight project to docmd." --- # Migrating from Astro Starlight to docmd Starlight is a documentation theme built on Astro. docmd provides a similar zero-JavaScript-by-default experience. It eliminates the need to configure a full web framework, reducing the learning curve. ## Step 1: Run the Migration Engine Run the following command at the root of your existing Starlight project: ```bash npx @docmd/core migrate --starlight ``` ### What Happens Automatically 1. **Backup**: Your entire project is safely moved into a new `starlight-backup/` directory. 2. **Content Migration**: Starlight keeps documentation in `src/content/docs/`. The migration engine extracts this directory and moves its contents to the root `docs/` folder. 3. **Config Generation**: A `docmd.config.json` is generated, extracting your site `title` from the Starlight integration inside `astro.config.mjs`. ## Step 2: Test the Setup Once the command finishes, preview your content in docmd: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration ### 1. Navigation Setup Starlight defines navigation in `astro.config.mjs` via the `sidebar` array. **Action required:** Create a `navigation.json` inside your new `docs/` folder. **Starlight (`astro.config.mjs`):** ```javascript sidebar: [ { "label": "Guides", "items": [ { "label": "Setup", "link": "/guides/setup/" } ] } ] ``` **docmd (`navigation.json`):** ```json [ { "title": "Guides", "collapsible": true, "children": [ { "title": "Setup", "path": "/guides/setup" } ] } ] ``` ### 2. Replacing Astro Components (MDX/Markdoc) Starlight uses Astro components embedded via MDX or Markdoc. Because docmd relies on pure Markdown syntax, these must be converted. **Action required:** Replace Astro components with docmd [Containers](../content/containers/callouts.md). #### Example: Converting Tabs **Starlight:** ```mdx import { Tabs, TabItem } from '@astrojs/starlight/components'; <Tabs> <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem> <TabItem label="Moons">Io, Europa, Ganymede</TabItem> </Tabs> ``` **docmd:** ```markdown ::: tabs == tab "Stars" Sirius, Vega, Betelgeuse == tab "Moons" Io, Europa, Ganymede ::: ``` #### Example: Converting Asides (Admonitions) **Starlight:** ```mdx :::note[Optional Title] Some note content. ::: ``` **docmd:** ```markdown ::: note "Optional Title" Some note content. ::: ``` ### 3. Frontmatter Mapping Starlight has strict frontmatter typing via Astro content collections. docmd frontmatter is simpler. If you used `hero` or `banner` frontmatter properties in Starlight for landing pages, replace them with docmd's [Hero Sections](../content/containers/hero.md) written directly in the Markdown body. ## Next Steps - Explore docmd's built-in [Search plugin](../plugins/search.md). Starlight uses Pagefind, while docmd ships with a highly optimised local search indexer natively. --- ## [Migrating from VitePress](https://docs.docmd.io/migration/vitepress/) --- title: "Migrating from VitePress" description: "A comprehensive guide on moving your VitePress project to docmd." --- # Migrating from VitePress to docmd VitePress is a fast Vue-powered SSG framework. docmd is equally fast, but it ships zero JavaScript framework logic to the client. This eliminates Vue hydration overhead. ## Step 1: Run the Migration Engine Run the following command at the root of your existing VitePress project: ```bash npx @docmd/core migrate --vitepress ``` ### What Happens Automatically 1. **Backup**: Your entire project is safely moved into a new `vitepress-backup/` directory. 2. **Content Migration**: Your `docs/` folder is restored to the root directory for docmd to use. The `.vitepress` hidden configuration folder is completely stripped to prevent conflicts. 3. **Config Generation**: A `docmd.config.json` is generated, extracting your site `title` from `.vitepress/config.js` or `.ts`. ## Step 2: Test the Setup Once the command finishes, preview your content in docmd: ```bash npx @docmd/core dev ``` Your Markdown files will compile, but your navigation sidebar will be empty. ## Step 3: Manual Configuration VitePress configures navigation in its config file and uses Vue components inside Markdown. You must translate these to docmd. ### 1. Navigation Setup VitePress uses an array of objects in `themeConfig.sidebar`. **Action required:** Create a `navigation.json` inside your `docs/` directory. **VitePress (`.vitepress/config.js`):** ```javascript themeConfig: { "sidebar": [ { "text": "Guide", "items": [ { "text": "Introduction", "link": "/introduction" }, { "text": "Getting Started", "link": "/getting-started" } ] } ] } ``` **docmd (`navigation.json`):** ```json [ { "title": "Guide", "collapsible": true, "children": [ { "title": "Introduction", "path": "/introduction" }, { "title": "Getting Started", "path": "/getting-started" } ] } ] ``` ### 2. Replacing Vue Components VitePress allows authors to embed Vue components directly in Markdown files. Because docmd does not run Vue on the client, you must remove custom components or replace them with native Markdown. **Action required:** Replace Vue-specific UI components with docmd [Containers](../content/containers/callouts.md). #### Example: Admonitions (Custom Containers) VitePress uses a markdown-it custom block syntax that looks similar to docmd. **VitePress:** ```markdown ::: info This is an info box. ::: ``` **docmd:** ```markdown ::: info This is an info box. ::: ``` ::: callout success "Zero Changes Required" VitePress container syntax works **without any modification**. The following aliases are fully supported: - `:::tip` → renders as `callout tip` - `:::warning` → renders as `callout warning` - `:::danger` → renders as `callout danger` - `:::info` → renders as `callout info` - `:::details` → renders as `collapsible` Spaceless syntax is also supported. Your existing VitePress content will render correctly in docmd without changes. ::: ## Next Steps - Explore docmd's [Build & Deploy](../deployment/index.md) guide. docmd does not rely on Vite's build pipeline. - Review the full list of [docmd Containers](../content/containers/index.md) for additional UI components. --- ## [Analytics Plugin](https://docs.docmd.io/plugins/analytics/) --- title: "Analytics Plugin" description: "Integrate Google Analytics 4 or legacy Universal Analytics and track user interactions automatically." --- The `@docmd/plugin-analytics` plugin allows you to easily integrate Google Analytics into your documentation. It supports the modern Google Analytics 4 (GA4) standard, legacy Universal Analytics (UA), and includes native event tracking for interaction-heavy documentation sites. ## Configuration Enable analytics by adding your tracking credentials to the `plugins` section of your `docmd.config.json`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `googleV4` | `object` | `null` | Google Analytics 4 configuration (requires `measurementId`). | | `googleUA` | `object` | `null` | Universal Analytics configuration (requires `trackingId`). | | `autoEvents` | `boolean` | `true` | Automatically track clicks, downloads, and TOC interactions. | | `trackSearch` | `boolean` | `true` | Track search keywords used by readers. | ### Example ```json "docmd.config.json" { "plugins": { "analytics": { "googleV4": { "measurementId": "G-XXXXXXX" }, "autoEvents": true, "trackSearch": true } } } ``` ## Tracked Events When `autoEvents` is enabled, the plugin captures the following interactions automatically: - **External links**: outbound clicks to other domains. - **Downloads**: clicks on links with the `download` attribute or common file extensions. - **TOC clicks**: section engagement via the right-hand navigation. - **Heading anchors**: clicks on per-section permalinks. - **Search queries**: keywords typed in the search bar (debounced 1 second). ::: callout info "Privacy & GDPR" By default, this plugin does not anonymise IP addresses as that is now handled natively by GA4. If you require advanced cookie consent management, you can manually inject scripts using a custom plugin hook. ::: --- ## [Git Plugin](https://docs.docmd.io/plugins/git/) --- title: "Git Plugin" description: "Repository-aware metadata, last-updated timestamps, and automated edit links derived from Git history." --- The `@docmd/plugin-git` plugin adds repository intelligence to your documentation. It extracts data directly from Git history at build time. It displays when a page was last modified, who contributed, and provides an optional "Edit this page" link. ## Configuration | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `repo` | `string` | `null` | Repository URL (e.g. `https://github.com/org/repo`). Required for edit links. | | `branch` | `string` | `'main'` | Branch name for edit links. | | `editLink` | `boolean` | `true` | Show "Edit this page" link when `repo` is set. | | `lastUpdated` | `boolean` | `true` | Show last updated timestamp. | | `commitHistory` | `boolean` | `true` | Show commit history tooltip on hover. | | `maxCommits` | `number` | `5` | Maximum commits to show in the tooltip (if `commitHistory` is true). | | `dateFormat` | `string` | `'relative'` | Timestamp format: `relative` (default), `iso`, or `locale-aware`. | ### Example ```json "docmd.config.json" { "plugins": { "git": { "repo": "https://github.com/org/repo", "branch": "main", "editLink": true, "lastUpdated": true, "commitHistory": true, "maxCommits": 5 } } } ``` ## Features - **Last-updated timestamps**: shown in the page footer. - **Commit history tooltip**: hover the timestamp to see recent commits for the page. - **Edit links**: optional links to edit the source file on GitHub, GitLab, or Bitbucket. - **Build-time caching**: Git history is queried once and cached, so site performance is unaffected. ## Behaviour Once configured, the plugin works automatically. Timestamps and edit links appear in the page footer. ### Footer Example ::: callout info "Rendering Result" The footer of this page is rendered by the Git plugin. Scroll to the bottom to see it in action. Hover over the **Last updated** date to see the commit history. ::: ## Per-Page Control Disable Git features for specific pages via frontmatter: ```markdown --- title: "Internal Notes" plugins: git: false --- ``` ## CI/CD Integration The Git plugin reads your repository history at build time using local Git commands. Many CI/CD providers use "shallow clones" by default (fetching only the last commit). This causes the plugin to show only the most recent change across all pages. To ensure accurate timestamps and history, configure your CI environment to perform a full fetch. ::: tabs == tab "GitHub Actions" Add `fetch-depth: 0` to your checkout step: ```yaml ".github/workflows/docs.yml" - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 ``` == tab "GitLab CI" Set the `GIT_DEPTH` variable to `0`: ```yaml ".gitlab-ci.yml" variables: GIT_DEPTH: 0 ``` == tab "Netlify" Netlify fetches the full history by default. If you encounter issues, ensure your build command has access to the `.git` directory. ::: ::: callout warning "Git Data Requirement" The `.git` directory must be present in the build environment. If building inside a Docker container or restricted CI environment, ensure Git history is preserved and the `git` binary is installed. ::: ## Localisation The plugin includes built-in translations for several common languages (English, German, Chinese, Korean, and others). The full set of bundled locales is maintained in the [source repository](external:https://github.com/docmd-io/docmd/tree/main/packages/plugins/git/i18n). Custom strings can be provided through the [UI Localisation](../configuration/localisation/ui-strings.md) system. --- ## [LLM Context Plugin](https://docs.docmd.io/plugins/llms/) --- title: "LLM Context Plugin" description: "Optimise your documentation for AI consumption with automated llms.txt and llms-full.txt generation." --- The `@docmd/plugin-llms` plugin follows the `llms.txt` standard. It generates two files at build time: a structured summary (`llms.txt`) and a full concatenated context (`llms-full.txt`). AI assistants and tools that understand the standard can use these to ingest your documentation directly. The plugin is **enabled by default** in 0.8.8. To produce absolute links, set `url` in your `docmd.config.json`. ## Generated Output The plugin produces three files at the site root: - `llms.txt` — structured list of all pages with title + description + URL - `llms-full.txt` — the same list but with each page's full markdown body concatenated below the entry - `llms.json` — a machine-readable manifest of every page (title, url, description, priority) These files are linked in the page `<head>` for automatic discovery by AI tools. ## Configuration | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable the LLM context generation. | | `fullContext` | `boolean` | `true` | If true, generates `llms-full.txt` containing the full markdown of every page. | | `maxTokenLimit` | `number` | `null` | Optional limit on the total characters/tokens for context files. | | `i18n` | `boolean` | `false` | When `true`, write per-locale files (`llms.<locale>.txt`, etc.) in addition to the default-locale set. See [Multi-locale output](#multi-locale-output) below. | ### Example ```json "docmd.config.json" { "url": "https://docs.example.com", "plugins": { "llms": { "fullContext": true } } } ``` ## Default behaviour (0.8.8) The plugin writes files for the **default locale only**. This is a deliberate change from earlier versions where the plugin wrote per-locale output by default. The reason: the unsuffixed `llms.txt` / `llms-full.txt` / `llms.json` filenames are the standard names that downstream consumers (Cursor, Claude, GPT, etc.) look for. Splitting them into `llms.en.txt` + `llms.hi.txt` + `llms.fr.txt` would have broken every existing integration. For single-locale projects (no `config.i18n` block) this is invisible — the plugin writes a single set of files at the site root, same as before. For multi-locale projects, only the default-locale pages are in the bundle. ## Multi-locale output (opt-in) To get per-locale files, set `i18n: true`: ```json "docmd.config.json" { "plugins": { "llms": { "i18n": true } } } ``` The plugin then writes: ```text site/llms.txt ← default locale (en) — UNSUFFIXED site/llms-full.txt ← default locale (en) — UNSUFFIXED site/llms.json ← default locale (en) — UNSUFFIXED site/llms.ja.txt ← Japanese — suffixed site/llms-full.ja.txt ← Japanese — suffixed site/llms.ja.json ← Japanese — suffixed site/llms.fr.txt ← French — suffixed site/llms-full.fr.txt ← French — suffixed site/llms.fr.json ← French — suffixed ``` Notice the pattern: **the default locale never gets a suffix** — its files keep the unsuffixed names so existing consumers don't break. Only the non-default locales get a `.<locale>` suffix. For sites with only one locale configured, no per-locale files are written regardless of the `i18n` flag (the suffix would just add noise). ## Security: Sanitised Output (0.8.10) Since 0.8.10, all user-controlled strings (page titles, descriptions) are sanitised before they land in `llms.txt`, `llms-full.txt`, and `llms.json`: - Markdown-special characters (`` ` ``, `[`, `]`, newlines) in titles are escaped so a malicious frontmatter can't break out of the `[title](url)` link form. - Strings starting with `=`, `+`, `-`, or `@` are prefixed with a single-quote so opening the file in a spreadsheet (Excel / Sheets / LibreOffice) does not execute a formula. The body in `llms-full.txt` is preserved verbatim — the file is treated as a first-party channel, and consumers that render it in an HTML context should sanitise on their side. ## Excluding a Page If a page contains sensitive information or internal notes you don't want AI models to learn, use the `llms: false` flag in your frontmatter: ```markdown --- llms: false --- ``` This excludes the page from the LLMS files. The page is still rendered in the regular site HTML and is still included in search results. ## See also - [OKF Bundle Plugin](./okf.md) — the complementary bundle format for AI-agent consumption (typed manifest, graph viewer, per-page concept files). LLMS is the flat list; OKF is the structured graph. - [Building AI-ready docs](../guides/ai-optimisation/generating-ai-ready-docs.md) - [Structure for LLMs](../guides/ai-optimisation/structure-for-llms.md) ::: callout tip "Maximising AI Accuracy" For detailed best practices on structuring your markdown (semantic headings, alt-text, etc.), see our [Optimising for AI Agents](../guides/ai-optimisation/generating-ai-ready-docs.md) guide. ::: --- ## [Math Plugin](https://docs.docmd.io/plugins/math/) --- title: "Math Plugin" description: "Native KaTeX/LaTeX mathematics integration for docmd." --- The **Math plugin** adds native LaTeX and KaTeX support to your docmd sites. It uses `markdown-it-texmath` integrated with the `katex` computation engine. This renders inline and block-level equations smoothly without complex client-side javascript libraries. ## Configuration The Math plugin is an optional plugin. Install it via the CLI: ```bash npx @docmd/core add math ``` Enable it in your `docmd.config.json`: ### Example ```json "docmd.config.json" { "plugins": { "math": {} } } ``` ## How It Works 1. Enable the plugin via your `docmd.config.json`. 2. Wrap your standard LaTeX mathematics in `$` (inline) or `$$` (block) indicators. 3. The engine processes these rules during the build exactly as raw static HTML tags. 4. Minimal injected CSS styles the classes automatically. This yields immediate visualisation on page load. ## Conditional Asset Loading (new in 0.8.7) The KaTeX stylesheet (~30 KB) only loads on pages that actually render math. Pages without any equations skip the fetch entirely, so a 100-page documentation site with only 5 math pages pays for the CSS on those 5 pages only. The detection scans each page's rendered HTML for `class="katex"` or `class="katex-display"` markers and injects the asset conditionally. No configuration needed - the behaviour is automatic. ## Usage ### Inline Mathematics Inject standard equations within a paragraph using single dollar signs `$`: ```markdown Here is an inline equation: $E = mc^2$ ``` Here is an inline equation: $E = mc^2$ ### Block Mathematics For wider mathematical proofs or distinct formulations, use double dollar signs `$$` for block level formatting: ```markdown $$ \sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$ ``` $$ \sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6} $$ --- ## [Mermaid Diagrams](https://docs.docmd.io/plugins/mermaid/) --- title: "Mermaid Diagrams" description: "Create professional architectural diagrams, flowcharts, and sequence diagrams directly in your Markdown files using Mermaid.js syntax." --- The `@docmd/plugin-mermaid` plugin integrates [Mermaid.js](external:https://mermaid.js.org/) into the build pipeline. Plain-text descriptions become interactive diagrams with theme support, panning, and zooming. ## Configuration The plugin is bundled with `@docmd/core` and enabled by default. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable Mermaid rendering globally. | ### Example ```json "docmd.config.json" { "plugins": { "mermaid": {} } } ``` ## Features - **Theme aware**: diagrams adapt to light or dark mode automatically. - **Interactive**: built-in pan, zoom, and fullscreen controls per diagram. - **Lazy initialisation**: scripts load and render only as a diagram enters the viewport. - **Icon pack**: supports `icon:name` syntax backed by the Lucide icon set. ## Usage Embed diagrams using a fenced code block with the `mermaid` language identifier. ### Sequence Diagram Example ::: tabs == tab "Preview" ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Enters URL Browser->>Server: HTTP Request Server-->>Browser: HTTP Response Browser-->>User: Displays Page ``` == tab "Source" ````markdown ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Enters URL Browser->>Server: HTTP Request Server-->>Browser: HTTP Response Browser-->>User: Displays Page ``` ```` ::: ### Architecture Example ```mermaid architecture-beta group api(icon:cloud)[API Service] service db(icon:database)[Database] in api service disk(icon:hard-drive)[Storage] in api db:L -- R:disk ``` ::: callout tip "AI Readability" Because Mermaid diagrams are defined as pure text in your Markdown, they are fully readable by AI agents. This allows LLMs to understand and explain your system architecture directly from your documentation source. ::: --- ## [OKF Bundle Plugin](https://docs.docmd.io/plugins/okf/) --- title: "OKF Bundle Plugin" description: "Generate an Open Knowledge Format (OKF) bundle from your docmd site so AI agents can consume your documentation directly." --- The `@docmd/plugin-okf` plugin generates an **[Open Knowledge Format][okf-spec]** (OKF) bundle for AI-agent consumption. OKF is a vendor-neutral, agent- and human-friendly standard for representing the metadata, context, and curated knowledge that modern AI systems need. The bundle sits next to your site (e.g. `site/okf/`) so agents can be pointed at it directly. The plugin is **enabled by default** in 0.8.8 — no configuration is required. The bundle is generated on every `docmd build`. [okf-spec]: https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing ## What is OKF? OKF is an open specification announced by Google Cloud in June 2026 that formalises the [LLM-wiki pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) into a portable, interoperable format. The motivation: ::: callout info As foundation models continue to improve, the lack of relevant context often limits what they can do, especially as they are used to build agentic systems. While these models can help you write code, summarize documents, or analyze a dataset, they still need the right information to produce accurate and actionable results — [Introducing the Open Knowledge Format](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing) ::: OKF represents organisational knowledge as a directory of markdown files with YAML frontmatter, plus a typed manifest, an interactive graph viewer, and a machine-readable bundle summary. The three principles behind the design: 1. **Minimally opinionated.** OKF requires exactly one thing of every concept: a `type` field. Everything else (what types exist, what other fields to include, what sections the body has) is left to the producer. 2. **Producer/consumer independence.** A bundle hand-authored by a human can be consumed by an AI agent. A bundle generated by a metadata export pipeline can be browsed in a visualizer. A bundle synthesized by one LLM can be queried by another. The format is the contract; the tooling at each end is independently swappable. 3. **Format, not platform.** OKF is not tied to any specific cloud, database, model provider, or agent framework. ## What you get ```text site/okf/ ├── okf.yaml ← typed manifest (bundle summary) ├── index.md ← Karpathy-style catalog grouped by type ├── graph/ ← opt-in: only when `plugins.okf.graph: true` │ ├── index.html ← interactive force-directed viewer (open at /okf/graph/) │ ├── graph.json ← graph data (nodes + edges) │ ├── graph.js ← viewer runtime (vanilla, no CDN deps) │ └── graph.css ← viewer styles (theme-aware) ├── concepts/ │ └── <slug>.md ← one markdown file per page └── _meta/ ├── bundle.json ← JSON mirror of okf.yaml └── lint-report.txt ← warnings produced during generation ``` Each concept file carries the OKF-required `type` field in frontmatter plus the original markdown body verbatim, so an agent can both navigate the manifest and read full pages. ## Default behaviour OKF is a **core plugin** in 0.8.8. The build auto-loads it and generates the bundle with sensible defaults: - **Default-locale only** by default (the bundle contains pages in the default locale only; the default-locale files sit at the bundle root). - **Type inference** — pages under `/api/`, `/guides/`, `/reference/`, `/concepts/`, `/runbooks/`, `/datasets/`, `/metrics/`, `/tables/` are auto-classified; everything else falls back to `concept`. - **Full markdown** in each concept file (the original page body is included, not just a frontmatter stub). You do not need to add anything to `docmd.config.json` to get an OKF bundle. The plugin runs with empty options and uses all defaults. ### Opting out Three opt-out paths are supported: ```json "docmd.config.json" { "plugins": { "okf": false } } ``` ```json "docmd.config.json" { "plugins": { "okf": { "enabled": false } } } ``` ```json "docmd.config.json" { "plugins": { "okf": { "capabilities": ["head"] } } } ``` The last form uses the plugin trust model — the `okf` plugin declares `capabilities: ['post-build']`; if your `config.plugins.okf.capabilities` array does not include `post-build`, the plugin is loaded but its `onPostBuild` hook does not run. This matches every other core plugin. ## Configuration All keys are optional. Listed values are the defaults: | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable the OKF bundle generation. | | `outputDir` | `string` | `'okf'` | Bundle directory, relative to the site output. | | `bundleName` | `string` | slugified `config.title` | Name used inside `okf.yaml` and the graph viewer title. | | `defaultType` | `string` | `'concept'` | Type assigned to pages with no explicit type. | | `typeField` | `string` | `'type'` | Frontmatter field name for OKF type. | | `warnOnMissingType` | `boolean` | `true` | Emit a TUI warning for pages that fell back to `defaultType`. | | `includeFullMarkdown` | `boolean` | `true` | Copy raw `.md` body into each concept file. | | `graph` | `boolean` | `false` | Emit a `graph/` subdirectory with `index.html`, `graph.js`, `graph.css`, and `graph.json`. Opt-in since 0.8.8 — the OKF spec does not require a viewer, so a clean spec-compliant bundle ships without it. The viewer fetches `graph.json` at runtime from the same directory, so opening `site/okf/graph/index.html` over `file://` works as long as the four files stay together. | | `localeStrategy` | `'default-only' \| 'folders' \| 'mixed' \| 'latest-only'` | `'default-only'` | Default: only the default locale, at the bundle root. Set to `'folders'` to nest non-default locales under `<locale>/`. | | `versionStrategy` | `'folders' \| 'mixed' \| 'latest-only'` | `'latest-only'` | Nest concepts by version id when versioning is enabled. | | `excludePatterns` | `string[]` | `[]` | Additional glob patterns to skip on top of `frontmatter.noindex` / `frontmatter.okf === false`. | ### Example — custom output dir + custom default type ```json "docmd.config.json" { "plugins": { "okf": { "outputDir": "knowledge", "defaultType": "doc", "warnOnMissingType": true } } } ``` ### Example — multi-locale output (opt-in) ```json "docmd.config.json" { "plugins": { "okf": { "localeStrategy": "folders" } } } ``` ```text site/okf/ ← default locale (en) at bundle root ├── okf.yaml ├── index.md ├── concepts/<slug>.md └── _meta/, graph/, ... site/okf/ja/ ← Japanese — nested under <locale>/ ├── okf.yaml └── concepts/<slug>.md ``` The default-locale files **always** sit at the bundle root so existing consumers don't break. Only non-default locales get a `<locale>/` subdirectory. ## Per-page opt-out Pages can opt out of the OKF bundle in two ways: ```markdown --- noindex: true # also excludes from sitemap, llms.txt, etc. --- --- okf: false # only excludes from the OKF bundle --- ``` The first form (`noindex: true`) is the standard docmd opt-out that excludes a page from every downstream consumer (sitemap, search, llms.txt, OKF). The second form (`okf: false`) excludes only from OKF, so the page is still in the search index and the llms.txt summary but not in the OKF bundle. ## Type resolution precedence For every page the plugin picks a type with this precedence: 1. `frontmatter.okf.type` (nested) — explicit 2. `frontmatter.<typeField>` (top-level) — usually `type:` 3. `frontmatter.okfType` (legacy) — old alias 4. Path-prefix inference (e.g. `/guides/foo` → `guide`) 5. `defaultType` (with a warning if `warnOnMissingType`) The path-prefix map covers `guides/`, `api/`, `reference/`, `concepts/`, `runbooks/`, `datasets/`, `metrics/`, and `tables/`. Any other path falls back to the `defaultType` (default: `concept`). ## How agents consume the bundle The OKF spec defines three "implementation surfaces" — the same bundle file can be consumed by any of them without translation: - **AI agent loader** — point your agent at `site/okf/index.md` or any concept file under `site/okf/concepts/`. The YAML frontmatter gives the agent a typed index, the markdown body gives it the full content. - **Visualizer** — open `site/okf/graph/index.html` in a browser (or visit `/okf/graph/` on a hosted site). The force-directed graph shows the relationships between concepts based on internal markdown links. Requires `plugins.okf.graph: true` (off by default). - **Programmatic** — read `site/okf/_meta/bundle.json` (or `site/okf/okf.yaml`) for a machine-readable manifest of every concept, with type, path, locale, version, and tags. The bundle is also compatible with Google's published reference implementations — see the [OKF spec page][okf-spec] for details. [okf-spec]: https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing ## When NOT to use OKF - **Public marketing sites** with no AI-agent audience — the `llms.txt` plugin alone is sufficient. Use `okf: false` to disable OKF and avoid generating the bundle. - **Single-page projects** — OKF shines for multi-page docs with cross-links. A one-page site has no graph to render. - **i18n with many locales** — the default-locale-only default is intentional (one bundle for the primary language). If you need per-locale bundles, opt in via `localeStrategy: 'folders'`, but the bundle size scales with locale count. ## See also - [Open Knowledge Format — Google Cloud blog post](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing) — the spec announcement with full design rationale - [LLM Context Plugin](./llms.md) — the complementary `llms.txt` plugin for AI-agent context - [Building AI-ready docs](../../guides/ai-optimisation/generating-ai-ready-docs.md) — broader guide on AI-agent consumption - [Structure for LLMs](../../guides/ai-optimisation/structure-for-llms.md) — how to organise content for machine consumption - [release notes 0.8.8](../../release-notes/0-8-8.md) — context on the OKF plugin's introduction --- ## [OpenAPI Plugin](https://docs.docmd.io/plugins/openapi/) --- title: "OpenAPI Plugin" description: "Static API reference documentation rendered directly from OpenAPI 3.x specifications at build-time." --- The `@docmd/plugin-openapi` plugin converts OpenAPI 3.x specification files into structured, searchable API reference pages. It follows the Docmd "Zero-JS" philosophy - rendering every endpoint, parameter, and response into semantic HTML tables during the build process, ensuring maximum performance and SEO. ## Configuration The OpenAPI plugin is included by default in `@docmd/core`. You can configure global rendering options in your `docmd.config.json`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `info` | `boolean` | `true` | Display the API title, version, and description from the spec's `info` object. | | `download` | `boolean` | `false` | If true, adds a link to the header of the spec to download the raw JSON/YAML file. | | `summaryOnly` | `boolean` | `false` | If true, only renders the method, path, and summary. Useful for large API indexes. | | `allowRawHtml` | `boolean` | `false` | If true, prevents escaping of HTML tags in descriptions. | ### Example ```json "docmd.config.json" { "plugins": { "openapi": { "info": true, "download": true, "summaryOnly": false } } } ``` ## Usage Embed an OpenAPI specification anywhere in your Markdown using a fenced code block with the `openapi` tag. The path is resolved relative to your project source. ````markdown ```openapi assets/openapi.json ``` ```` ### Rendering Result ```openapi assets/docmd-api.json ``` ## What Gets Rendered For each path and HTTP method in the spec, the plugin renders: - **Method badge** - colour-coded (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) - **Path** - the full endpoint path with parameters highlighted - **Summary and description** - from the operation object - **Parameters table** - name, location (`path`, `query`, `header`, `cookie`), type, required flag, description - **Request body table** - schema properties with types and defaults - **Responses table** - status codes with descriptions and response schema types - **Deprecated notice** - operations marked `deprecated: true` are flagged inline ::: callout tip "Build-Time Rendering" All rendering happens at build time. The generated pages are static, with no client-side JavaScript required to display them. This gives you fast page loads, full search indexation, and SEO-friendly HTML. ::: ## Capability Support | Feature | Support | | :--- | :--- | | OpenAPI 3.x | ✓ (JSON & YAML*) | | Swagger 2.x | ✗ (Convert to 3.x first) | | `$ref` Resolution | ✓ (Internal schemas) | | `oneOf` / `anyOf` | ✓ (Shown as union types) | | `deprecated` flag | ✓ | *\*YAML support requires the `js-yaml` package to be installed in your project.* --- ## [PWA & Offline Support](https://docs.docmd.io/plugins/pwa/) --- title: "PWA & Offline Support" description: "Transform your documentation into a progressive web application with offline caching and mobile-first features." --- The `@docmd/plugin-pwa` plugin turns your documentation into a Progressive Web App. It writes a web manifest for mobile installation and registers a service worker that caches pages for offline reading. ## Configuration Customise your app branding within the `plugins` section of your `docmd.config.json`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable PWA manifest and service worker generation. | | `themeColor` | `string` | `'#1e293b'` | The primary colour of the mobile UI browser chrome. | | `bgColor` | `string` | `'#ffffff'` | Background colour for the splash screen during installation. | | `logo` | `string` | `null` | Path to the app icon (relative to project source). | ### Example ```json "docmd.config.json" { "plugins": { "pwa": { "themeColor": "#1e293b", "bgColor": "#ffffff", "logo": "assets/app-icon.png" } } } ``` ## Features - **Offline caching**: stale-while-revalidate strategy. Pages load from cache, then refresh in the background. - **Installable**: emits a `manifest.webmanifest` so users can install the site to their home screen on iOS and Android. - **Auto icons**: derives PWA icons from your project logo or favicon if no explicit icon is provided. - **SPA friendly**: works with the SPA router and the standard directory routing. ## Icon Resolution Priority The plugin resolves your PWA icons based on the following priority: 1. `pwa.icons` - Explicit array in config. 2. `pwa.logo` - Path relative to source. 3. `config.logo` - Global site logo. 4. `config.favicon` - Global favicon. ::: callout tip "Testing PWA Features" Service workers are bypassed in `npx @docmd/core dev` to prevent caching issues during editing. To test PWA features, run `npx @docmd/core build` and serve the `site/` directory using a static host. ::: --- ## [Search Plugin](https://docs.docmd.io/plugins/search/) --- title: "Search Plugin" description: "Enable high-speed, offline-first full-text search for your documentation using MiniSearch." --- The `@docmd/plugin-search` plugin provides a powerful, client-side search experience for your documentation. It uses [MiniSearch](external:https://github.com/lucaong/minisearch) to build a lightweight index during the build process, allowing users to find technical information instantly without a server-side database. ## Configuration Search is enabled by default in most `docmd` templates. You can control its visibility and placement via the `layout` configuration. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable the full-text search indexer. | | `placeholder` | `string` | `'Search...'` | Custom placeholder text for the search input. | | `maxResults` | `number` | `10` | Maximum number of results to display in the modal. | ### Example ```json "docmd.config.json" { "layout": { "optionsMenu": { "position": "header", "components": { "search": true } } } } ``` ## How It Works <img width="720" class="with-border" src="/assets/previews/search-ui-default.webp"> ### 1. Indexing (Build-time) During the `npx @docmd/core build` process, the search plugin iterates through every page on your site. It extracts the title, headings, and plain-text prose, then compiles this data into a compressed `search-index.json` file. * **Deep Linking**: The indexer automatically registers every heading (`#`, `##`, etc.) as a searchable target. * **Relevancy Boosting**: Titles are given the highest weight, followed by headings, then page content. ### 2. Retrieval (Client-side) When a user opens the search modal (usually via `/` or `Ctrl+K`), the `search-index.json` is fetched by the browser. Searches are performed locally using fuzzy matching (allowing for small typos) and instant prefix matching. ## Customising Search Behaviour Whilst the search plugin is designed for zero-config simplicity, you can exclude specific pages from the index by using the `noindex` flag in their frontmatter: ```yaml --- title: "Internal Specification" noindex: true # This page will not appear in search results or sitemaps --- ``` ## Technical Implementation The plugin injects a lightweight search modal into the `<body>` of your site. It is fully accessible (ARIA compliant) and supports keyboard navigation for a native app-like experience. ::: callout tip "Search Analytics" If you have the [Analytics Plugin](./analytics.md) enabled, search keywords used by your readers are automatically captured and sent to your analytics provider, giving you insights into what information is missing or hardest to find. ::: Because the search runs entirely on the client, no data, not even keystrokes, leaves the browser. This makes it suitable for privacy-sensitive industries (healthcare, finance, security). ## Comparison Many documentation generators (like Docusaurus) rely on **Algolia DocSearch**. Whilst Algolia is powerful, it introduces friction: | Feature | docmd Search | Algolia / External | | :--- | :--- | :--- | | Setup | Zero config (automatic) | API keys, CI crawling | | Privacy | Client-side, no data sent | Data sent to third-party servers | | Offline | Yes | No | | Cost | Free | Free tier limits or paid | | Speed | In-memory, instant | Network latency dependent | ## Semantic Search (Alpha Preview) ::: callout tip "Introducing docmd-search" `docmd-search` is a fully offline semantic search engine for documentation. It runs entirely in the browser, requires no server, no API keys, and sends nothing to anyone. It is not tied to docmd: you can plug it into any documentation engine or static site. This is an early alpha. APIs and behaviour will change. The foundation (private, offline, genuinely intelligent search) is already there. [→ View on GitHub](https://github.com/docmd-io/docmd-search) ::: > **Experimental Feature** - Semantic search is currently in alpha preview. The default keyword-based search remains the recommended option for production use. <img width="720" class="with-border" src="/assets/previews/search-ui-semantic.webp"> Semantic search uses local embeddings to understand the meaning behind queries, enabling more intelligent results beyond simple keyword matching. ### Enabling Semantic Search First, install the `docmd-search` package: ```bash npm install docmd-search ``` Then enable it in your configuration: ```json "docmd.config.json" { "plugins": { "search": { "semantic": true } } } ``` ### How Semantic Search Works Unlike keyword search which matches exact terms, semantic search: * **Understands context** - A query for "authentication" finds relevant pages even if they use different terminology like "login" or "sign-in" * **Handles typos naturally** - No need for fuzzy matching; the model understands intent * **Finds related concepts** - Searching "API" returns relevant endpoint documentation, not just pages containing "API" ### Configuration Options | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `semantic` | `boolean` | `false` | Enable semantic search (requires `docmd-search` package) | | `showConfidence` | `boolean` | `false` | Display similarity confidence score badges in semantic search results | | `showFilters` | `boolean` | `true` | Show the version filter bar above search results (set `false` to hide it) | | `model` | `string` | `'Xenova/all-MiniLM-L6-v2'` | Embedding model to use | | `chunkSize` | `number` | `512` | Maximum chunk size in characters | | `chunkOverlap` | `number` | `50` | Overlap between chunks in characters | | `indexDir` | `string` | - | Path to pre-built semantic index | ### Comparison: Semantic vs Keyword | Feature | Semantic Search | Keyword Search | | :--- | :--- | :--- | | **Understanding** | Context-aware | Exact match only | | **Typo tolerance** | High | Limited (fuzzy matching) | | **Synonyms** | Yes | No | | **Setup** | Requires `docmd-search` | Built-in | | **Index size** | Larger (1–2 MB per 100 files) | Smaller | | **Privacy** | 100% Private (client-side) | 100% Private (client-side) | | **Offline** | Yes | Yes | ### Automatic Installation When `semantic: true` is enabled, the plugin automatically installs `docmd-search` and its peer dependencies (`@huggingface/transformers`, `onnxruntime-node`) if they're not already available. This works with npm, pnpm, yarn, and bun — detecting your project's package manager automatically. If the automatic installation fails (e.g., in restricted CI environments), the plugin gracefully falls back to keyword search. ::: callout info "Resolver robustness (new in 0.8.9)" The resolver that locates `docmd-search` inside `node_modules` now uses an `import` → `default` → `require` → `main` fallback chain when reading the package manifest, plus a manual `node_modules` walk as a backstop for pnpm's isolated layout. No action required on your side — this is purely a build reliability improvement. ::: ### Available Models The `model` option lets you choose an embedding model. Models are downloaded once and cached locally. | Model | Size | Languages | Best For | | :---- | :--- | :-------- | :------- | | `Xenova/all-MiniLM-L6-v2` *(default)* | ~23 MB | English only | Fast, English-only documentation | | `Xenova/paraphrase-multilingual-MiniLM-L12-v2` | ~118 MB | 50+ languages | **i18n docs** (Chinese, German, French, etc.) | | `Xenova/multilingual-e5-small` | ~118 MB | 100+ languages | Wide language coverage | | `Xenova/paraphrase-multilingual-mpnet-base-v2` | ~270 MB | 50+ languages | Best multilingual quality | ::: callout info "Custom models" You can use any HuggingFace model compatible with Transformers.js. Browse at [huggingface.co/models](https://huggingface.co/models?pipeline_tag=feature-extraction&library=transformers.js) and filter by `transformers.js` library. ::: ### Fallback Behaviour If semantic search is enabled but `docmd-search` cannot be installed or found, the plugin automatically falls back to keyword search. This ensures your documentation remains searchable regardless of configuration. ::: callout warning "Alpha Limitations" Semantic search is experimental. Current limitations include: * English-only models (multilingual model available but less tested) * Higher memory usage (~50–100 MB in browser) * First load may be slower as embeddings are fetched ::: ### Best Practices For optimal semantic search performance: 1. **Exclude noise** - Don't index changelogs or draft content: ```json "docmd.config.json" { "plugins": { "search": { "semantic": true, "exclude": ["**/release-notes/**", "**/drafts/**"] } } } ``` 2. **Pre-build for CI/CD** - Use the `indexDir` option to pre-generate indexes: ```bash npx docmd-search --ui ``` 3. **Monitor index size** - Check the `.docmd-search/` directory size regularly 4. **Test thoroughly** - Verify search results quality before deploying to production --- ## [SEO Plugin](https://docs.docmd.io/plugins/seo/) --- title: "SEO Plugin" description: "Optimise your documentation for search engines and control AI crawler access with native meta tag generation." --- The `@docmd/plugin-seo` plugin generates high-quality metadata for every page. It ensures your documentation is not only discoverable by human readers on search engines but also correctly interpreted by AI models and social media platforms. ## Configuration Configure site-wide SEO defaults in your `docmd.config.json`. Page-level settings always take precedence over global defaults. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `defaultDescription` | `string` | `null` | Fallback description for pages without frontmatter descriptions. | | `aiBots` | `boolean` | `true` | Allow (`true`) or block (`false`) AI training bots. When `false`, blocks GPTBot, ChatGPT-User, Google-Extended, CCBot, and other AI crawlers. | | `openGraph` | `object` | `null` | Open Graph settings for social media (Facebook, LinkedIn). | | `twitter` | `object` | `null` | Twitter (X) Card settings including username and card type. | ### Example ```json "docmd.config.json" { "plugins": { "seo": { "defaultDescription": "Comprehensive documentation for the docmd ecosystem.", "aiBots": false, "twitter": { "siteUsername": "@docmd_io", "cardType": "summary_large_image" } } } } ``` ## Features - **Automatic `robots.txt`**: generated when missing, with sitemap reference and AI-bot directives. - **Smart fallbacks**: extracts the first 150 characters of prose if no description is set. - **AI bot governance**: by default AI bots can index content. Set `aiBots: false` to block AI training crawlers while still allowing traditional search engines. - **Canonical URLs**: emits `<link rel="canonical">` to prevent duplicate-content issues. - **Social previews**: native Open Graph and Twitter Cards. - **Structured data**: LD+JSON Article Schema for rich search snippets. ## robots.txt Auto-Generation The plugin automatically generates a `robots.txt` file during the build process if one doesn't exist in your output directory. **Generated content includes:** ```txt User-agent: * Allow: / # Sitemap Sitemap: https://your-domain.com/sitemap.xml ``` **Blocking AI Training Bots:** When `aiBots: false` is set, the generated `robots.txt` includes: ```txt # Block AI training bots User-agent: GPTBot Disallow: / User-agent: ChatGPT-User Disallow: / User-agent: Google-Extended Disallow: / # ... (additional AI crawlers) ``` ### robots.txt Location Strategy The plugin intelligently handles `robots.txt` across multiple locations: **Priority Order:** 1. **Site root** (`site/robots.txt`) - Checked first, highest priority 2. **Assets folder** (`site/assets/robots.txt`) - Copied to site root if found **Behaviour:** - If `robots.txt` exists in **site root**: Preserved, no action taken - If `robots.txt` exists in **assets folder**: Automatically copied to site root (recommended location for SEO) - If `robots.txt` not found: Auto-generated based on SEO configuration **Recommended Practice:** Place your custom `robots.txt` in the `assets/` folder of your documentation source. The plugin will copy it to the site root during build: ``` your-docs/ ├── assets/ │ └── robots.txt ← Place here ├── index.md └── docmd.config.json ``` After build, it appears at the correct location: ``` site/ ├── robots.txt ← Copied here (SEO standard location) ├── assets/ │ └── robots.txt ← Also preserved here └── index.html ``` ::: callout tip "Why Site Root?" Search engines expect `robots.txt` at the domain root (`https://example.com/robots.txt`). The plugin ensures your file is always in the correct location, whether you provide a custom one or let it auto-generate. ::: ## Page-Level Overrides Fine-tune settings for individual pages using frontmatter: ```markdown --- title: "Advanced Configuration" noindex: true # Hide from all search engines seo: keywords: ["docmd", "javascript", "ssg"] aiBots: true # Override global block for this page ldJson: true # Enable Article Schema --- ``` ::: callout tip "Search Discovery" For best results, ensure your `url` is defined in the root of your configuration. Without a base URL, the plugin cannot generate absolute canonical links or social image paths. ::: --- ## [Sitemap Plugin](https://docs.docmd.io/plugins/sitemap/) --- title: "Sitemap Plugin" description: "Automatically generate a standard-compliant sitemap.xml for better search engine discovery." --- The `@docmd/plugin-sitemap` plugin generates a `sitemap.xml` file at the root of your build directory. This provides search engines with a comprehensive map of your site's architecture, ensuring that all pages - including versioned documentation - are crawled and indexed. ## Configuration Enable sitemap generation by providing your `siteUrl` in the root configuration. You can customise the crawl weight within the `plugins` object. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `enabled` | `boolean` | `true` | Enable or disable sitemap generation. | | `defaultChangefreq` | `string` | `'weekly'` | Hint to crawlers on how often pages change. | | `defaultPriority` | `number` | `0.8` | Default weight for standard pages (0.0 to 1.0). | | `rootPriority` | `number` | `1.0` | Weight for the homepage (`index.md`). | ### Example ```json "docmd.config.json" { "url": "https://docs.example.com", "plugins": { "sitemap": { "defaultChangefreq": "weekly", "defaultPriority": 0.8 } } } ``` ## Features - **Canonical URLs**: resolves page paths to clean public URLs based on your `url` config. - **Versioned discovery**: includes pages from every configured version (`/v1/`, `/v2/`, etc.). - **Per-page exclusions**: skip pages with `sitemap: false` in frontmatter. - **Standard XML**: output follows the sitemaps.org protocol supported by every major search engine. ## Page-Level Controls Override sitemap behaviour for specific pages using frontmatter: ```markdown --- title: "Archive Page" priority: 0.3 # Lower weight for legacy content changefreq: "monthly" # Hint to crawlers sitemap: false # Exclude this specific page --- ``` ::: callout tip "Validation" After building your site, you can find the sitemap at `site/sitemap.xml`. You can submit this URL directly to search engine consoles to accelerate indexing. ::: --- ## [Threads Plugin](https://docs.docmd.io/plugins/threads/) --- title: "Threads Plugin" description: "Add inline discussion threads to your documentation - stored directly in your markdown files." --- The **Threads plugin** brings collaborative inline comments to your documentation. Select text, leave a comment, and start a discussion. All threads are stored directly in your markdown source files. No database is required. Original Author: [@svallory](external:https://github.com/svallory) ::: callout info "Alpha Release" This plugin is in alpha. The API and storage format are stable. The UI remains under active development. ::: ## Configuration The Threads plugin is an optional plugin. Install it via the CLI: ```bash npx @docmd/core add threads ``` Enable it in your `docmd.config.json`. | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `sidebar` | `boolean` | `false` | When `true`, threads stay grouped at the bottom of the page. When `false`, threads appear inline next to highlighted text. | ### Example ```json "docmd.config.json" { "plugins": { "threads": { "sidebar": true } } } ``` ## How It Works 1. **Select text** on any documentation page during `npx @docmd/core dev`. 2. A **comment popover** appears. Write your comment and submit. 3. The selected text gets **highlighted** with a thread marker. 4. Threads store as `::: threads` blocks at the bottom of the markdown file. 5. **No database** is needed. Your markdown files remain the single source of truth. ## Preview Here is what threads look like on a live page. Text with discussions gets <span class="threads-preview-highlight">highlighted like this</span>. Thread cards appear below. <div class="threads-preview-card"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 2d ago</div> <div class="threads-preview-body">This section could use a diagram to explain the architecture. What do you think?</div> </div> <div class="threads-preview-comment threads-preview-reply"> <div class="threads-preview-avatar">B</div> <div class="threads-preview-meta"><strong>Bob</strong> · 1d ago</div> <div class="threads-preview-body">Good idea - I'll add a Mermaid flowchart. Does <code>sequenceDiagram</code> work here?</div> <div class="threads-preview-reactions"> <div class="threads-preview-reaction">👍 <span>2</span></div> <div class="threads-preview-reaction">🚀 <span>1</span></div> </div> </div> <div class="threads-preview-comment threads-preview-reply"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 12h ago</div> <div class="threads-preview-body">Perfect. A simple flowchart would be ideal.</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> Here is a <span class="threads-preview-highlight-blue">second highlight with a different colour</span>. Threads cycle through a palette of colours automatically. <div class="threads-preview-card threads-preview-card-blue"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">C</div> <div class="threads-preview-meta"><strong>Charlie</strong> · 3d ago</div> <div class="threads-preview-body">Should we mention backward compatibility here?</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> Resolved threads appear dimmed: <div class="threads-preview-card threads-preview-card-resolved"> <div class="threads-preview-comment"> <div class="threads-preview-avatar">A</div> <div class="threads-preview-meta"><strong>Alice</strong> · 5d ago  <span class="threads-preview-resolved-badge">✓ Resolved</span></div> <div class="threads-preview-body">Fixed the typo in the config example.</div> </div> <div class="threads-preview-footer"> <div class="threads-preview-footer-btn">+ New Comment</div> </div> </div> A floating **discussion button** <span class="threads-preview-fab">💬<span class="threads-preview-fab-badge">2</span></span> appears in the bottom-right corner. It shows the count of open threads. Click it to jump to the first thread on the page. ## Storage Format Threads embed in your markdown using docmd's container syntax: ```markdown # My Documentation Page Some content with ==highlighted text=={t-a1b2c3d4} that has a thread. ::: threads ::: thread t-a1b2c3d4 ::: comment c-e5f6a7b8 "Alice" "2026-04-09" This text needs clarification. ::: ::: comment c-d9e0f1a2 "Bob" "2026-04-09" reply-to c-e5f6a7b8 Updated it - does this work? ::: reactions - 👍 Alice ::: ::: ::: ::: ``` The `==text=={threadId}` syntax links highlighted text in the document body to a specific thread. ## Features | Feature | Description | | :--- | :--- | | **Text Selection** | Select any text to start a new thread. | | **Replies** | Nested reply chains within each thread. | | **Reactions** | Emoji reactions on individual comments. | | **Edit / Delete** | Modify or remove your comments. | | **Resolve** | Mark threads as resolved with author and timestamp. | | **Author Profiles** | Git-based author detection with Gravatar support. | | **Highlight Markers** | Visual indicators showing where threads anchor. | | **Floating Button** | Quick-access FAB with open thread count. | | **Scroll Preservation** | Page stays in place after adding comments. | ## Actions API The threads plugin exposes the following actions via the WebSocket RPC system. Call these from browser plugins using `docmd.call()`: | Action | Description | | :--- | :--- | | `threads:get-threads` | Parse and return all threads from a file. | | `threads:add-thread` | Create a new thread with its first comment. | | `threads:add-comment` | Add a comment to an existing thread. | | `threads:edit-comment` | Edit an existing comment's body. | | `threads:delete-comment` | Remove a comment from a thread. | | `threads:delete-thread` | Remove an entire thread and cleanup highlights. | | `threads:resolve-thread` | Toggle resolved/unresolved status. | | `threads:toggle-reaction` | Toggle an emoji reaction on a comment. | | `threads:get-authors` | Read the author profile map. | | `threads:upsert-author` | Create or update an author profile. | ## Author Profiles Author information is stored in `<docsRoot>/.threads/authors.json`: ```json ".threads/authors.json" { "alice@example.com": { "name": "Alice", "avatarUrl": "https://gravatar.com/avatar/..." } } ``` During development, the plugin automatically detects your Git username and email for author identification. ::: callout tip "Version Control Friendly" Since threads are stored in your markdown files, they are automatically version-controlled with Git. Review comments in PRs, track discussion history, and collaborate through your existing workflow. ::: --- ## [Using Plugins](https://docs.docmd.io/plugins/usage/) --- title: "Using Plugins" description: "Install, configure, and manage docmd plugins - from required defaults to optional add-ons." --- docmd features a modular plugin architecture. Required plugins ship with the core and need no installation. Optional plugins can be installed with a single CLI command. ## Installing Plugins Use the docmd CLI to install and remove plugins: ```bash # Install a plugin npx @docmd/core add <plugin-name> # Remove a plugin npx @docmd/core remove <plugin-name> ``` The installer detects your package manager (npm, pnpm, yarn, or bun). It resolves short names to full package names and injects the config into your `docmd.config.json`. Use `--verbose` (or `-V`) for full installer output: ```bash npx @docmd/core add <plugin-name> -V ``` ## Required Plugins These plugins are bundled with `@docmd/core`. No installation is needed. Enable them in your `docmd.config.json`: ```json "docmd.config.json" "plugins": { "search": {}, "seo": { "aiBots": false }, "sitemap": {}, "analytics": {}, "llms": {}, "okf": {}, "mermaid": {}, "openapi": {}, "git": {} } ``` ::: callout tip "Git Plugin" The Git plugin detects if your project is a Git repository. If not, it disables itself automatically. No configuration is required for last-updated timestamps. ::: ::: callout info "OKF Bundle (new in 0.8.8)" `@docmd/plugin-okf` generates an [Open Knowledge Format][okf-spec] bundle (`site/okf/`) — a typed manifest plus per-page concept files that AI agents consume directly. The plugin is **enabled by default**; set `"plugins": { "okf": false }` to opt out. See the [OKF Bundle Plugin docs](./okf.md) for the full contract. [okf-spec]: https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing ::: ## Optional Plugins Optional plugins require installation before enabling. | Plugin | Install Command | Description | | :--- | :--- | :--- | | [PWA](pwa.md) | `npx @docmd/core add pwa` | Progressive Web App support with offline caching | | [Threads](threads.md) | `npx @docmd/core add threads` | Inline discussion comments stored in Markdown | | [Math](math.md) | `npx @docmd/core add math` | Native KaTeX and LaTeX mathematics rendering | ## Auto-Installation When you add an official plugin to your `docmd.config.json` without installing it, docmd automatically downloads and installs it on the next build. This works for all plugins in the official registry. ```json "docmd.config.json" { "plugins": { "pwa": {} } } ``` The auto-installer: - Targets official `@docmd/plugin-*` packages only. - Pins the version to match your `@docmd/core` installation. - Detects and uses your project's package manager. - Reports progress in the terminal as it runs. ::: callout tip "Resilient auto-install (new in 0.8.9)" The auto-installer uses dynamic `import()` for the final load step, so it works for ESM packages that declare only an `import` condition in their `exports` field. The set of *names* it can install is still restricted to the official plugin registry allowlist — a registry re-check runs inside the retry path as defense-in-depth, so a future change to the installer cannot silently turn it into a generic npm-loader. ::: ## Third-Party & Custom Plugins For security, the installer enforces an official registry allowlist. Third-party plugins must be installed natively using your package manager: ```bash npm install my-custom-plugin # or pnpm add, yarn add, bun add ``` After installation, add the plugin to your `docmd.config.json` using its exact package name: ```json "docmd.config.json" { "plugins": { "my-custom-plugin": { "someOption": true } } } ``` If the plugin meets docmd's requirements, it activates automatically during the build. Otherwise, the engine reports an error. ## Plugin Scopes and `noStyle` Overrides Plugins inject CSS and behaviour globally. However, you can configure them to bypass specific pages or entirely disable their execution on unstyled landing pages (`noStyle: true`). ### Global Config Extent Instruct any plugin to automatically skip `noStyle` pages via your `docmd.config.json`: ```json "docmd.config.json" { "plugins": { "math": { "noStyle": false } } } ``` ### Page Local Scope (Frontmatter) You can definitively enable or disable any plugin per-document via markdown frontmatter. ```markdown --- noStyle: true plugins: math: true threads: false --- # Only Math renders here, Threads are completely blocked ``` ## Plugin Lifecycle Plugins hook into different stages of the build and development process: | Hook | Description | | :--- | :--- | | `markdownSetup(md, opts)` | Extend the Markdown parser with custom rules. | | `generateMetaTags(config, page, root)` | Inject `<meta>` and `<link>` tags into the `<head>`. | | `generateScripts(config, opts)` | Inject scripts into `<head>` or `</body>`. | | `getAssets(opts)` | Define external files or CDN scripts to inject. | | `onPostBuild(ctx)` | Run logic after all HTML files finish generating. | | `translations(localeId)` | Return translated UI strings for a locale. | | `actions` | Server-side handlers callable via WebSocket RPC. | | `events` | Fire-and-forget handlers for browser-pushed events. | ## Plugin Safety The plugin system guarantees build safety: - **Validation**: Invalid plugin descriptors are rejected at load time. - **Isolation**: Every hook invocation is wrapped in a try/catch. A broken plugin cannot crash the build. - **Capability enforcement**: Plugins can only register for hooks they have declared. See [Building Plugins](building-plugins.md) for the full API reference. ::: callout tip "Traceable Architecture" icon:sparkles Every meta-tag and script the engine emits is generated from explicit config and plugin output. There are no hidden side effects. ::: --- ## [Browser API (Client-Side)](https://docs.docmd.io/reference/browser-api/) --- title: "Browser API (Client-Side)" description: "Interact with docmd from the browser - live compilation and dev-mode plugin communication." --- docmd provides two browser APIs: the **isomorphic compile engine** for rendering markdown in the browser, and the **dev-mode plugin API** for real-time communication with the dev server. ## Isomorphic Compile Engine The engine that generates static sites in Node.js can run entirely within a web browser. This is ideal for building CMS previews, interactive playgrounds, or embedding documentation. ### Installation via CDN ```html <!-- Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@docmd/ui/assets/css/docmd-main.css"> <!-- The Isomorphic Engine --> <script src="https://unpkg.com/@docmd/live/public/docmd-live.js"></script> ``` ### `docmd.compile(markdown, config)` Compiles raw Markdown into a full HTML document string using the default docmd layout. **Parameters:** - `markdown` (String): The raw Markdown content. - `config` (Object): Configuration overrides (same schema as `docmd.config.json`). **Returns:** `Promise<String>`: The complete HTML document. ### Example: Live Preview To ensure style isolation, render the output inside an `<iframe>` using the `srcdoc` attribute. ```javascript const editor = document.getElementById("editor"); const preview = document.getElementById("preview"); async function updatePreview() { const html = await docmd.compile(editor.value, { "title": "Preview", "theme": { "appearance": "light" } }); preview.srcdoc = html; } editor.addEventListener("input", updatePreview); ``` ## Dev-Mode Plugin API During `npx @docmd/core dev`, a `window.docmd` global is injected into every page automatically. This API enables real-time communication between browser-side plugin code and server-side action handlers via WebSocket RPC. ::: callout info "Dev Mode Only" icon:code The plugin API methods below are only available during `npx @docmd/core dev`. They are not included in production builds. ::: ### `docmd.call(action, payload)` Call a server-side action handler registered by a plugin. Returns a promise that resolves with the handler's return value. ```javascript const threads = await docmd.call("threads:get-threads", { "file": "docs/getting-started.md" }); console.log(threads); ``` If the action modifies source files, the page automatically reloads after the promise resolves. ### `docmd.send(name, data)` Send a fire-and-forget event to the server. No response is returned. ```javascript docmd.send("analytics:page-view", { "path": window.location.pathname }); ``` ### `docmd.on(name, callback)` Subscribe to server-pushed events. Returns an unsubscribe function. ```javascript const unsub = docmd.on("threads:updated", (data) => { console.log("Threads updated:", data); }); unsub(); ``` ### `docmd.afterReload(name, callback)` Declare a handler that runs after a page reload. If context was stashed with `scheduleReload`, the callback receives it. ```javascript // Restore scroll position after a live-reload docmd.afterReload('scroll-restore', (ctx) => { window.scrollTo(0, ctx.scrollY); }); ``` ### `docmd.scheduleReload(name, context)` Stash context into `sessionStorage` for a named `afterReload` handler. The matching handler fires with this context after the next page reload. ```javascript docmd.scheduleReload("scroll-restore", { "scrollY": window.scrollY }); ``` ## Considerations - **No File System**: The browser engine cannot scan folders. You must provide the `navigation` array explicitly in the config object if you need a sidebar. - **Node-Only Plugins**: Plugins that rely on Node.js APIs (like Sitemap or LLM text generation) are disabled in the browser environment. - **WebSocket Connection**: The dev-mode API requires an active WebSocket connection to the dev server. It auto-reconnects with exponential backoff if the connection drops. --- ## [Build API](https://docs.docmd.io/reference/build-api/) --- title: "Build API" description: "Programmatic build API — call docmd from Node.js to build sites, live editor bundles, and workspace projects." --- You can import and use the docmd build engine directly from your Node.js applications. This is ideal for custom CI/CD pipelines, automated documentation generation, and pre-rendering docs in monorepos. ## Installation Ensure `@docmd/core` is installed in your project: ```bash npm install @docmd/core ``` ## Core Functions ### `buildSite(configPath, options)` The primary build function. Handles configuration loading, Markdown parsing, and asset generation. ```javascript import { buildSite } from "@docmd/core"; async function runBuild() { await buildSite("./docmd.config.json", { "isDev": false, offline: false, zeroConfig: false }); } ``` ### `buildLive(options)` Generates the browser-based **Live Editor** bundle. ```javascript import { buildLive } from "@docmd/core"; async function generateEditor() { await buildLive({ "serve": false, port: 3000 }); } ``` ## Workspace Management For managing workspaces programmatically, use the dedicated workspace functions. ### `isWorkspace(config)` Returns `true` if the provided configuration object follows the Workspace schema. ### `detectWorkspace(configPath)` Detects and loads a workspace configuration file. Returns a normalised `WorkspaceRootConfig` or `null`. ### `buildWorkspace(config, options)` Builds all projects within a workspace. Handles shared assets and project-specific prefixing. ### `devWorkspace(config, options)` Starts the workspace dev server. Watches all projects for changes and performs targeted rebuilds. ```javascript import { detectWorkspace, buildWorkspace } from "@docmd/core"; async function buildAll() { const config = await detectWorkspace("./docmd.config.json"); if (config) { await buildWorkspace(config, { quiet: false }); } } ``` ## Example: Custom Pipeline Wrap docmd to compose complex documentation workflows — generate dynamic content, build, then move the output to your final location. ```javascript import { buildSite } from '@docmd/core'; import fs from 'fs-extra'; async function deploy() { // 1. Generate dynamic content await fs.writeFile('./docs/dynamic.md', '# Generated Content'); // 2. Execute build await buildSite('./docmd.config.json'); // 3. Move output await fs.move('./site', './public/docs'); } ``` ::: callout tip The programmatic API is highly compatible with **AI-driven documentation**. Agents can trigger builds after content updates to verify integrity and manage deployments autonomously. ::: ## What's Next - [Plugins](/plugins/usage) — extend docmd without touching the engine. - [CLI Commands](/reference/cli-commands) — the recommended path for most CI/CD. - [Workspaces](/configuration/workspaces) — multi-project configuration reference. --- ## [CLI Commands](https://docs.docmd.io/reference/cli-commands/) --- title: "CLI Commands" description: "Command-line reference for docmd - all available commands and options." --- ## Commands Overview | Command | Description | |:--------|:------------| | [`npx @docmd/core init`](#npx-docmdcore-init) | Scaffold a new documentation project | | [`npx @docmd/core dev`](#npx-docmdcore-dev) | Start the development server with hot reload | | [`npx @docmd/core build`](#npx-docmdcore-build) | Generate a production static site | | [`npx @docmd/core live`](#npx-docmdcore-live) | Launch the browser-based Live Editor | | [`npx @docmd/core stop`](#npx-docmdcore-stop) | Kill running dev servers | | [`npx @docmd/core deploy`](#npx-docmdcore-deploy) | Generate deployment configs | | [`npx @docmd/core migrate`](#npx-docmdcore-migrate) | Upgrade legacy configs or migrate from other tools | | [`npx @docmd/core validate`](#npx-docmdcore-validate) | Validate links and check documentation files | | [`npx @docmd/core doctor`](#npx-docmdcore-doctor) | Pre-flight check: report missing plugins, broken configs, mismatched engines | | [`npx @docmd/core mcp`](#npx-docmdcore-mcp) | Run as an MCP (Model Context Protocol) server over stdio | | [`npx @docmd/core add <plugin>`](#npx-docmdcore-add-plugin) | Install and configure a plugin | | [`npx @docmd/core remove <plugin>`](#npx-docmdcore-remove-plugin) | Remove a plugin and its config | ## Global Options | Option | Alias | Description | |:-------|:------|:------------| | `--config <path>` | `-c` | Path to config file (default: `docmd.config.json`) | | `--verbose` | `-V` | Show detailed build logs | | `--version` | `-v` | Output the installed version | | `--help` | `-h` | Display help menu | | `--cwd <path>` | - | Override working directory (for monorepos) | ## `npx @docmd/core init` Scaffold a new documentation project in the current directory. ```bash npx @docmd/core init ``` Creates: - `docs/index.md` - boilerplate home page - `docmd.config.json` - recommended defaults - Updated `package.json` with build scripts ## `npx @docmd/core dev` Start a development server with instant hot reload. ```bash npx @docmd/core dev [options] ``` | Option | Alias | Description | |:-------|:------|:------------| | `--port <number>` | `-p` | Server port (default: `3000`) | | `--config <path>` | `-c` | Path to config file | ## `npx @docmd/core build` Generate a production-ready static site in `site/`. ```bash npx @docmd/core build [options] ``` | Option | Alias | Description | |:-------|:------|:------------| | `--offline` | - | Rewrite links to `.html` for `file://` browsing | | `--config <path>` | `-c` | Path to config file | ## `npx @docmd/core live` Launch the browser-based Live Editor. ```bash npx @docmd/core live [options] ``` | Option | Description | |:-------|:------------| | `--build-only` | Generate the editor bundle without starting the server | ## `npx @docmd/core stop` Kill running dev servers. ```bash npx @docmd/core stop [options] ``` | Option | Alias | Description | |:-------|:------|:------------| | `--port <number>` | `-p` | Stop only the server on this port | | `--force` | `-f` | Also kill `serve` processes on ports 3000, 3001, 8080, 8081 | ## `npx @docmd/core deploy` Generate deployment configuration files. ```bash npx @docmd/core deploy [options] ``` | Option | Description | |:-------|:------------| | `--docker` | Generate a `Dockerfile` + `.dockerignore` | | `--nginx` | Generate `nginx.conf` | | `--caddy` | Generate `Caddyfile` | | `--github-pages` | Generate `.github/workflows/deploy.yml` | | `--vercel` | Generate `vercel.json` | | `--netlify` | Generate `netlify.toml` | | `--force` | Overwrite existing deployment files | ## `npx @docmd/core migrate` Migrate from another tool or upgrade configs. ```bash npx @docmd/core migrate ``` Automatically re-maps deprecated keys (e.g., `siteTitle` → `title`) and restructures the config object. **0.8.10 polish** — the command now also handles: - `--upgrade` — translate a legacy `docmd.config` (pre-0.7.x keys) to the modern schema in place. - `--dry-run` — preview the migration plan (files to move, new `docmd.config.json` body) without writing anything. The default-locale's `nav:` is also auto-translated for MkDocs sources. ## `npx @docmd/core validate` Validate documentation files and check for broken internal links. ```bash npx @docmd/core validate [options] ``` | Option | Description | |:-------|:------------| | `--json` | Output errors as machine-readable JSON (useful for CI pipelines). | Scans every Markdown file, follows relative links and image references, and reports any broken targets. Exits with a non-zero status if any link is invalid, so you can wire it into pre-merge hooks. ## `npx @docmd/core doctor` Pre-flight check that reports missing plugins, broken configs, and mismatched engines. No filesystem writes, no build side-effects — purely diagnostic. ```bash npx @docmd/core doctor [options] ``` | Option | Description | |:-------|:------------| | `--config <path>` | Path to a non-default `docmd.config.json` (or `.ts`/`.js`/`.mjs`). | | `--fix` | Auto-install any missing official plugin or template that `doctor` flags. | | `--json` | Output the full report as machine-readable JSON (for CI and tooling). | 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, 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 (`pnpm add`, `npm install --save`, `yarn add`, or `bun add`) to install the candidates, then exits with code 0 if everything resolved. With `--json`, the same data is emitted as a single JSON object — useful for pre-commit hooks and CI gates. Exit code 0 means the project is healthy; non-zero means at least one issue remains after any `--fix` run. ## `npx @docmd/core mcp` Run docmd as a Model Context Protocol (MCP) server over stdio. Use this to give AI agents (Claude Desktop, Cursor, etc.) the ability to read and validate your documentation directly. ```bash npx @docmd/core mcp ``` The server communicates over standard input/output using the JSON-RPC protocol. Configure your MCP client with: ```json "claude_desktop_config.json" { "mcpServers": { "docmd": { "command": "npx", "args": ["-y", "@docmd/core", "mcp"] } } } ``` ## `npx @docmd/core add <plugin>` Install and configure an official or community plugin. ```bash npx @docmd/core add <plugin-name> ``` | Example | Description | |:--------|:------------| | `npx @docmd/core add analytics` | Install `@docmd/plugin-analytics` | | `npx @docmd/core add search` | Install `@docmd/plugin-search` | The CLI detects your package manager (npm, pnpm, yarn, or bun) and injects recommended defaults into `docmd.config.json`. ## `npx @docmd/core remove <plugin>` Safely uninstall a plugin and clean up its config. ```bash npx @docmd/core remove <plugin-name> ``` Removes: - The npm package - Plugin configuration from `docmd.config.json` ::: callout tip "Agent-Compatible Logging" icon:sparkles docmd uses structured terminal logging. AI agents can parse output precisely for error detection and automated maintenance. ::: --- ## [Client-Side Events](https://docs.docmd.io/reference/client-side-events/) --- title: "Client-Side Events" description: "Hook into the docmd SPA lifecycle to add interactive features." --- docmd uses a lightweight Single Page Application (SPA) router to provide instant page transitions. Because the browser does not perform a full reload during navigation, scripts relying on `DOMContentLoaded` will not re-execute. To handle this, docmd dispatches custom lifecycle events that you can listen for in your `customJs` files. ## `docmd:page-mounted` This event is dispatched whenever a new page has been successfully fetched and injected into the DOM. ### Usage Add a listener to the `document` object to re-initialise third-party libraries or trigger custom animations. ```javascript document.addEventListener("docmd:page-mounted", (event) => { const { url } = event.detail; console.log(`Navigated to: ${url}`); }); ``` ### Event Details (`event.detail`) | Property | Type | Description | | :--- | :--- | :--- | | `url` | `String` | The absolute URL of the page that was just mounted. | ## Best Practices 1. **Idempotency**: Ensure your initialisation logic can be safely called multiple times on the same page or cleaned up before the next navigation. 2. **Global Scope**: Scripts added via `customJs` execute in the global scope. Use an IIFE (Immediately Invoked Function Expression) to avoid polluting the `window` object. 3. **Cleanup**: If your script adds global event listeners (e.g., `window.onresize`), consider tracking the current path to remove them when the user navigates away. --- ## [Live Editor](https://docs.docmd.io/reference/live-api/) --- title: "Live Editor" description: "Understanding the docmd Live Editor and its browser-based authoring workflow." --- The docmd Live Editor is a dedicated environment for real-time documentation authoring. It uses the isomorphic core to provide an instant, side-by-side preview of your Markdown content without requiring a backend build process. ## Launching the Editor Start the local Live Editor by running: ```bash npx @docmd/core live ``` The editor will typically be available at `http://localhost:3000`. ## Architecture Unlike the standard `dev` server which rebuilds files on the disk, the Live Editor runs the engine directly in your browser. This enables: 1. **Instant Feedback**: Content is re-rendered as you type. 2. **Portable Playgrounds**: The editor can be bundled into a static site for hosting on platforms like GitHub Pages. 3. **Cross-Platform Consistency**: The preview uses the exact same rendering logic as the production build. ## Static Deployment Generate a shareable, standalone version of the editor: ```bash npx @docmd/core live --build-only ``` This creates a `dist/` directory containing the editor's HTML and the bundled isomorphic engine. --- ## [MCP Server](https://docs.docmd.io/reference/mcp-server/) --- title: "MCP Server" description: "Connect AI development agents to your documentation workspace using the Model Context Protocol." --- docmd includes a native Model Context Protocol (MCP) server, enabling AI development agents to interact with your documentation workspace programmatically over a secure, local connection. ## What is MCP? The [Model Context Protocol](external:https://modelcontextprotocol.io/) is an open standard for connecting AI models to external tools and data sources. It uses JSON-RPC 2.0 messages over a transport layer (stdio, HTTP). docmd implements the `stdio` transport — the agent spawns `docmd mcp` as a child process and communicates via stdin/stdout. ## Quick Start ```bash docmd mcp ``` This starts the MCP server over `stdio`. No network ports are opened — all communication happens through standard input/output streams. ### Claude Desktop Configuration Add to your Claude Desktop `claude_desktop_config.json`: ```json { "mcpServers": { "docmd": { "command": "npx", "args": ["@docmd/core", "mcp"], "cwd": "/path/to/your/docs/project" } } } ``` ### Cursor / Windsurf Configuration Add to your editor's MCP settings: ```json "mcp_settings.json" { "command": "npx @docmd/core mcp", "transport": "stdio" } ``` ## Available Tools The MCP server exposes six tools that agents can call: | Tool | Description | | :--- | :--- | | **`search_docs`** | Full-text search across all documentation files. Returns matching lines with file paths and line numbers. | | **`list_docs`** | List every markdown file in the project (optionally scoped to a subdirectory such as a locale or version). Returns relative paths so the agent can navigate the docs tree before reading individual files. | | **`read_doc`** | Read the raw markdown content of any documentation file by its relative path. Path is sandboxed to the project root. | | **`get_config`** | Retrieve the resolved `docmd.config` — title, source/output directories, configured locales, versions, and enabled plugins. Sensitive values (API keys, analytics IDs) are stripped from the response. | | **`validate_docs`** | Run link validation across all markdown files. Returns a list of broken links with file, line, and target. | | **`get_llms_context`** | Retrieve the complete `llms-full.txt` context — the unified content of the entire documentation site, optimised for LLM ingestion. | ### Tool Schemas #### `search_docs` ```json { "name": "search_docs", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "The term or phrase to search for." } }, "required": ["query"] } } ``` #### `list_docs` ```json { "name": "list_docs", "inputSchema": { "type": "object", "properties": { "subdir": { "type": "string", "description": "Optional subdirectory to scope the listing (e.g. 'en', 'v1', 'guides'). Path is sandboxed to the configured source directory." } } } } ``` #### `read_doc` ```json { "name": "read_doc", "inputSchema": { "type": "object", "properties": { "route": { "type": "string", "description": "Relative path to the markdown file (e.g. docs/getting-started.md). Must resolve inside the project root." } }, "required": ["route"] } } ``` #### `get_config` ```json { "name": "get_config", "inputSchema": { "type": "object", "properties": {} } } ``` #### `validate_docs` / `get_llms_context` No input parameters required. ## Protocol Details docmd implements the MCP specification (protocol version `2025-03-26`): - **Transport**: `stdio` — JSON-RPC 2.0 messages over stdin/stdout, one per line - **Diagnostics**: Logged to `stderr` (does not interfere with the JSON-RPC stream) - **Lifecycle**: `initialize` → `notifications/initialized` → tool calls - **Ping**: Responds to `ping` requests with `{}` (required for connection health checks) - **Capabilities**: Declares `tools`, `resources`, and `prompts` (tools are the primary interface) ## Privacy & Security - **Local only**: The server runs as a child process — no network exposure, no ports opened - **Sandboxed**: File operations are restricted to the project working directory - **No telemetry**: No data is sent anywhere — all processing happens on your machine ## Complementary Features The MCP server works alongside other AI-first features in docmd: - **`llms.txt` / `llms-full.txt`**: Generated at build time by the `llms` plugin. Any agent can fetch these from your deployed site without MCP. - **Copy Context widget**: Browser UI button that copies page content optimised for pasting into AI chat windows. - **SKILL.md**: Agent instruction manual auto-generated by `docmd init`. Points to the [docmd-skills](external:https://github.com/docmd-io/docmd-skills) knowledge base. ::: callout tip "When to use MCP vs llms.txt" Use **MCP** when an agent needs to search, read specific files, or validate links interactively during development. Use **llms-full.txt** when an agent needs the entire documentation context in a single fetch (e.g., for RAG or pre-prompting). ::: --- ## [docmd v0.8.0 - The Parallel Engine Era](https://docs.docmd.io/release-notes/0-8-0/) --- title: "docmd v0.8.0 - The Parallel Engine Era" description: "High-performance multi-threaded architecture, workspace support, and massive performance boosts." --- The `docmd` 0.8.0 release is a monumental architectural upgrade. We have moved from a single-threaded sequential engine to a native multi-threaded worker pool that processes pages in parallel. This release also introduces first-class **workspace support**, allowing you to manage complex documentation ecosystems under a single domain with near-instant build times. ## ✨ Highlights ### ⚡ Parallel Build Engine docmd now builds your documentation in parallel using a highly optimised `WorkerPool`. By offloading Markdown AST parsing and processor hooks into background threads, docmd fully utilises all available CPU cores. For large sites (1000+ pages), this results in **up to 10x faster builds**. ### 🏢 workspace Support You can now build multiple independent documentation projects into a single site. This is perfect for monorepos or large organisations that need to unify multiple documentation sources under one domain (e.g., `docmd.io` and `docmd.io/search`). - **Unified Output**: Each project has its own config but shares a single output directory. - **Independent Context**: Each sub-project maintains its own versioning, i18n, and plugin configurations. ### 🔌 Plugin Worker API We have exposed the internal `WorkerPool` to the entire plugin ecosystem. Plugins can now offload computationally heavy tasks (like image processing, remote indexing, or data parsing) to background threads using the new `ctx.runWorkerTask()` API. ### 📜 Persistent Git Indexing The Git plugin has been redesigned for speed. It now features a **Persistent Disk Cache** and parallel I/O processing. - **Massive Speedup**: Indexing 800+ pages now takes ~3.5s instead of ~18s on subsequent builds. - **Smart Pruning**: The cache automatically manages entries for deleted or renamed files. ### 🏠 SEO-Friendly README Routes docmd now automatically treats `README.md` as a directory index, ensuring that links like `[Guide](./guide/README.md)` resolve correctly to `/guide/`. - **Intelligent Fallback**: `index.md` is always prioritised, with `README.md` serving as a fallback if no index is present. - **Clean URLs**: Automatically strips `README` and `index` from URLs for a professional look. ### ⚙️ Modern Configuration You can now write your configuration in TypeScript or JSON. - **TypeScript Support**: Use `docmd.config.ts` with full autocompletion and type safety via `defineConfig`. - **JSON Support**: Lightweight `docmd.config.json` for environments where JavaScript execution is restricted. ### 🧜 Better Mermaid Diagrams The Mermaid plugin now features an improved UI for large diagrams. - **Refined Controls**: Zoom and pan controls have been moved to the bottom-left to prevent overlapping with content. - **Fullscreen Experience**: Fullscreen mode now includes full access to all navigation and zoom controls. ## 📝 Complete Changelog ### 🚀 Engine & Architecture - **Worker-Parser Pipeline**: The core markdown processor is now re-hydrated dynamically inside background threads. Files are read concurrently and farmed out to the workers in batches. - **AST Caching Engine**: An MD5-based caching layer intercepts unmodified files. If a file's raw content hash hasn't changed since the previous pass, the AST parsing is skipped entirely. - **Persistent Dev Workers**: During `npx @docmd/core dev`, the worker pool remains persistent across file saves. This eliminates the 200-500ms thread-startup latency commonly associated with Node.js workers, resulting in near-instant incremental rebuilds. - **Worker CPU Throttling**: The thread pool calculates the exact number of threads based on system architecture, reserving one CPU core to prevent I/O starvation and OS lockups. - **WorkerPool MaxListeners Guard**: The EventEmitter listener cap is dynamically scaled (`poolSize * 4 + 50`) to prevent spurious Node.js warnings on high-throughput builds with 900+ pages. ### 🔌 Plugin System - **`onBeforeBuild` Lifecycle Hook**: A new dedicated "Data Indexing" phase allows plugins to fetch heavy data (like Git logs or remote APIs) and display a progress bar *before* HTML generation begins. This guarantees the core render loop remains purely synchronous and lightning-fast. - **`runWorkerTask` API**: Exposed directly on the plugin contexts (`onBeforeBuild`, `onBeforeRender`, `onPostBuild`, `actions`, `events`) for generic script execution in the background. - **Git Plugin Persistent Cache**: The Git plugin now runs in the new `onBeforeBuild` hook and utilises a reliable persistent disk cache (`.docmd/cache/git-history.json`). This completely eliminates redundant `git log` shell subprocesses on subsequent builds, dropping the build time of large repositories (800+ pages) from ~18 seconds down to just ~3.5 seconds. - **Git Plugin Parallel I/O**: Git metadata syncing now processes pages in parallel batches (concurrency of 10). Since `git log` is async I/O, this yields ~5-10x faster cold-start indexing on large sites compared to sequential processing. - **Git Cache Auto-Pruning**: The disk cache automatically removes stale entries for deleted or renamed files during each save, preventing unbounded cache growth over time. - **Search Index Worker Offload**: When a WorkerPool is available, the CPU-intensive MiniSearch tokenization and indexing is offloaded to a worker thread via `runWorkerTask`, keeping the main thread free for other post-build tasks. - **Decoupled API Imports**: Plugins can now import `fsUtils`, `WorkerPool`, and `getGitRoot` directly from `@docmd/utils`. ### 🖥️ Terminal Interface - **TUI Progress Bars**: Exposing the `@docmd/tui` engine directly to plugin contexts. The Git and Search plugins now render highly stable, in-place progress bars during their indexing phases to clearly separate data-fetching latency from raw build speed. ### ⚙️ Infrastructure & Tooling - **Centralised Git Context**: Internal Git branch detection and repository root parsing (`getGitRoot`) have been extracted into the safe utilities boundary. - **Modern Config Candidates**: Added `docmd.config.ts` and `docmd.config.json` to the default configuration search path. - **JSON-serialisable Configs**: Continued transition towards zero-config architecture by ensuring the resolved config object is fully JSON-serialisable. ## ⚠️ Breaking Changes - **Utility Imports**: Custom plugins relying on core relative imports must migrate to `@docmd/utils`. - **Serialisable Hooks**: `markdownSetup` hooks must be serialisable for cross-thread instantiation. ## Migration Guide Upgrade by running `npm install @docmd/core@latest`. Most sites will see immediate performance gains without any configuration changes. See [Installation](../getting-started/installation) for a full walkthrough. --- ## [docmd v0.8.1 - Engine Architecture & Git Cache Fixes](https://docs.docmd.io/release-notes/0-8-1/) --- title: "docmd v0.8.1 - Engine Architecture & Git Cache Fixes" description: "Pluggable engine architecture (preview), persistent git indexing, navigation fixes, and JSON config standardisation." --- ::: callout danger **This release is deprecated.** Version 0.8.1 contains a packaging defect that causes `npm install` to fail with an `EUNSUPPORTEDPROTOCOL` error. All changes and fixes have been carried forward to [v0.8.2](./0-8-2.md). Please upgrade immediately. ::: 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 easily with existing plugins. ```json { "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 use 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 | ::: callout info "Preview Status & Platform Support" 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 workspace 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 reliable 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: ```json { "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. ### 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: ```json [ { "title": "GitHub", "path": "external:https://github.com/docmd-io/docmd" } ] ``` This is equivalent to: ```json [ { "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 workspace 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 workspace 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 - **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 - **workspace Cache**: Relocated state storage to deterministic temporary OS structures to prevent loss between loop boundaries --- ## [v0.8.10 - CLI Polish and Workspace UX](https://docs.docmd.io/release-notes/0-8-10/) --- title: "v0.8.10 - CLI Polish and Workspace UX" description: "Release notes for docmd v0.8.10 - clearer CLI error messages, deploy and migrate flag coverage, and plugin installer accuracy." date: "2026-07-06" --- ### ✨ Highlights This release is a developer-experience pass on the CLI after the 0.8.8 hardening and 0.8.9 plugin-loader work. The most user-visible change is that workspace configuration errors now point at the actual problem with a working example, instead of a single bare sentence. Several long-standing CLI gaps are also closed: the `deploy --force` flag is honoured (no more silent overwrites), `migrate --dry-run` is now a real option, `migrate --upgrade` covers the full legacy key map, the dev server shuts down gracefully on `docmd stop`, and the plugin installer no longer claims success on a no-op install. No public API changes. No breaking config changes. Purely a developer-experience release. ### 🔌 MCP server gets two new tools The `docmd mcp` server now exposes six tools (was four) and ships a working `prompts/list` handler so MCP clients that respect the declared `prompts` capability get a clean empty list instead of a "method not found" error. Two new tools: - **`list_docs(subdir?)`** — Lists every markdown file in the project, optionally scoped to a subdirectory (a locale, a version, a guide section). Returns relative paths so the agent can navigate the docs tree before reading individual files. The `subdir` argument is sandboxed through the same `safePath` boundary that protects `read_doc`. - **`get_config()`** — Returns the resolved `docmd.config` as a JSON object: title, source and output directories, configured locales, versions, and the list of enabled plugins. Sensitive values (API keys, analytics IDs) are reconstructed into a safe summary — raw secrets are never returned. Together with the existing `search_docs`, `read_doc`, `validate_docs`, and `get_llms_context`, an agent can now explore the project structure (`get_config` → `list_docs` → `read_doc`) without first guessing paths or doing blind `search_docs` calls. ### 🌐 Korean (`ko`) UI translation Thanks to a community contribution (PR #170, by @moduvoice), the built-in UI now ships with Korean translations. The locale is loaded at runtime the same way as every other translation — adding `ko.json` to the right directories is the entire registration step, no source change required. | Package | Keys | File | | :--- | :---: | :--- | | `@docmd/ui` (core theme) | 44 | `packages/ui/translations/ko.json` | | `@docmd/plugin-search` | 8 | `packages/plugins/search/i18n/ko.json` | | `@docmd/plugin-git` | 11 | `packages/plugins/git/i18n/ko.json` | | `@docmd/plugin-threads` | 42 | `packages/plugins/threads/i18n/ko.json` | Every `ko.json` file was verified to have the exact same key set as its `en.json` counterpart — no missing or extra keys, and all `{placeholder}` tokens preserved. A Korean-language docs site built with docmd now renders the built-in UI chrome (sidebar, search, 404 page, cookie consent, language/version switchers, git history widget, threads discussion plugin) in Korean instead of falling back to English. To opt out for a project, no configuration change is needed — the locale is only used when the project explicitly configures `i18n.locales` with `{ id: "ko", label: "한국어" }`. ### 🧪 `migrate --dry-run` for every migration path `docmd migrate --dry-run` is now a real flag for every supported source (Docusaurus, MkDocs, VitePress, Starlight) and for the in-place `--upgrade` path. Dry-run prints what would change and exits 0 without writing anything: ``` ┌─ Dry run: MkDocs migration │ Would move 3 files → mkdocs-backup/ │ docs │ index.md │ mkdocs.yml │ Would write docmd.config.js │ Config {"title":"My Test Site","src":"docs","out":"dist","theme":{"appearance":"system"}} └────────────────────────────────────────────────────────── ⬢ No changes made. Re-run without --dry-run to apply. ``` For `--upgrade`, the dry-run prints the upgraded config in full so you can diff it against the existing file before committing. ### 📦 `migrate --upgrade` covers the full legacy-key map The `--upgrade` path used to handle only six legacy keys (projects, siteTitle, siteUrl, baseUrl, srcDir, outputDir, defaultLocale). It now also handles: | Legacy key | Becomes | | :--- | :--- | | `source` | `src` | | `outDir` | `out` | | `nav` | `navigation` | | top-level `search` (boolean) | `plugins.search` | | top-level `sidebar` | `layout.sidebar` | | `theme.defaultMode` | `theme.appearance` | | `theme.enableModeToggle` | `optionsMenu.components.themeSwitch` | | `theme.positionMode` | `optionsMenu.position` | Each upgrade emits a `[ DONE ] Upgraded "X" to "Y"` step, and a config that doesn't contain any legacy keys still prints `Configuration is already up to date with the latest schema.` ### 🩺 Better workspace error messages When a workspace config is missing a root project (the most common first-time setup mistake), the error used to be a single bare sentence: `"Workspace configuration must have a root project with prefix "/""`. That gave the user no example and no path forward. The error now reads: ``` Workspace configuration must include a root project with prefix "/". Each workspace needs one project that owns the site root, with the others mounted under their own prefixes. Example: { "workspace": { "projects": [ { "name": "main", "src": "./docs", "prefix": "/" }, { "name": "api", "src": "./api-docs", "prefix": "/api/" } ] } } See https://docs.docmd.io/guides/workspace for the full layout guide. ``` The same shape applies to every workspace validation error: each one ends with the concrete configuration that would satisfy the validator. ### � `deploy --force` now means what it says The `--force` flag on `docmd deploy` was previously accepted but never read by the deployer. Running `docmd deploy --docker` on a project that already had a `Dockerfile` would silently overwrite it without warning. The new behaviour: - Without `--force`, an existing config file is preserved and the TUI line shows `[ SKIP ] Dockerfile (already exists, skipped — use --force to overwrite)`. - With `--force`, the existing file is overwritten as before. This applies to every deploy target: `--docker`, `--nginx`, `--caddy`, `--github-pages`, `--vercel`, and `--netlify`. ### 🛰️ Netlify template no longer soft-404s every route The generated `netlify.toml` used to include a `[[redirects]]` block that sent every URL to `/index.html` with HTTP 200: ```toml [[redirects]] from = "/*" to = "/index.html" status = 200 ``` That meant any missing route returned the home page with a 200 status — a soft-404 that hides errors, hurts SEO, and creates a URL-enumeration surface. The block has been removed: docmd generates a real HTML file for every route, so Netlify serves the right file when one exists and falls back to the bundled `404.html` (with a 404 status) when it doesn't. ### 🔗 Offline-mode links work in every hosting shape The `docmd build --offline` flag used to leave the rendered HTML with absolute paths like `<a href="/destination/">` for markdown links. Those work on an HTTP server but break when the user opens `site/index.html` from the filesystem — `file://` cannot resolve absolute paths that have no host. The fix post-processes the rendered markdown HTML in offline mode and rewrites every internal `<a href>` and `<img src>` to a relative `.html` path using the same logic the button container (`:::`) already used. The result: | Source | `build` (HTTP) | `build --offline` (file://) | | :--- | :--- | :--- | | Button container `::: "/destination"` | `./destination/` | `./destination/index.html` | | Markdown link `[text](/destination)` | `/destination/` | `./destination/index.html` | | Markdown image `![alt](/assets/x.png)` | `/assets/x.png` | `./assets/x.png` | | External `https://example.com` | unchanged | unchanged | | Anchor `#section` | unchanged | unchanged | Non-offline builds are completely unchanged (clean URLs preserved for SEO). The output works in every hosting shape: `file://`, HTTP servers, custom domains, the dev server, the live editor. Nested pages get the correct `../` prefix to navigate up from subfolders. ### 🔌 docmd-search peer dependencies auto-install together When `plugins.search.semantic: true` is set and either `docmd-search` itself or one of its peers (`@huggingface/transformers`, `onnxruntime-node`) is missing, the plugin now: 1. Restricts its module-resolution scope to the user's project (`process.cwd()/node_modules` only) — previously it could walk up to the monorepo root via `__dirname` and find a copy there, leading to confusing behaviour. 2. Auto-installs **just the peers** when only those are missing (previously: warn and give up). 3. Surfaces the **actual reason** in the fallback message — previously the message always said "docmd-search not installed" even when only a peer was missing. ### 🛰️ Open Knowledge Format is on by default OKF has shipped in 0.8.8 and is fully on by default: - Auto-loaded for every build unless explicitly disabled via `plugins.okf: false`. - `plugins.okf.typeField` defaults to `type` (frontmatter > path > fallback). - Missing `type` fields get ONE summary `TUI` line plus a per-page entry in `okf/_meta/lint-report.txt` so detail isn't lost. - Orphan concepts and broken internal links are listed in the same lint report. - Graph viewer is opt-in via `plugins.okf.graph: true` (a `graph/index.html`, `graph.js`, and `graph.css` get emitted under `okf/graph/`). - `plugins.okf.i18n: true` emits OKF bundles for every configured locale (default-only otherwise). No public API changes. ### 🛑 Graceful shutdown on `docmd stop` `docmd stop` used to send SIGTERM and, if that failed, immediately send SIGKILL. The dev server's SIGTERM handler was a one-liner `process.exit(0)` that bypassed the watchers, HTTP server, WebSocket server, and worker-pool cleanup. After a stop, child processes and live sockets could be left hanging. The new flow: 1. `docmd stop` sends SIGTERM. 2. The dev server runs the same graceful shutdown as Ctrl+C (close watchers → close wss → close http server → terminate worker pool → exit 0). 3. `docmd stop` polls every 100ms for up to 5 seconds for the process to exit on its own. 4. Only if the process is still alive after the grace period does `docmd stop` escalate to SIGKILL. The TUI line shows `Stopped ... PID gracefully` for a clean exit, or `Killed ... PID (SIGKILL after grace)` if the escalation was needed. ### 🐛 Bug fixes - **Workspace validator: actionable error message when no root project is configured.** The single-sentence error is replaced with a multi-line message that explains the requirement, shows a valid JSON example, and links to the workspace layout guide. - **Plugin installer: accurate final message for already-installed plugins.** `docmd add <plugin>` for a plugin that's already in the config used to print "Plugin successfully installed and activated" even though no install happened. The final TUI line now reflects the actual outcome: new install prints the success message; already-configured prints `⬢ Plugin was already configured. Nothing changed.` - **Deployer: `--force` no longer silently clobbers existing configs.** Every deploy target now honours `--force`: default behaviour is to skip existing files; `--force` opts in to overwriting. - **Deployer: Netlify `[[redirects]]` block removed to fix the soft-404.** Generated `netlify.toml` no longer rewrites every URL to `/index.html` with status 200. Missing routes now serve the bundled `404.html` with a 404 status. - **Offline build: markdown links and images are now rewritten to relative `.html` paths.** Previously only the button container was offline-aware; markdown `[text](url)` and `![alt](src)` emitted absolute paths that `file://` couldn't resolve. They now go through the same `fixHtmlLinks` rewrite as the button container (#167). - **Dev server: SIGTERM runs the same graceful shutdown as SIGINT.** The dev server now closes watchers, the WebSocket server, the HTTP server, and the worker pool on SIGTERM before exiting. `docmd stop` polls for the process to exit and only escalates to SIGKILL after a 5-second grace period. - **docmd-search: peer dependencies auto-install when missing.** When `plugins.search.semantic: true` is set and the peer packages (`@huggingface/transformers`, `onnxruntime-node`) are not installed, the plugin now installs them rather than warning and falling back to keyword search (#163 deeper fix). - **Versions: `config.versions.list` accepted as alias for `all`.** Users who wrote `list` (a common shape for "list of versions") saw silent 0-page builds because the schema only recognised `all`. Aliasing `list` → `all` restores their config without changing the canonical key (M-6). - **Versions: missing current-version directory is a hard error.** The build now aborts with a clear pointer to the missing path and the version id. Previously it silently produced a 0-page site with no actionable message. Old (non-current) versions remain soft-warns (T-Z6). - **llms.txt / llms.json titles are sanitised.** Frontmatter titles containing markdown injection chars (`` ` ``, `[`, `]`, newlines) no longer break the link form or render as raw HTML, and titles starting with `=`, `+`, `-`, or `@` are prefixed with a single-quote so opening the file in a spreadsheet does not execute a formula. CSV formula neutralisation (T-Z11) and markdown injection prevention (T-Z10) in one helper. - **`NO_COLOR` and `DOCMD_NO_BANNER` suppress the build banner.** Setting `NO_COLOR=1` (or the docmd-specific `DOCMD_NO_BANNER=1`) now hides the ASCII art and version line at the top of the build output. `NO_COLOR` is the de-facto standard for CLIs; `DOCMD_NO_BANNER` is a docmd-specific escape hatch for users who want colour but no banner (N-13 + N-16). - **Migration polish.** `moveFilesToBackup` now keeps lockfiles and `package.json` in place so a recovery doesn't have to re-resolve every dependency (N-10). The Docusaurus and MkDocs migrators preserve the original `staticDir` / `site_dir` (N-22) and MkDocs `nav:` blocks are translated to docmd's `navigation` format with multi-level sections preserved via `children` (N-9). - **MCP: `prompts/list` returns an empty list instead of "method not found".** The server declares `prompts` capability in `initialize` for forward compatibility, but had no handler. MCP clients honouring the capability advertisement now get `{ prompts: [] }` instead of an unhandled-method error. ### Changelog 1. **Workspace validator**: `validateProjects` in `packages/core/src/engine/workspace.ts` now throws a multi-line `Error` with a JSON example and a docs link when no project has `prefix: "/"` (M-2). 2. **Plugin installer**: `addPlugin` in `packages/plugins/installer/src/index.ts` branches on the `injected` flag returned by the config editor and emits `TUI.info` for the already-configured case, instead of the misleading `TUI.success` (M-14). 3. **Deployer**: `write()` in `packages/deployer/src/index.ts` now takes a `force` argument and skips with a `[ SKIP ]` TUI line when the target file exists and `--force` was not passed (N-2). All six target generators (docker, nginx, caddy, github-pages, vercel, netlify) pass `opts.force` through. 4. **Deployer (Netlify)**: `generateNetlify` in `packages/deployer/src/providers/netlify.ts` no longer emits a `[[redirects]] from = "/*" status = 200` block. docmd generates real HTML per route, so the catch-all was both unnecessary and the source of the soft-404 (T-Z9). 4. **Stop**: `stopServer` in `packages/core/src/commands/stop.ts` exports a new `waitForExit(pid, timeoutMs)` helper and uses it to poll for the target process to exit after SIGTERM. The escalation to SIGKILL only happens after the 5-second grace period (M-11). 5. **Dev server**: `startDevServer` in `packages/core/src/commands/dev.ts` extracts the SIGINT shutdown path into a `gracefulShutdown()` function used by both `SIGINT` and `SIGTERM` handlers (M-11). 6. **Migrate**: `migrateProject` in `packages/core/src/commands/migrate.ts` accepts a new `dryRun` option (N-3). For every source path (Docusaurus, MkDocs, VitePress, Starlight) the dry-run prints the file move list and the new `docmd.config.js` before any side effects; for `--upgrade` it prints the upgraded config. `packages/core/src/bin/docmd.ts` adds `--dry-run` to the migrate CLI. 7. **Migrate**: the `--upgrade` path in `packages/core/src/commands/migrate.ts` now handles eight additional legacy keys: `source`, `outDir`, `nav`, top-level `search`, top-level `sidebar`, `theme.defaultMode`, `theme.enableModeToggle`, and `theme.positionMode` (N-4). 8. **Tests**: `tests/cli-contracts/validate-workspace.test.js` adds 5 new M-2 assertions covering the exit code and the four message-content invariants. 10. **MCP server**: `runMcpServer` in `packages/core/src/commands/mcp.ts` adds `list_docs` (file listing, sandboxed `subdir`) and `get_config` (safe config summary) tools, and a `prompts/list` handler returning `{ prompts: [] }`. `tools/list` now advertises six tools. 11. **Korean (ko) UI translation**: community contribution (PR #170, @moduvoice) adds `ko.json` for `@docmd/ui` (44 keys), `@docmd/plugin-search` (8), `@docmd/plugin-git` (11), and `@docmd/plugin-threads` (42). All key sets verified identical to `en.json`; no source changes required thanks to the runtime translation loader. 9. **Tests**: `tests/cli-contracts/plugin-add-remove.test.js` adds 3 new M-14 assertions covering the already-installed message, the absence of the false success message, and the regression guard for fresh installs. 10. **Tests**: new `tests/cli-contracts/deploy.test.js` (5 assertions, registered in `tests/runner.js` as `deploy`) covers the N-2 skip / overwrite / fresh paths. 11. **Tests**: new `tests/cli-contracts/stop.test.js` (3 assertions, registered as `stop`) covers the M-11 `waitForExit` helper against live child processes. 12. **Tests**: new `tests/cli-contracts/migrate.test.js` (33 assertions, registered as `migrate`) covers N-3 dry-run for both source migrations and upgrade, and N-4 coverage of all 13 legacy upgrade paths. --- ## [v0.8.11 - Security Fixes and Cross-Locale Routing](https://docs.docmd.io/release-notes/0-8-11/) --- title: "v0.8.11 - Security Fixes and Cross-Locale Routing" description: "Release notes for docmd v0.8.11 - threads plugin XSS fix, init template JSON fix, cross-locale link rewrite, TUI error summary, Docusaurus frontmatter translation, and deploy template node bump." date: "2026-07-10" --- ### ✨ Highlights This release is a security and quality patch addressing six non-breaking issues from the v0.8.6 battle-test report. The most important change is a stored XSS in the threads plugin — a malicious `authors.json` could escape the `<script>` block and execute arbitrary JavaScript on every page that loads the threads client. The fix parses the file as JSON and re-serialises through a `scriptLiteral` helper that escapes the four byte sequences the HTML parser treats specially (`</script`, `<!--`, U+2028, U+2029). A second user-visible fix corrects the cross-locale link rewrite: when a non-default-locale page (e.g. `fr/index.md`) writes a link to the default-locale prefix (e.g. `/en/`), the build used to emit `<a href="/en/">` which 404s because the default-locale page actually lives at root, not under its own prefix. The fix strips the default-locale prefix from absolute hrefs in the rendered markdown so the link points to the actual page. No public API changes. No breaking config changes. Purely a security + DX release. ### 🔒 Security: threads plugin `</script>` breakout (S-7) The threads plugin read `docs/.threads/authors.json` with `fs.readFileSync` and interpolated the **raw text** into a `<script>` body. Any author field containing `</script>` would close the script tag and inject arbitrary HTML/JS into every page that uses the threads client. CWE-79 XSS, CVSS 8.1. **The fix** (in `packages/plugins/threads/src/index.ts`): 1. Parse `authors.json` as JSON (not raw text) so the payload gets proper string escaping. 2. Coerce non-object top-level values to `{}` (the runtime schema is a plain object). 3. Re-serialise through `scriptLiteral` from `@docmd/utils`, which escapes the four byte sequences that are unsafe inside an inline `<script>` block: `</script`, `<!--`, U+2028, U+2029. 4. Log a single error and fall back to `{}` on parse failure rather than letting the build crash on a malformed config. Added `@docmd/utils` as a runtime dependency. A regression probe lives at `scripts/probe-threads-xss.mjs` — it feeds attacker payloads (`</script><script>`, U+2028, non-object values) and asserts the output contains no breakout. ### 🔒 Security: `init` template generated invalid JSON (F9) The default `docmd.config.json` template produced by `docmd init --yes` was missing a comma between the `Agent Skills` navigation entry and the `Quick Guide` group. Any user who ran `init` got a config file that failed JSON parse at position 886. The build then aborted with `Error parsing config file: Expected ',' or ']' after array element`. **The fix** (in `packages/core/src/commands/init.ts`): single-character correction to `defaultConfigContent`. The init demo template, the Docker image's seeded template, and every fresh `docmd init` now produce a valid config on the first run. ### 🌐 Cross-locale link rewrite (M-5) When the default locale is `en`, English pages live at `/index.html`, `/api/`, etc. — **not** at `/en/`. But a non-default-locale page (e.g. `docs/fr/index.md`) writing `[English](/en/)` produced `<a href="/en/">` which 404s, because the default-locale page is at `/` not `/en/`. The `hreflang` annotations were already correct (0.8.10 fix); only the inline markdown link path needed the same treatment. **The fix** (in `packages/parser/src/markdown-processor.ts` + `packages/core/src/engine/generator.ts`): 1. Engine passes `defaultLocale` and `allLocales` to the markdown post-processor through the existing `env` object. 2. A new `stripDefaultLocalePrefix()` helper walks every `<a href="/<defaultLocale>/...">` in the rendered HTML and drops the prefix, so `/en/foo` from a `fr/` page becomes `/foo`. 3. The strip runs **before** the existing `#167` relative-path rewrite, so both passes see a clean, correct path. 4. The fix is locale-id-aware: it only matches the configured default locale, and it never touches external URLs, anchors, `mailto:`, or `src=` on `<img>`. Adds **Test 3.5** in `feature-integration.test.js` (6 assertions) covering both the fix and the no-regression for the online build (clean URLs without `index.html` suffix). ### 📊 End-of-build error summary (N-12) Previously the user saw `Build complete. Generated N pages in Tms` and only later discovered plugin failures when a downstream tool choked on a bad artifact. Now every failed plugin is listed by name + hook + reason in the TUI before the build aborts. **The fix** (in `packages/core/src/commands/build.ts`): 1. Load failures (`getPluginLoadErrors()`) — each failed plugin is listed as `• <name> — <reason>` under a `N plugin(s) could not be loaded` TUI error block. 2. Runtime hook failures (`getPluginErrors()`) — every plugin error is listed as `• <plugin> :: <hook> — <message>` under a `Plugin errors during build` TUI error block. 3. The build still exits 1 (the original `process.exit(1)` after error throw is preserved) but the operator now sees the **full list** before the process dies, not just the last error. ### 🔄 Docusaurus `id` / `sidebar_label` frontmatter translation (T-Z14 / T-Z17) `docmd migrate --docusaurus` used to copy the `docs/` directory verbatim, leaving every Docusaurus-specific frontmatter key in place. docmd's parser didn't recognise `id:` (it derives route IDs from filenames) and had no way to use `sidebar_label:` (it expects `nav_title:` for navigation overrides). The migration was technically successful but produced a config that was semantically wrong. **The fix** (in `packages/core/src/commands/migrate.ts`): a new `translateDocusaurusFrontmatter()` helper walks the copied docs directory, finds every `.md` / `.mdx` / `.markdown` file, and: 1. **Drops `id:`** — docmd derives the route from the filename, so the Docusaurus override is meaningless. 2. **Translates `sidebar_label:` → `nav_title:`** — docmd's first-class nav override. Files that fail to parse keep their original content; a TUI line reports the count of files touched (e.g. `Translated Docusaurus frontmatter in 14 file(s)`). The translation runs on every `docmd migrate --docusaurus` invocation including `--dry-run` previews. ### 🐳 Deploy template: `node:20-alpine` → `node:22-alpine` (N-5 / N-8) The deploy generator template `packages/deployer/src/providers/docker.ts` was pinned to `node:20-alpine` even though Node 20 went End-of-Life on 2026-04-30. New Dockerfiles generated today by `docmd deploy --docker` would have been built on an EOL base image. **The fix**: bump the template to `node:22-alpine`. The published `docker/Dockerfile` (used to build the official `ghcr.io/docmd-io/docmd` image) is still on `node:20-alpine` until the next major release — the deploy template can lead the published image because it's a *suggestion* for users to customise, not a contract. ### 🔍 Semantic search: auto-detect + first-build fix When `plugins.search.semantic: true` is set, the build pipeline installs `docmd-search` and its peer deps (`@huggingface/transformers`, `onnxruntime-node`) on first run. But the HTML modal was rendered BEFORE the install completed, so the `data-semantic="true"` attribute was never emitted — the browser fell back to keyword search even though the semantic index existed on disk. **Three changes:** 1. **Runtime auto-detect** (`client.ts`): the browser client now probes for `.docmd-search/manifest.json` via a HEAD request, regardless of what `data-semantic` says on the modal. This catches the first-build case where deps were installed in `onPostBuild` (after `generateScripts` already rendered the page). One round-trip per page load — zero perf cost. 2. **Single source of truth** (`index.ts`): `onConfigResolved` computes a `searchConfig` object (semanticRequested, docmdSearchInstalled, peersInstalled, semanticUsable) and stamps it on `config._searchConfig`. `generateScripts` and `getAssets` both read from this object — no more duplicate resolution checks that could disagree. 3. **Correct TUI ordering**: the "missing dependencies" warning now only appears AFTER `ensureDocmdSearch` has genuinely failed to install — not before. Previously the warning fired pre-install and was immediately contradicted by the "[ DONE ] installed successfully" line below it. ### Verification - `pnpm --filter @docmd/parser build`: clean - `pnpm --filter @docmd/core build`: clean - `node tests/runner.js --skip-setup`: **543 passed, 0 failed** (was 537; +6 from M-5 regression tests in feature-integration.test.js) - `node tests/feature-integration.test.js`: **143 passed, 0 failed** (was 137) - `node scripts/probe-threads-xss.mjs`: **5/5 checks pass** (XSS regression probe) - No public API changes, no breaking config changes --- ## [v0.8.12 - Auto-Install Hardening and GitHub Pages Fix](https://docs.docmd.io/release-notes/0-8-12/) --- title: "v0.8.12 - Auto-Install Hardening and GitHub Pages Fix" description: "Release notes for docmd v0.8.12 - hardened auto-install pipeline (CWE-78), engine auto-install, corrected core dependency manifest, and automatic base path derivation for GitHub Pages project sites." date: "2026-07-12" --- ### ✨ Highlights This release fixes a regression that broke asset loading on GitHub Pages project sites (#175), hardens the plugin/template/engine auto-install pipeline against shell injection (CWE-78), and removes `@docmd/plugin-pwa` from the default install (it was never a core plugin). No breaking changes. No new required config. Existing configs, plugins, and CI pipelines work unchanged. ### 🐛 Fix: GitHub Pages project sites 404 on all assets (#175) Users deploying to `https://username.github.io/repo-name/` saw every CSS, JS, and image file 404 after upgrading from 0.8.9. The cause: 0.8.10 added a `<base href="/">` tag to fix a separate workspace issue, which made the browser resolve all relative URLs against the domain root instead of the subpath. **The fix:** docmd now derives the asset base path from your `url` config automatically. If `url` is `https://username.github.io/my-repo`, docmd sets `base` to `/my-repo/` internally. No manual `base` config is needed. ```json "docmd.config.json" { "url": "https://username.github.io/my-repo" } ``` That's it. docmd handles the rest. Users who explicitly set `base` are unaffected. The derivation is slash-tolerant on both `url` and `base` — `"my-repo"`, `"/my-repo"`, and `"/my-repo/"` all work. ### 🔒 Security: shell injection in auto-install (CWE-78) The plugin auto-install path built a shell-string command by interpolating the package name into `pnpm add ${pkg}`. A package name with shell metacharacters that ever reached this code path would execute arbitrary commands under the user's account. **The fix:** a new shared module (`packages/api/src/runtime-deps.ts`) replaces the shell-string with `spawn(pm, args, { shell: false })` using a fixed arg array. A strict regex validator (`/^@docmd\/(plugin|template|engine)-[a-z0-9][a-z0-9.-]*$/`) and a registry lookup act as defence-in-depth. The auto-install path can no longer be turned into a generic `npm install` loader. ### 🧰 Shared runtime-deps module The plugin loader (`hooks.ts`) and the engine loader (`engine.ts`) each used to carry their own copy of the auto-install pipeline. Both now go through `runtime-deps.ts`. One install behaviour, applied everywhere. The TUI status reporter is idempotent per-build, so dev-server rebuilds do not spam duplicate `[ WAIT ]` / `[ DONE ]` lines. ### 🛠 Engine auto-install Requesting `engine: "rust"` in config used to fall straight through to JS if `@docmd/engine-rust` was not installed. The new flow tries to install `engine-rust` first; if the install fails or the native binary is not usable on the platform, it falls back to JS and surfaces the reason in a `[ FAIL ]` line. The same applies to `loadEngine('js')` as a last resort. ### 📦 Corrected core dependency manifest `@docmd/plugin-pwa` was listed as a direct dependency of `@docmd/core` but was never in `CORE_PLUGINS` (the source-of-truth constant that drives auto-loading). Every `npm install @docmd/core` pulled it in, even for users who never enabled PWA. **The fix:** removed `@docmd/plugin-pwa` from `packages/core/package.json#dependencies`. It now installs on demand, the same as `math`, `threads`, and every other optional plugin. The dependency list now matches `CORE_PLUGINS` exactly. ### 📐 Test coverage 51 new assertions in `tests/cli-contracts/runtime-deps.test.js`: public surface, validator (12 positive, 13 negative cases including shell metacharacters), registry cache idempotency, install refusal paths, and static source checks proving no `execSync` shell-string remains in `hooks.ts` or `engine.ts`. ### Migration Zero. Existing configs, plugins, and CI pipelines work unchanged. **Full changelog**: https://github.com/docmd-io/docmd/compare/0.8.11...0.8.12 --- ## [v0.8.13 - Centralised Base Tag and Auto-Install Cache Fix](https://docs.docmd.io/release-notes/0-8-13/) --- title: "v0.8.13 - Centralised Base Tag and Auto-Install Cache Fix" description: "Release notes for docmd v0.8.13 - the <base> tag is now enforced centrally by the generator (templates can no longer drift), offline mode no longer emits a <base> tag (#177), and the auto-install retry path uses a manual node_modules walk-up that bypasses Node's stale require.resolve cache on Linux CI." date: "2026-07-14" --- ### ✨ Highlights This release closes the loop on three issues reported against 0.8.10–0.8.12: the `#175` GH Pages asset path regression, the `#177` offline-mode `<base>` break, and the `#167` offline link rewrite. The root cause of all three was that the `<base>` tag decision was scattered across templates — 0.8.13 makes the generator the single source of truth. As a bonus, the auto-install retry path no longer fails on Linux CI for `@docmd/template-summer`, `docmd-search`, and other on-demand deps, because the post-install load now uses a manual `node_modules` walk-up instead of relying on Node's stale `require.resolve` cache. No breaking changes. No new required config. Existing configs, plugins, and CI pipelines work unchanged. ### 🐛 Fix: `<base>` tag decision centralised in the generator (#175, #167, #177) 0.8.10 added an unconditional `<base href="/">` to the layout template. That fixed a workspace asset issue but broke three other things at once: - `#175` (GH Pages subpath): when a user set `url: "https://user.github.io/repo"`, the `<base>` should have been `"/repo/"` not `"/"`. 0.8.10 was fixed for subpath, but the root-deploy case still emitted the unnecessary `<base href="/">`. - `#167` (offline link rewrite): the markdown post-processor correctly rewrote `/destination/` to `./destination/index.html` in offline mode, but the `<base href="/">` then told the browser to re-root those relative paths against the filesystem root over `file://`. The links "worked" in the HTML source but 404'd in the browser. - `#177` (offline CSS/assets): opening `site/index.html` from disk produced unstyled pages for the same reason — the `<base>` re-rooted `./assets/css/...` to filesystem root, which 404s. **The fix (0.8.13):** the generator now computes the canonical `<base>` decision based on `(isOfflineMode, siteRootAbs)` and applies it after template rendering. Templates no longer emit `<base>` themselves. The decision table: | Scenario | `<base>` emitted | Why | | :--- | :---: | :--- | | `build` (online, root deploy) | no | Relative URLs resolve against the document URL, which is what we want | | `build` (online, GH Pages subpath) | `<base href="/repo/">` | Browser needs to know it's at a subpath | | `build --offline` | no | `file://` resolution must use document-relative paths | | `file://` (direct disk view) | n/a | Search client shows the helpful offline message instead | **No template edits required for existing users** — the build output is now correct by default. The change is invisible unless you were relying on a template emitting its own `<base>` (which no official template did). ### 🔧 Auto-install retry now survives Node's stale resolve cache The auto-install path (`tryLoadAfterInstall`) used a bare `import(packageName)` for the post-install load. On Linux CI, Node's internal `require.resolve` cache returned a stale "not found" even after `npm install` had placed the package in `node_modules`. The result: build would install `@docmd/template-summer` and `docmd-search` successfully, then fail with `Could not load @docmd/template-summer after auto-install` (this was the CI failure that broke GH Pages deploys in 0.8.12). **The fix:** a new `manualResolvePackageEntry()` walks the `node_modules` directory tree with fresh `fs.existsSync()` checks, completely bypassing Node's resolve cache. The new flow is: 1. Try `createRequire(consumerCwd).resolve(name)` (fast, honours `exports` field). 2. If that fails, walk up from `consumerCwd` looking for `node_modules/<name>/package.json` directly (reliable, cache-free). As a bonus, a new `DOCMD_INSTALL_VERSION` environment variable overrides the version used in `npm install <name>@<version>`, so users can pin to a specific release or use `latest` regardless of what's installed locally. ### 🐛 Fix: search client shows a helpful message on `file://` The keyword search and semantic search both use `fetch()` to load index files. Browsers block `fetch()` from `file://` URLs (CORS), so opening `site/index.html` from disk showed `Failed to load search index.` — a misleading error that suggested something was broken. 0.8.13 detects `window.location.protocol === 'file:'` before any fetch and shows a clear message instead: > Search requires a web server. Open this site via http://localhost instead of file:// to enable search. This makes the limitation explicit instead of leaving the user to wonder why their search "doesn't work" offline. A true offline index is a separate feature (track separately if you want it). ### 🧹 Test and lint cleanup - `eslint.config.mjs` now ignores `_`-prefixed variables/arguments/caught errors (standard convention) - `tools/prep.js` test runner streams test output live instead of capturing silently - `tools/simulate-consumer.mjs` empty catch block has an explanatory comment - `packages/plugins/openapi/` removed a dead `const r = ...` binding and a stale eslint-disable directive - Removed dead `summariseTests()` / `extractFailures()` helpers from `prep.js` (replaced by streaming) ### Migration Zero. Existing configs, plugins, and CI pipelines work unchanged. The `<base>` change is fully backwards-compatible for any site whose `url` config matches the actual deployment URL. **Full changelog**: https://github.com/docmd-io/docmd/compare/0.8.12...0.8.13 --- ## [v0.8.14 - Offline Navigation Robustness, Secure Spawning, and Test Speed-up](https://docs.docmd.io/release-notes/0-8-14/) --- title: "v0.8.14 - Offline Navigation Robustness, Secure Spawning, and Test Speed-up" description: "Release notes for docmd v0.8.14 - unified offline URL resolution (#179), path-traversal/command injection security hardening (#167, #175), and optimised test runner dependency resolution." date: "2026-07-15" --- ### ✨ Highlights This release focuses on consolidating offline link generation, securing dependency installs, and optimised test execution. Key issues addressed include `#179` (offline folder navigation redirects), `#167`/`#175` (SEO metadata omissions in offline builds), and security hardening against command injection (CWE-78) in the installer. Furthermore, we have resolved performance bottlenecks in the test runner, dropping test suite latency from 15 minutes to under 2 minutes. No breaking changes. No new config required. Existing configurations, plugins, and CI pipelines work unchanged. ### 🐛 Fix: Unified Offline Navigation (#179) Previously, system-generated navigation elements (logo, breadcrumbs, version/language switchers, sidebar) emitted directory-style links (such as `./` or `/`). When viewed offline over `file://`, browsers resolved these to filesystem directory paths rather than explicit HTML files, resulting in directory listings or broken pages. **The fix:** all URL generation has been consolidated into a single source of truth (`packages/parser/src/utils/url-utils.ts`). Navigational components now route through bound helpers (`buildRelativeUrl` and `buildAbsoluteUrl`). In `--offline` mode, all generated URLs automatically resolve directory endpoints to explicit `index.html` targets (e.g. `./index.html` or `../index.html`), ensuring bulletproof navigation across local filesystems. ### 🧹 SEO & Metadata Robustness (#167, #175, #177) Canonical links, Open Graph tags (`og:url`, `og:image`), and Twitter Card tags require absolute URLs. When `siteUrl` was missing or the project was compiled in `--offline` mode, these tags resolved to broken root-relative paths like `/guide/`, which caused metadata errors. **The fix:** the SEO plugin now checks `siteUrl` and `offline` flags. Canonical and Og/Twitter metadata tags are omitted in offline builds or if `siteUrl` is not configured, unless they are explicitly absolute URLs. ### 🔒 Security: Command Spawning Hardened (CWE-78) Peer-dependency installation within `@docmd/plugin-search` has been refactored to prevent command injection risks. **The fix:** we replaced shell-based execution (`execSync`) with a secure, centralised runtime-dependency installer. Package managers are now spawned directly via argument arrays without shell expansion, ensuring robust cross-platform execution in CI and production environments. ### ⚡ Optimisation: Test-Suite Dependency Resolving The feature integration and asset pipeline tests previously triggered costly, network-heavy package installations (e.g. downloading `docmd-search` and its peer dependencies) in temporary test folders, driving execution time up to 15 minutes. **The fix:** we introduced the `DOCMD_TEST_SEARCH_PATH` environment variable. During test runs, the plugin bypasses external npm package downloads and resolves search and template dependencies directly from the monorepo workspace. The entire test suite now completes in under two minutes. ### 🚀 Optimisation: Incremental Semantic Indexing Cache Reuse Previously, the search plugin compiled the search index from scratch on every rebuild/reload, taking 30–42 seconds because the output directory (`site/.docmd-search/`) was cleared. **The fix:** - The search plugin now writes the semantic index to the **docs source directory** (`docs/.docmd-search/` or version directory `ver.dir/.docmd-search/`) which is preserved across builds and checked into version control. - It runs incremental indexing in this folder (reusing existing manifests and batch files) and recursively copies the final generated index assets to the site output directory. - This results in a **100x+ build speedup** (warm rebuilds complete in **under 300ms**). ### ⚙️ Rust Engine Native Addon DX & Routing - **Local Binary Copying:** Configured `postinstall.cjs` in `@docmd/engine-rust` to check for sibling `rust-binaries/bin/` folders, enabling the Rust engine to be used during development and testing of new versions prior to npm CDNs publication. - **Task Routing:** Updated task routing to only dispatch native-supported tasks (`file:*` and `search:index`) to the Rust engine, falling back seamlessly to JS for unsupported search-related tasks. ### Migration Zero. Existing configurations, plugins, and CI pipelines work unchanged. **Full changelog**: https://github.com/docmd-io/docmd/compare/0.8.13...0.8.14 --- ## [v0.8.15 - Subpath Deploy Fix, Local Search Bundle, and Auto-Install Cleanup](https://docs.docmd.io/release-notes/0-8-15/) --- title: "v0.8.15 - Subpath Deploy Fix, Local Search Bundle, and Auto-Install Cleanup" description: "Release notes for docmd v0.8.15 - proper GitHub Pages subpath asset resolution (#175), navigation trailing-slash consistency, locally-bundled MiniSearch, and de-duplicated auto-install output." date: "2026-07-16" --- ### ✨ 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. ::: callout tip "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 --- ## [v0.8.16 - Dev Server Base Fix, Unified Search Folder, and Auto-Install Hardening](https://docs.docmd.io/release-notes/0-8-16/) --- title: "v0.8.16 - Dev Server Base Fix, Unified Search Folder, and Auto-Install Hardening" description: "Release notes for docmd v0.8.16 - dev server no longer breaks on subpath URLs, all search artefacts move to .docmd-search/, the redundant manifest probe is removed, and auto-install no longer pre-blocks workspace sub-projects." date: "2026-07-16" --- ### ✨ Highlights Three coordinated fixes that close the follow-ups to `#175` reported on `v0.8.15`. No breaking changes, no new config keys, no required migrations. Existing projects build and serve unchanged. ### 🐛 Fix: Dev server respects the production URL `v0.8.15` introduced auto-derivation of `base` from `url`'s pathname, so a GitHub Pages project site at `https://user.github.io/repo` automatically gets `base = /repo/` and emits subpath-aware asset URLs. The dev server, however, always serves the output dir at root (`/`) — so every asset on `localhost` 404'd whenever `url` carried a subpath. The reported workaround was `"base": "/"`, which made dev work but disabled the auto-derivation, breaking search on the production deploy. Both states were broken for one environment. **The fix:** dev mode now forces `base = /` when the value was auto-derived. The override is restricted to: - `isDev: true` (build path is untouched) - `_baseAutoDerived` is set (an explicit `base` in the config is always honoured) - `DOCMD_PROJECT_PREFIX` env var is absent (workspace dev uses it) Users no longer need a `base` entry in their config at all. ### 🗂 Fix: All search data moves to `.docmd-search/` Keyword and semantic search now share a single output folder: - **Before:** `search-index.json` lived at the output root, semantic files under `.docmd-search/`. - **After:** both live under `.docmd-search/`. Default locale: `.docmd-search/search-index.json`. Non-default: `.docmd-search/<locale>/search-index.json`. This keeps the output root clean and unifies the contract the client fetches against, so the next fix could land cleanly. ### 🐛 Fix: Removed the runtime `manifest.json` HEAD probe The search client probed `.docmd-search/manifest.json` with a `HEAD` request on every page load to catch the narrow case where semantic deps were installed mid-build. On every keyword-only site that probe returned 404, which was the exact error users were reporting. **The fix:** semantic mode is decided solely by the build-time `data-semantic` flag on the search modal. The flag is computed in `onConfigResolved` from `semanticUsable`, so the build and the client agree on which mode is active. The rare mid-build edge case resolves on the next rebuild (dev mode triggers one automatically). ### 🐛 Fix: Keyword index always generates as fallback Once the runtime probe was removed, a second race surfaced: when semantic indexing succeeded, the keyword `search-index.json` was skipped entirely. If the modal's `data-semantic` flag was stale (set to `false` at render time because deps were not yet installed), the client fell back to keyword mode and 404'd because no keyword index existed. **The fix:** the keyword index now always generates, even after a successful semantic build. The index is tiny (a few KB for most projects) and serves as a runtime safety net. TUI messages are suppressed when semantic already ran, so the log stays clean. ### 🐛 Fix: `data-semantic` flag stamped post-build The `data-semantic="true"` attribute on the search modal is computed at render time from `semanticUsable`, which checks whether `docmd-search` is resolvable. On a fresh install, deps are installed in `onPostBuild`, after pages have already been rendered without the flag. The client then defaults to keyword mode even though the semantic index exists. **The fix:** after the semantic index builds successfully, every HTML page is post-processed to ensure the modal carries `data-semantic="true"`. This closes the race without reintroducing the runtime HEAD probe. The post-build walk skips `.docmd-search/` and `node_modules/` to stay fast on large sites. ### 🧰 Auto-install no longer pre-blocks workspace sub-projects The pre-check that scanned for `package.json` in `cwd` before spawning the package manager has been removed. npm, pnpm, yarn, and bun all walk up the directory tree themselves to find the project root, so the pre-check was wrong in two cases it claimed to handle: 1. Workspace sub-projects (e.g. `docs/docmd-search/` when `docs/package.json` lives one level up). 2. Any case where a plugin or template needs to install and the project root is several dirs deep. **The fix:** the spawn is always attempted. The friendly "no `package.json` found" hint now fires only when the spawn genuinely fails **and** no `package.json` exists in any ancestor directory. Templates are covered by the same path as plugins. Verified end-to-end with a fresh brutetest using `@docmd/template-summer` and `plugins.search.semantic: true`: both auto-install silently on the first build, summer CSS/JS land at `site/assets/template/`, and the semantic index writes to `site/.docmd-search/`. ### 🏗 Portable deploys via canonical `<base href>` Non-offline builds with a subpath (`siteRootAbs !== '/'`) now emit a single `<base href="/<repo>/">` tag in the document head. Asset URLs in the head use **simple-relative** paths (`assets/foo.css`); the `<base>` tag shifts them to the correct location at runtime, no matter where the site is hosted. **Why this matters:** the previous approach encoded the subpath into every asset URL. The rename-flow went like this — you rename the repo, the next build keeps emitting `/old-name/assets/...` until you update `config.url` and rebuild. With `<base>`, the path is computed once from the deploy location and applied uniformly. Moving a site between repos, hosts, or folder mounts no longer requires touching `config.url` if `url` is already correct for the current deploy. **Three-mode boundary** to keep this clean: | Mode | `<base>` | Assets | |---|---|---| | `build` (subpath) | emitted | simple-relative `'assets/foo.css'` | | `build` (root deploy) | none (document default) | simple-relative `'assets/foo.css'` | | `dev` | none | depth-aware `./` or `../` | | `build --offline` | none (file:// has no host) | depth-aware `./` or `../` | The canonicaliser (`normaliseBaseTag` in `packages/parser/src/utils/url-utils.ts`) strips any pre-existing `<base>` tag emitted by older templates or third-party plugins, then injects exactly one at the canonical position right after ``. The deploy shape is decided in one place; templates don't need to know about it. ### 📂 Fix: Robust offline asset path resolution Offline builds (`--offline`) could previously suffix arbitrary non-markdown asset files (e.g. PDFs, images, JSON files in subdirectories) with `/index.html`, breaking downloads and images. **The fix:** the URL normalizer now uses a robust, non-destructive check to verify if a path carries a filename with a dot (indicating an asset file), ensuring only targeted files (`.md`, `.html`, etc.) are processed, leaving other file extensions untouched. ### 🧰 Improved consumer simulation workflow Testing the documentation generator monorepo changes against consumer projects is now seamless: - **The fix:** the local simulation engine (`tools/sim.mjs`) has been optimized with `--source` specification and support for the `--doctor` mode to run simulated consumer checks. - **Wired commands:** added `dev:sim`, `build:sim`, and `doctor:sim` commands directly to `docs/package.json` utilizing the monorepo's `sim.mjs` wrapper with `--regen-tars` and `--skip-monorepo-build` flags. ### 🧹 Noisy CLI environment warnings silenced Running `npm` or `npx` commands spawned from within a `pnpm` runner could leak internal `pnpm` configurations into the environment, causing npm to output annoying warnings about "Unknown env config". **The fix:** the spawning wrappers now sanitize the environment by stripping `npm_config_npm_globalconfig`, `npm_config_verify_deps_before_run`, and `npm_config__jsr_registry` from `process.env` prior to executing subcommands. ### 🎨 Favicon fallback to prevent 404 console errors Web browsers automatically request `/favicon.ico` at the root of a domain. If the site had no favicon configured, this led to a 404 response in the browser console. **The fix:** the page generator and 404 template now automatically fall back to the default `assets/favicon.ico` when `config.favicon` is not defined in the workspace config. ### 📊 Enhanced prep pipeline and TUI summaries The monorepo development pipeline TUI has been polished: - **Terminal cursor-up rewriting:** the test runner status now correctly updates the `[ WAIT ]` line to `[ DONE ]` or `[ FAIL ]` in-place, eliminating duplicate output lines in standard terminal emulators. - **Accurate time and verdict summary:** at the very end of the prep execution, a concise 2-3 line summary reports the total elapsed time, success status, and a list of failed sections. ### 📦 Upgrade ```bash "upgrade" npx @docmd/core@0.8.16 build ``` No config changes required. If you previously set `"base": "/"` as a workaround for `v0.8.15`, you can remove it — the dev server now adapts automatically. --- ## [docmd v0.8.2 - Patch Release](https://docs.docmd.io/release-notes/0-8-2/) --- title: "docmd v0.8.2 - Patch Release" description: "Patched dependency protocol errors and updated release automation." --- 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 Notes](./0-8-1.md). --- ## [docmd v0.8.3 - Workspaces & Enhanced Security](https://docs.docmd.io/release-notes/0-8-3/) --- title: "docmd v0.8.3 - Workspaces & Enhanced Security" description: "Introduced the new Workspace architecture with configuration cascading, a premium Project Switcher, and major security hardening." --- 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. #### 🛡️ 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 reliable 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. --- ## [v0.8.4 - Deployer & Security](https://docs.docmd.io/release-notes/0-8-4/) --- title: "v0.8.4 - Deployer & Security" description: "Release notes for docmd v0.8.4 - modular deployer package, markdown line break control, security hardening, and stability fixes." date: "2026-05-18" --- ### ✨ 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: ```bash 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. ```json { "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 --- ## [v0.8.5 - Semantic Search Alpha & SEO Enhancements](https://docs.docmd.io/release-notes/0-8-5/) --- title: "v0.8.5 - Semantic Search Alpha & SEO Enhancements" description: "Release notes for docmd v0.8.5 - semantic search alpha preview, SEO plugin robots.txt auto-generation, Mermaid C4Context fix, and config upgrade CLI." date: "2026-05-31" --- ### ✨ 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: ```json { "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. **Documentation** - https://docs.docmd.io/plugins/search/#semantic-search-alpha-preview > **Note:** This is an alpha preview. Multilingual models are available, but broader testing and optimisation are still ongoing. ## Introducing Offline Semantic Search Engine (docmd-search) We're excited to introduce **docmd-search**. ```bash 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 ```json { "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. ```bash 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 --- ## [v0.8.6 - AI-First Integration, MCP & Docker](https://docs.docmd.io/release-notes/0-8-6/) --- title: "v0.8.6 - AI-First Integration, MCP & Docker" description: "Release notes for docmd v0.8.6 - native MCP Server, modular Agent Skills, official Docker image, CJK search tokenization, Copy Context widgets, and TOC improvements." date: "2026-06-05" --- ### ✨ 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 tokenizer 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: ```bash 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`](https://github.com/docmd-io/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`): ```bash # Pull and run with demo site docker pull ghcr.io/docmd-io/docmd:0.8.6 docker run -p 3000:3000 ghcr.io/docmd-io/docmd:0.8.6 # Build your docs docker run -v $(pwd)/docs:/docs -v $(pwd)/site:/site ghcr.io/docmd-io/docmd:0.8.6 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 tokenizer for CJK, Thai, Lao, Khmer, Burmese, and Tibetan scripts in MiniSearch. 13. **TOC**: Added support for H1 headings in the table of contents with proper anchor links and styling. 14. **TOC**: Implemented independent scrolling for the TOC sidebar with `max-height` constraints to prevent footer overlap. 15. **TOC**: Added automatic centring of active TOC items during page scroll with debounced smooth scrolling. 16. **TOC**: Extended scroll spy to observe H1 headings alongside H2-H4. 17. **Parser**: Updated heading anchor injection to include H1 headings for permalink icons. 18. **UI**: Fixed footer rendering issues caused by TOC overflow on pages with many headings. 19. **Search**: Fixed confidence percentage calculation in docmd-search 0.1.0-alpha.1 to prevent scores exceeding 100%. 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 --- ## [v0.8.7 - Custom Template Plugin API](https://docs.docmd.io/release-notes/0-8-7/) --- title: "v0.8.7 - Custom Template Plugin API" description: "Release notes for docmd v0.8.7 - the new Custom Template Plugin API with Summer template preview, opt-in cookie consent dialog, site-wide announcement banner, asset priority system, and 0.8.6 Docker :latest tag fix." date: "2026-06-20" --- 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 ``` ```js // 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](https://docs.docmd.io/theming/templates) ### ☀️ Summer — the first official template A bright, airy layout with a top search bar, soft halo accents, and a denser card grid. ```bash 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. ```json { "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. ```json { "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 | | Quick-start crashed on empty `/docs` in Docker | Entrypoint seeds `/docs` from the bundled template when empty | | 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 `` from `generateMetaTags` injected live script into every page. New `sanitizeHeadInjection()` in `@docmd/utils` strips `