Inkpath turns a directory of Markdown files into a static website. It writes plain HTML and CSS. Pages without Mermaid diagrams contain no Inkpath JavaScript.
Install#
Inkpath requires Node.js 22.13 or newer.
pnpm add -D inkpath
Start with one file#
Create content/INDEX.md:
---
title: Engineering notes
description: Notes about systems I want to remember.
---
Write the home page here.
Directories become sections, while Markdown files become pages. Numeric filename prefixes control their default order without appearing in the generated URLs.
Preview while you write#
pnpm exec inkpath dev
The development server watches Markdown, configuration, and public files. A successful edit rebuilds the site and refreshes the browser; a failed build leaves the last valid output in place.
Measured performance#
On an Apple M4 Pro with Node.js 26.5.0, the deterministic 10,000-page benchmark measured a 2.28-second median clean build, a 6.25-millisecond body-only edit, and a 0.68-millisecond no-op rebuild. A separate validated 100,000-page body edit measured 10.22 milliseconds median and 14.14 milliseconds p95. The isolated persistent-engine worker peaked at 235 MiB RSS during the 10,000-page body edit. A representative ordinary page plus shared CSS transferred 4.0 KiB with gzip or 3.3 KiB with Brotli and contained no Inkpath JavaScript.
A reproducible 1,000-page persistent-development run measured 60.62 milliseconds median and 61.98 milliseconds p95 from source edit through watcher build completion. The benchmark report also records 10,000-page structural and clean-build validation samples.
Body and link edits to existing notes update the affected graph. Title and order edits write only affected documents but still rebuild site-wide navigation and rendering indexes. Route and draft-state changes, additions, deletions, renames, and coalesced multi-file Markdown saves reconstruct topology from cached page state, validate the complete link graph, and transactionally publish affected outputs. Configuration, public assets, direct content-asset events, and transitions that add the first or remove the last Mermaid or KaTeX page still use a complete validated build. The watcher uses a 55-millisecond quiet period for an isolated change, 75 milliseconds for a burst, and a 90-millisecond maximum wait; engine timings and browser reload are separate. The full Inkpath benchmark report includes reproducible commands, p95 results, target misses, and limitations. A separate pinned Hugo, MkDocs, Docusaurus, and Quartz comparison reports its defined native configurations without making a universal fastest-generator claim.
One source tree, one site graph#
Inkpath reads the content tree, resolves page relationships, validates references, and then writes the static site. Public files pass through unchanged.
flowchart TB accTitle: How Inkpath builds a site accDescr: Inkpath reads Markdown and public files, validates the content graph, and writes HTML, CSS, assets, and split Mermaid chunks when a page contains a diagram. source["Markdown and public files"] --> build["inkpath build"] build --> validate["Resolve routes, links, and assets"] validate --> site["Write site/"] site --> pages["HTML and CSS"] site --> diagrams["Hashed Mermaid chunks when needed"]
inkpath check walks the same content graph without writing the output directory, so it can catch a broken page or anchor in CI.[1]
The Mermaid entry file is small. The browser imports Mermaid only on a diagram page, then loads the chunk for the diagram type it encounters. Inkpath reuses versioned chunks between Markdown rebuilds.
Markdown and its output#
| Feature | What Inkpath writes |
|---|---|
| Navigation | Nested sections, breadcrumbs, contents, adjacent notes, and heading permalinks. |
| References | Validated relative links, backlinks on destination pages, and _inkpath/orphans.json. |
| Page metadata | Identifiers, dates, duration, difficulty, and tags from frontmatter. |
| Discovery | Canonical and Open Graph metadata, sitemap.xml, rss.xml, and atom.xml when site.url is set. |
| Rich Markdown | Footnotes, tables, highlighted code, callouts, Mermaid, and optional build-time KaTeX. |
| Browser assets | Content-hashed ESM chunks only on pages that contain Mermaid. |
Why the orphan report is separate
Navigation and content links answer different questions. A note can appear in a collection but still have no incoming Markdown link. Inkpath records that note in _inkpath/orphans.json.
Math without a browser runtime#
Set markdown.math: true in inkpath.yaml. Inkpath renders inline math such as and display math during the build:
KaTeX CSS and fonts are copied only when a page contains math.
Markdown support#
- Headings, tables, nested lists, fenced code blocks, and syntax highlighting
- Footnotes, custom or collapsible callouts, Mermaid diagrams, and optional KaTeX
- Arbitrarily nested sections with breadcrumbs and adjacent-page navigation
- Relative-link, heading, image, and local-file validation
- Backlinks, an orphan report, feeds, a sitemap, and social metadata
Raw HTML and MDX aren't executed.
Build#
pnpm exec inkpath check
pnpm exec inkpath build
The build writes a directory of static files that can be served by GitHub Pages, Cloudflare Pages, Netlify, an object store, or a regular web server.
Carry one HTML file#
Use the same source tree to create a self-contained document that opens directly from disk:
pnpm exec inkpath single
pnpm exec inkpath single ./notes --output handbook.html
Inkpath combines the home page, sections, and notes in navigation order. Local styles, images, downloadable files, KaTeX resources, and Mermaid runtime code are embedded in the HTML. Ordinary external links remain external, while remote page resources are rejected so the file stays portable. The default output is site.html, and it does not require a neighboring asset directory or a web server.
Footnotes
Inkpath rejects missing Markdown targets, headings, images, and local files before replacing the previous successful output. ↩︎