Skip to content

Documentation ​

Docs live next to the code they describe, so anyone (human or AI agent) working in a package finds its docs without leaving the folder, and one VitePress site assembles them.

Principles ​

  1. The markdown on disk is the main copy. Agents read files, not the built site. Every page must make sense as plain markdown; the site only adds rendering, navigation and checks.
  2. Point at code, don't copy it. What can be read from the code (examples, signatures, options) is included or checked at build time, never pasted.
  3. Hide by folder, not by flag. Where a page lives decides whether it can be public; a forgotten front matter key must not be enough to leak it.
  4. The build catches drift. Dead links, unknown symbols and examples that no longer type-check fail (or warn in) vp run build:docs.

The parts not built yet are specified on their own pages:

PageCoversStatus
Code referencestype-checked examples, included code, symbol links, embedded docsplanned
Visibilitypublic vs internal (dev/) docs, two buildsplanned
Sub-sitespackages with their own site, also mounted in the root siteplanned

Layout ​

packages/<pkg>/docs/
  *.md        handwritten docs (index.md, guides, …)
  api/        generated API reference, only where it pays off (gitignored, written by the build)
docs/         the site shell: home page and cross-cutting docs (guides, this section)

A package takes part in the site as soon as its docs/ folder contains any markdown. It is served at /<package directory name>/; the shell is served at /. Only @mrmt/vite and @mrmt/vite-ui get a generated docs/api/: it is written by the TypeDoc plugin during vp run build (Build system), so run the build once to get it. The other packages rely on their handwritten pages and on the JSDoc that ships in their .d.ts files.

Write links as relative paths to the .md file, e.g. [Lib](../../vite/docs/index.md) or [Testing](../testing.md#scaffold-integration-tests). They work in the file tree, on GitHub and for agents reading the sources without a built site, and on the site: the workspace helper resolves them from the real source file and maps them to site URLs. Don't use site-absolute links (/vite/lib): they break on disk.

Avoid linking to generated pages (docs/api/**) from handwritten docs you expect to read without building: they don't exist on a fresh checkout. On the site build they always do.

Conventions (all optional) ​

Nothing below is enforced. They keep things easy to navigate:

  • an index.md per package: what it is, when to use it, the entry points;
  • front matter title (otherwise the first heading is used) and, where the order matters, order (pages without one sort by file name);
  • one topic per file, named after the topic; a topic that grows gets a folder with an index.md (like this one).

This repository's docs/.vitepress/config.ts is written by hand. Other monorepos can scaffold the equivalent with Docs({ workspace: true }) (Documentation plugin).

How the site assembles the pages ​

docs/.vitepress/config.ts calls workspaceDocs() from @mrmt/vitepress-plugin-sidebar/workspace and spreads the result into the VitePress config. It:

  • discovers the workspace packages (npm and pnpm workspaces, through @manypkg/get-packages);
  • sets srcDir to the repository root and generates the rewrites that map packages/<pkg>/docs/** to /<pkg>/** (pages are read in place, nothing is copied);
  • builds srcExclude so READMEs, changelogs and sources don't become pages (VitePress cannot express "everything except these folders", so it lists what to leave out);
  • registers the markdown rule that turns relative .md links into site URLs;
  • adds a Packages nav dropdown and one sidebar per package.

The site task (vp run build:docs) depends on the packages' builds, because the config imports the built plugin and the API references are generated by the builds.

Dev server ​

vp run docs restarts VitePress (debounced) when a page is added or removed, or when an edit changes a title or order, so the sidebar stays current; body edits just hot-reload. Details and options (restart) are in the sidebar plugin docs.

The generated API pages are only refreshed by the package build (vp run build, or vp pack --watch in the package).