Publish a Documentation Site
Documentation that only renders to HTML serves humans well and
agents poorly: an agent fetching a page gets markup it has to strip
before it can read the words. fit-doc builds a static
site where every HTML page ships with a co-located
index.md of the same content, so a human opens the page
and an agent fetches the markdown — one source, two readers. You
write plain markdown with YAML front matter;
fit-doc produces directory-style URLs, a table of
contents, breadcrumbs, and the metadata files that make a site
discoverable.
Prerequisites
- Node.js 22+
-
A source directory with at least an
index.template.htmland one.mdfile
fit-doc runs through npx, so there is
nothing to install globally:
npx fit-doc build --src=docs --out=dist
1. Lay out the source directory
A site is a directory of markdown pages plus one Mustache template that wraps every page. Only two files are required.
| File / Directory | Required | Purpose |
|---|---|---|
index.template.html |
yes | Mustache template applied to every page |
*.md |
yes | Pages with YAML front matter |
assets/ |
no | Static files copied verbatim to the output |
CNAME |
no | Custom domain — also used to derive the base URL |
llms.txt |
no | Curated index for agents, augmented at build |
robots.txt |
no | Copied verbatim to the output |
Files named CLAUDE.md, SKILL.md, and the
assets/ directory are never rendered as pages.
2. Write a page
Each page is a markdown file with YAML front matter.
title and description are the two fields
you will set on almost every page:
---
title: Getting Started
description: Install the tool and run your first build.
---
## Install
Run the build command and open the output.
Body headings start at ##. The title from
front matter becomes the page's <h1>, so a
manual # Heading in the body produces a duplicate.
3. Wrap pages in a template
The template is plain HTML with Mustache placeholders.
fit-doc fills it once per page. A minimal template
needs the title and the rendered content:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
<meta name="description" content="{{description}}" />
</head>
<body>
<main class="layout-{{layout}}">
<h1>{{title}}</h1>
{{{content}}}
</main>
</body>
</html>
Use the triple-stache {{{content}}} so the rendered
markdown is inserted as HTML rather than escaped. The template also
receives toc, breadcrumbs,
canonicalUrl, and the hero fields when a page declares
them in front matter.
4. Build the site
npx fit-doc build --src=docs --out=dist
fit-doc reports each page it writes:
Building documentation...
✓ guide/index.html
✓ index.html
Documentation build complete!
Every markdown file becomes a directory containing
index.html, which gives clean directory-style URLs:
| Source | Output URL |
|---|---|
index.md |
/ |
about/index.md |
/about/ |
docs/guide.md |
/docs/guide/ |
Alongside each index.html, fit-doc writes
a co-located index.md with the same rendered content,
so an agent can fetch the markdown of any page by appending
index.md to its URL.
Links between markdown files are rewritten to match. A
[guide](guide.md) in the source becomes
href="guide/" in the output, so you author
links against the files you can see and the build resolves them to
published paths.
5. Preview with live reload
While writing, serve the site locally and rebuild on every change:
npx fit-doc serve --src=docs --watch --port=3000
The server builds once, then watches the source directory and
rebuilds when a file changes. Drop --watch to serve a
static build without rebuilding.
6. Add a base URL for discoverability
A base URL lets fit-doc emit absolute links in the
metadata files. Pass it explicitly, or drop a
CNAME file in the source directory and
fit-doc derives https://{cname}/ from it:
npx fit-doc build --src=docs --out=dist --base-url=https://example.com
With a base URL available, the build adds:
-
sitemap.xml— every page listed by absolute URL, sorted by path. -
Canonical links — each page's
canonicalUrltemplate variable resolves to its full address. -
llms.txtaugmentation — if you ship a curatedllms.txt,fit-doccopies it to the output and appends a markdown link to every page, grouped by URL prefix (top-level pages under## Products,/docs/pages under## Documentation, the rest under## Optional).
Link cards between pages
A collection page can link to its children without hand-writing
anchors. A content-partial marker pulls the target page's
title and description at build time. The
marker is an HTML comment of the form
part:TYPE:PATH wrapped in <!-- and
-->, where TYPE is card or
link and PATH is the target page's
path relative to the current page's directory.
A card marker pointing at a sibling page named
about resolves to a card linking to
about/, with the target's title as the card heading
and its description as the card text. A link marker
resolves to a plain inline anchor instead. Because the path is
relative, ../sibling reaches across the tree. The build
fails if the target page does not exist, which keeps internal
navigation honest.
Verify
-
npx fit-doc build --src=docs --out=distexits zero and reports each page. -
dist/index.htmlexists anddist/index.mdholds the same content. -
A
[link](other.md)in source renders ashref="other/"in the output. -
Adding
--base-urlproducesdist/sitemap.xmlwith absolute page URLs. -
A
cardpartial marker renders a card with the target page's title and description.
What's next
Give Agents and Humans the Same Interface
Capabilities that work on every surface — one presenter, one contract, and one formatter shared between CLI and web, with no separate integrations.
Render Templates with Project Overrides
Ship default templates with a package and let each project override any one of them — two-tier Mustache resolution that keeps generated output consistent across surfaces.