Installation
How to install and set up zudo-doc for local development.
Prerequisites
Node.js 22+ — required by zfb and the toolchain
pnpm — recommended package manager
Info
You can also use npm, yarn, or bun, but this guide uses pnpm for all examples.
Create a New Project
The fastest way to get started is with the create-zudo-doc CLI. It scaffolds a new project with an interactive setup wizard.
pnpm create zudo-docOr with other package managers:
npm create zudo-doc
yarn create zudo-doc
bunx create-zudo-docFor non-interactive usage (CI, automation, AI agents), use --yes to accept defaults or pass flags directly:
pnpm create zudo-doc my-docs --yes
pnpm create zudo-doc my-docs --lang ja --scheme "Default Dark" --no-i18n --pm pnpm --installSee the CLI reference for all available flags.
The CLI walks you through the following options:
Project Name
Enter a name for your project directory (default: my-docs).
Default Language
Choose the default language for your documentation site. Supported languages include English, Japanese, Chinese (Simplified/Traditional), Korean, Spanish, French, German, and Portuguese.
Color Scheme Mode
Choose how your site handles color schemes:
Light & Dark (toggle) — users can switch between light and dark themes. Uses the bundled
Default Light/Default Darkpair.Single scheme — one fixed color scheme for the entire site, either
Default LightorDefault Dark.
When using light/dark mode, you can also set the default mode (light or dark) and whether to respect the user's system color scheme preference.
zudo-doc ships exactly these two schemes, sharing one set of OKLCH ramps — there is no catalog of community or terminal presets to browse. The defaults are package-owned; a fresh scaffold has no color-scheme module. To customize the palette, create your own scheme module and pass it through the colorSchemes field of zudoDoc({ ... }) in zfb.config.ts (see the Color guide), then preview changes live with the Design Token Panel's Palette tab (see Color Scheme Preview).
Features
Use the interactive picker to choose optional modules for internationalization, search and sidebar tools, Claude resources and skills, design and navigation controls, versioning and document history, tags and changelogs, desktop wrappers, and indexing. Built-in full-text/word-match search, sidebar filtering, image enlarge, dynamic page transitions, and footer copyright are selected by default.
For the complete feature list, defaults, and non-interactive flags, see the CLI reference.
Package Manager
Choose your preferred package manager: pnpm (recommended), npm, yarn, or bun. After scaffolding, the CLI will ask whether to install dependencies for you.
Tip
The installer writes your choices into a single zfb.config.ts — a zudoDoc({ … }) call holding only the fields that differ from the defaults. You can change these settings at any time after project creation. See Configuration for the full field reference.
Alternative: Clone the Repository
You can also start by cloning the full repository directly:
git clone https://github.com/zudolab/zudo-doc.git my-docs
cd my-docs
pnpm installNote
Cloning the repository gives you the complete project including the documentation source and all features enabled. Use this approach if you want to explore the full codebase or contribute to zudo-doc itself.
Development
pnpm devThe zfb dev server starts on port 4321 with instant hot module replacement.
Warning
Make sure port 4321 is available. If another process is already using it, pnpm dev will fail with EADDRINUSE — kill the conflicting process and retry.
Build
pnpm buildThis generates static HTML in the dist/ directory. You can deploy it to any static hosting service.
Type Checking
pnpm checkRuns the project's TypeScript type checker in strict mode.
Danger
Never commit the dist/ directory to source control. It is already excluded via .gitignore.
Project Structure
A freshly scaffolded project is deliberately small — around a dozen files:
my-docs/
├── .gitignore # node_modules, dist, .zfb
├── .npmrc # trust-policy-exclude[]=undici-types@6.21.0
├── pnpm-workspace.yaml # minimumReleaseAge: 0 (disables pnpm 11's release-age gate)
├── CLAUDE.md # project notes for Claude Code
├── package.json # deps + dev/build/preview/check scripts
├── tsconfig.json # 5-line extends of the package base config
├── zfb.config.ts # the ONE config file — a zudoDoc({ … }) call
├── pages/
│ ├── index.tsx # home route (1-line re-export)
│ └── docs/
│ └── [[...slug]].tsx # doc-route stub (see the callout below)
└── src/
├── content/
│ └── docs/
│ └── getting-started/
│ ├── index.mdx
│ ├── installation.mdx
│ └── introduction.mdx
└── styles/
└── global.css # ~20-line @import chain + your token overrides | File | Purpose |
|---|---|
zfb.config.ts | Your entire configuration. Imports zudoDoc from @takazudo/ and passes the fields you chose; everything else falls back to a documented default. |
tsconfig.json | Extends @takazudo/; adds only include and the preact-compat paths. |
src/ | @imports the package's theme.css / content.css / features.css and leaves you a @theme { … } block for token overrides. |
src/ | Your documentation, authored as MDX. The scaffold seeds a few getting-started/ pages to replace. |
pages/, pages/docs/[[...slug]].tsx | Thin route stubs — see below. |
Why so little?
Everything a project used to copy into itself — the layout, header, sidebar, TOC, nav builders, URL helpers, color-scheme utilities, and the frontmatter schema — now ships from @takazudo/zudo-doc and is consumed straight from node_modules. Doc routes are injected by the package (packageOwnedRoutes defaults to true), so your pages/ directory carries only the two stubs below rather than a full set of layout files. A fresh project holds just what is genuinely its own: config, content, and a couple of route seams.
Why pages/index.tsx exists
The home route is a one-line re-export of the package-owned static index route:
export { default } from "@takazudo/zudo-doc/routes/index";A re-export works here because the static / route needs no build-time paths() extraction.
Why pages/docs/[[...slug]].tsx exists
Package route injection renders your doc pages at build time, but injected dynamic routes currently return 404 in zfb dev (pnpm dev). To keep the dev authoring loop working, a small self-contained stub ships that reconstructs the doc route from the package's sanctioned entrypoints (@takazudo/ + / + the virtual:zudo-doc-route-context module). It makes / return 200 in both zfb dev and zfb build.
This is the one interim file in the scaffold that will disappear once the upstream dev-render gap closes (follow-up #2667).
See the Writing Docs guide for how to create and organize your documentation pages, and Customizing zudo-doc for the ladder from a config tweak to full source control.