manni site
Every docs framework starts its site differently. Mintlify is mint dev,
Starlight is astro dev, MkDocs is mkdocs serve, and each picks its own
port. manni site finds the site, detects its framework from its files, and
runs that framework’s own command. One command per job works in every docs
repository manni detects.
manni site is not a document tool. It runs the site that every other domain
checks. manni a11y check crawls the site it serves, on the URL your
collection already names.
Four commands
Section titled “Four commands”| Command | Does |
|---|---|
manni site start [dir] | Runs the framework’s dev server, with hot reload, until Ctrl-C. |
manni site build [dir] | Runs the framework’s production build once. |
manni site preview [dir] | Runs build, then serves the output until Ctrl-C. It always builds first, so it never serves stale output. |
manni site annotate [dir] | Joins the graph’s pins and statements to the built pages, as data. See Show readers what is proven. |
There is no default subcommand. manni site alone prints usage and exits 2.
Each command prints one line on stderr before it runs anything. The line names
the framework, the directory and the exact command. After that the output is
the framework’s own.
A 30-second proof
Section titled “A 30-second proof”This repository’s site is Starlight, in docs/. Its manni.config.yaml sets
only site.annotate.after-build, and a collection whose url: is
http://127.0.0.1:4321/manni/. After manni graph publish, build, annotate and
serve the site:
$ manni site previewmanni: Starlight in docs/. Running npm run buildmanni: Starlight in docs/. Annotating docs/dist from docs/public/graph/chunks.json.docs/dist: 258 pages annotated. 4163 of 4202 pins placed, 39 listed on their page only. 2 blocks carry a verification.manni: Starlight in docs/. Running npm run preview -- --host 127.0.0.1 --port 4321The host and the port came from the collection url:. In a second terminal,
the accessibility check reads the same url: and crawls the served build with
no flags:
manni a11y checkCtrl-C stops the server, exit 0.
How the site is found
Section titled “How the site is found”- The directory you pass, as in
manni site start website. - Else
site.dirinmanni.config.yaml. - Else a search, where the first match wins. It looks in the config file’s
directory, or the working directory when there is no config. Then it looks
in that directory’s
docs/,website/andsite/.
In each directory the framework’s own files decide. A mint.json is Mintlify,
an @astrojs/starlight dependency is Starlight, and a mkdocs.yml is MkDocs.
There is no framework: key, because the files already say which framework it
is. A directory with two frameworks in it is an error, exit 2, which names
both and asks for an override.
Which command runs
Section titled “Which command runs”manni detects Mintlify, Fern, Starlight, Docusaurus, VitePress, Nextra, Fumadocs, Rspress, MkDocs, Zensical, Sphinx, Hugo, Jekyll and MadCap Flare. The framework table has each one’s marker, commands and default port.
- A Node framework runs the project’s own script when
package.jsonhas one, such asnpm run dev, because it carries the project’s flags. Without a script, it runs the framework’s binary through the package manager the project uses. - A Python tool runs under
uv runorpoetry runwhen the project has auv.lockorpoetry.lock. Jekyll runs underbundle exec. - A framework with no preview server of its own writes a static directory.
MkDocs, Zensical, Sphinx, Hugo, Jekyll and Flare are in this group.
previewserves that directory with a small server built into manni, bound to127.0.0.1.
Mintlify and Fern have no local build, so manni site build and
manni site preview stop with exit 2 there. manni site start works.
Flare is the reverse. It has no development server, so start exits 2, and
preview serves the last build. Check a MadCap Flare project
covers it.
The port comes from the collection
Section titled “The port comes from the collection”manni a11y check reads a collection’s url: as the place to start its crawl.
manni site start and manni site preview read the same url: for the port
and host to bind, so the two agree without being told:
collections: - name: site paths: ["docs/**/*.md"] url: http://127.0.0.1:4321/Only a local url: counts, on localhost, 127.0.0.1 or [::1]. A public
URL names the deployed host, not a port on your machine. --port and --host
win over the url:. With neither a flag nor a local url:, the framework’s
default port applies, and manni passes no port flag at all. When two collections name different local URLs, manni
warns and uses the framework’s default.
A framework manni does not detect
Section titled “A framework manni does not detect”Write the commands in manni.config.yaml. Each one is a whole command line,
run through the shell in the site’s directory:
site: dir: handbook commands: start: pnpm dev --port 4000 build: pnpm build preview: npx serve dist -l 4000A command you set replaces the detected one for that verb, and the others stay
detected. preview still runs build first. When every command a verb needs
is set, nothing is detected, so any framework works this way. --port and
--host do not apply to a command you wrote. Put the port in the command.