# create-zudo-doc

Scaffold a new [zudo-doc](https://zudo-doc.takazudomodular.com) documentation site in seconds. Generates a ready-to-run project powered by [zfb](https://github.com/zudolab/zudo-doc), MDX, Tailwind CSS v4, and Preact — with optional features (search, i18n, sidebar, doc history, design token panel, and more).

## Quick Start

```bash
# pnpm
pnpm create zudo-doc

# npm
npm create zudo-doc@latest

# yarn
yarn create zudo-doc

# bun
bunx create-zudo-doc
```

Running without arguments starts the **interactive mode**: the CLI prompts for project name, language, color scheme, and which optional features to enable, then scaffolds the project and optionally installs dependencies.

Release history is shipped as `CHANGELOG.md` in the npm package. The file is
generated from the repository's changelog MDX pages; edit those source pages
instead of editing the generated markdown directly.

## Non-Interactive Usage

Pass `--yes` to accept all defaults and skip prompts, or provide flags to pre-answer specific questions:

```bash
# All defaults, no prompts
pnpm create zudo-doc my-docs --yes

# Fully specified, non-interactive
pnpm create zudo-doc my-docs \
  --lang ja \
  --additional-langs en,de \
  --scheme "Default Dark" \
  --search \
  --pm pnpm \
  --install
```

### Destination paths

The positional argument is the **destination** — the directory to scaffold
into, not just a bare name. It may be a path (relative, `../`-prefixed, or
absolute), and its **last segment** becomes the project name written to the
generated `package.json`:

```bash
# Creates ./sub/ref-doc with the package name "ref-doc"
pnpm create zudo-doc sub/ref-doc --yes
```

Only that last segment has to satisfy the project-name grammar (starts with a
lowercase letter or digit; lowercase letters, digits, dots, underscores, and
hyphens only; 214 characters max) — the directories leading up to it are just a
path. `.`, `..`, and a filesystem root are rejected, because they name no last
segment to derive the project name from.

Use `--name` to override the derived name while the positional argument keeps
supplying the directory:

```bash
# Creates ./sub/My-Docs with the package name "ref-doc"
pnpm create zudo-doc sub/My-Docs --name ref-doc --yes
```

This makes side-by-side scaffolding straightforward — for example, comparing
two template versions by generating both into one scratch directory and
diffing them:

```bash
pnpm create zudo-doc@5.17.0 /tmp/tpl-check/v5.17 --yes
pnpm create zudo-doc@5.18.0 /tmp/tpl-check/v5.18 --yes
diff -r /tmp/tpl-check/v5.17 /tmp/tpl-check/v5.18
```

### Locales and translations

`--lang` selects the primary locale. Its pages use the unprefixed
`/docs/...` routes and `src/content/docs/`. Add any number of additional
locales, in the order shown by the language switcher, with
`--additional-langs <code,...>`:

```bash
pnpm create zudo-doc my-docs \
  --lang en \
  --additional-langs ja,de \
  --yes
```

An omitted or blank list creates a single-locale project. The same rule
applies to a preset that omits `additionalLangs`; an explicit non-empty list
is normalized to lowercase, validates each code for safe URL/path use, rejects
duplicates and the primary code, and creates `src/content/docs-<code>/` plus
the corresponding `/<code>/docs/...` routes. A legacy preset containing only
`i18n: true` keeps compatibility inference (`ja` for primary `en`, otherwise
`en`).

CLI locale flags replace the preset list rather than merging with it. An
explicit `--additional-langs` also enables i18n; if it overrides
`--no-i18n`, the CLI prints a warning so the precedence is visible.

The generated starter uses Japanese prose for `ja` and English placeholder
prose for every other additional locale. Translate those pages before
publishing. Labels are configuration-driven: the switcher uses each locale's
configured `label` and map order, so custom codes and labels are not tied to
hard-coded `JP` or `JA` links.

Built-in UI translations resolve in this order:

`requested locale → configured default locale → package English → raw UI-string key`

## Options

### Project basics

| Flag | Description | Default |
|------|-------------|---------|
| `[destination]` | Directory to scaffold into; may be a path whose last segment becomes the project name | prompted |
| `--name <name>` | Project name written to `package.json`; overrides the name derived from the destination | destination's last segment |
| `--lang <code>` | Default language: `en`, `ja`, `zh-cn`, `zh-tw`, `ko`, `es`, `fr`, `de`, `pt` | `en` |
| `--additional-langs <a,b>` | Ordered additional locale codes; implies i18n and replaces a preset list | none |
| `--pm <manager>` | Package manager: `pnpm`, `npm`, `yarn`, `bun` | detected |
| `--[no-]install` | Install dependencies after scaffolding | prompted |
| `-y, --yes` | Use defaults for all unspecified options, skip prompts | — |
| `-h, --help` | Show help | — |

### Color scheme

| Flag | Description |
|------|-------------|
| `--color-scheme-mode <mode>` | `single` (one fixed scheme) or `light-dark` (OS-aware) |
| `--scheme <name>` | Color scheme name when using `single` mode |
| `--light-scheme <name>` | Light scheme when using `light-dark` mode |
| `--dark-scheme <name>` | Dark scheme when using `light-dark` mode |
| `--default-mode <mode>` | `light` or `dark` — initial mode in `light-dark` |
| `--[no-]respect-system-preference` | Follow OS color scheme preference |

### Features

Each feature has a `--[no-]<flag>` form. Passing `--feature` enables it; `--no-feature` disables it; omitting the flag triggers the interactive prompt (or uses the default when `--yes` is set).

| Flag | Description | Default |
|------|-------------|---------|
| `--[no-]i18n` | Legacy multi-language toggle; with no explicit list, infers one additional locale | off |
| `--[no-]search` | Full-text search | on |
| `--[no-]sidebar-filter` | Real-time sidebar filter | on |
| `--[no-]image-enlarge` | Click-to-enlarge for oversized images | on |
| `--[no-]asset-viewer` | Viewer pages for files under `public/assets/` | on |
| `--[no-]tag-governance` | Vocabulary-aware tag audit + suggest scripts | off |
| `--[no-]claude-resources` | Auto-generate Claude Code docs from `.claude/` | off |
| `--[no-]codex-resources` | Auto-generate Codex docs from `.codex/` + `AGENTS.md` | off |
| `--[no-]claude-skills` | Ship zudo-doc Claude Code skills (design-system, translate, version-bump) | off |
| `--[no-]design-token-panel` | Interactive panel for tweaking spacing, font, color tokens | off |
| `--[no-]sidebar-resizer` | Draggable sidebar width handle | on |
| `--[no-]sidebar-toggle` | Show/hide desktop sidebar button | on |
| `--[no-]toc-toggle` | Show/hide the desktop table of contents (edge chevron, xl screens) | on |
| `--[no-]versioning` | Multi-version documentation support | off |
| `--[no-]doc-history` | Show per-page document edit history | on |
| `--[no-]body-foot-util` | Right-aligned strip below each doc (history trigger + GitHub source link) | off |
| `--[no-]llms-txt` | Generate `llms.txt` for LLM consumption | on |
| `--[no-]skill-symlinker` | Symlink documentation skills into `.claude/` | off |
| `--[no-]tauri` | Tauri desktop app — Mode 1 offline reader | off |
| `--[no-]tauri-dev` | Tauri dev wrapper — Mode 2 configurable dev wrapper | off |
| `--[no-]footer-nav-group` | Navigation links in the footer | off |
| `--[no-]dynamic-page-transition` | SPA-style page transition with history handling | on |
| `--[no-]footer-copyright` | Copyright notice in the footer | on |
| `--[no-]footer-taglist` | Grouped tag index in the footer (requires tag-governance) | off |
| `--[no-]changelog` | Changelog page | off |
| `--changelog-packages <a,b>` | Per-package changelog pages and a Changelog dropdown (implies `--changelog`) | none |

### Advanced

| Flag | Description |
|------|-------------|
| `--github-url <url>` | GitHub repository URL — drives header link and "View source" links |
| `--preset <path>` | Load all settings from a JSON file (use `-` for stdin) |

## Examples

```bash
# Japanese docs site with search and sidebar, using pnpm
pnpm create zudo-doc my-docs \
  --lang ja \
  --search \
  --sidebar-filter \
  --pm pnpm \
  --install \
  --yes

# Light/dark color scheme with the Default pairing
pnpm create zudo-doc my-docs \
  --color-scheme-mode light-dark \
  --light-scheme "Default Light" \
  --dark-scheme "Default Dark" \
  --default-mode dark \
  --yes

# Fully featured site from a preset file
pnpm create zudo-doc my-docs --preset ./my-preset.json --install

# Per-package changelog pages
pnpm create zudo-doc my-docs --changelog-packages core,cli --yes
```

## Programmatic API

```ts
import { createZudoDoc } from "create-zudo-doc";

await createZudoDoc({
  projectName: "my-docs",
  defaultLang: "en",
  additionalLangs: ["ja", "de"],
  colorSchemeMode: "single",
  singleScheme: "Default Dark",
  features: ["search", "sidebarFilter", "tagGovernance"],
  changelogPackages: ["core", "cli"],
  packageManager: "pnpm",
  install: true,
});
```

## Documentation

Full documentation at [zudo-doc.takazudomodular.com](https://zudo-doc.takazudomodular.com).

## License

MIT — see [LICENSE](./LICENSE).
