Programmatic API
2 minutes read
The package exposes two entry points today:
| Entry | Exports |
|---|---|
@velella/mizzen |
version. |
@velella/mizzen/contracts |
The frozen contract types, type-only. |
test/contracts-import.test.ts builds the package and imports each entry point the way a consumer does, so the table above is checked against the artifact.
Inside the repository, each stage is a function with typed input and output:
| Function | File | Returns |
|---|---|---|
build(options) |
src/pipeline/build.ts |
BuildResult: the output folder, every file written (sorted), and every diagnostic. |
buildModel(root) |
src/model/build.ts |
ModelResult: the complete site model plus diagnostics. It parses, renders Markdown, and builds navigation, but writes nothing. |
applyFacts({ site, root, sourceDir, dir? }) |
src/model/facts.ts |
ApplyFactsResult: the site with each derived fact's value at data[fact.name], plus diagnostics. buildModel calls it. |
loadConfig(root, options?) |
src/config/load.ts |
LoadConfigResult: a complete SiteConfig after defaults, plus diagnostics. |
loadRegistry(themeRoot) |
src/render/registry.ts |
ThemeRegistry: the theme manifest, layouts, chrome, and components. |
loadCodeConfig(root, options?) |
src/plugins/hooks.ts |
LoadedCode: the site's plugins and diagnostics. See Plugins. |
build() takes:
root: the site root, the folder that holdsmizzen.yml.out: the output folder, replaced as a whole. It must be outsidesource, or its first segment must start with_or., as in_site.themeRoot: the theme's root folder, which holdssrc/index.tsand thelayouts/,chrome/, andcomponents/folders.themeFiles: theme files to copy, as paths relative tothemeRoot; each lands underassets/theme/with its hash in the name.defaultLayout: the layout for a page that names none; without it such a page is an error.outputsDir: the folder outputs are read from; defaultsrc/outputs/.cache: reuse an unchanged build's output from the cache; off by default, andmizzen buildturns it on.cacheDir: the cache folder; default<root>/.mizzen/cache, and only used whencacheis true.workers: pages to render at once in worker threads; default1, which renders in this process.2or more starts that many workers, each loading the theme.
Every output runs first, in memory, and its files are checked: a path outside out is an error, and so is a path two outputs both write (the first one wins). Then the site is written to a staging folder beside out and swapped in only when complete. A site's own file wins over an output's file at the same path, with no diagnostic. Problems in content and theme come back as diagnostics; a throw means a bug, such as an output or layout that threw, and leaves out as it was.
import { build, type BuildResult } from "../src/pipeline/build.ts";
/** Builds a site and returns what was written. */
export function buildSite(root: string, out: string, themeRoot: string): Promise<BuildResult> {
return build({ root, out, themeRoot, defaultLayout: "doc" });
}
buildModel() is the API for a tool that reads the site without writing it, such as a linter or an MCP server. Its diagnostics are the same ones a build reports.