/CLAUDE.md
CLAUDE.md at /CLAUDE.md
Path: CLAUDE.md
zudo-doc
Minimal documentation framework built with Astro 6, MDX, Tailwind CSS v4, and Preact islands.
Tech Stack
- Astro 6 — static site generator with Content Collections
- MDX — via
@astrojs/mdx, content directory configurable viadocsDirsetting - Tailwind CSS v4 — via
@tailwindcss/vite(not@astrojs/tailwind) - Preact — for interactive islands (TOC scroll spy, sidebar toggle, collapsible categories) and server-rendered content typography components, with compat mode for React API compatibility
- Shiki — built-in code highlighting, theme set from active color scheme
- TypeScript — strict mode via
astro/tsconfigs/ strict
Commands
pnpm dev— runs Astro dev server (port 4321) and doc-history-server (port 4322) concurrently viarun-p(predev kills stale processes)pnpm dev:astro— Astro dev server only (port 4321)pnpm dev:history— doc history API server only (port 4322)pnpm dev:stable— alternative build-then-serve dev mode (avoids HMR crashes on content file add/remove)pnpm dev:network— Astro dev server with--host 0.0.0.0for LAN accesspnpm build— static HTML export todist/pnpm check— Astro type checkingpnpm b4push— pre-push validation: format check → template drift check → tags audit (tags:audit --ci) → design token lint → typecheck → build → link check → E2E tests
Key Directories
packages/
├── ai-chat-worker/ # CF Worker for AI chat API
├── md-plugins/ # Shared remark/rehype plugins (link resolver, admonitions, etc.)
├── search-worker/ # CF Worker for search API
├── doc-history-server/ # Doc history REST API + CLI generator
└── create-zudo-doc/ # CLI scaffold tool
src/
├── components/ # Astro + Preact components
│ ├── admonitions/ # Note, Tip, Info, Warning, Danger
│ └── content/ # MDX element overrides (server-rendered, no client JS)
├── config/ # Settings, color schemes
├── content/
│ ├── docs/ # English MDX content
│ └── docs-ja/ # Japanese MDX content (mirrors docs/)
├── hooks/ # Preact hooks (scroll spy)
├── layouts/ # Astro layouts (doc-layout)
├── pages/ # File-based routing
│ ├── docs/[...slug] # English doc routes
│ └── ja/docs/[...slug] # Japanese doc routes
└── styles/
└── global.css # Design tokens (@theme) & Tailwind config
Conventions
Components: Astro vs Preact
- Default to Astro components (
.astro) — zero JS, server-rendered - Use Preact islands (
client:load) only when client-side interactivity is needed - Preact runs in compat mode (
@astrojs/preactwithcompat: true), so components can use React-style imports and APIs - Current Preact islands:
toc.tsx,mobile-toc.tsx,sidebar-toggle.tsx,sidebar-tree.tsx,theme-toggle.tsx,doc-history.tsx,color-tweak-panel.tsx,color-tweak-export-modal.tsx - Content typography components (
src/): Preact function components (nocomponents/ content/ client:directive — server-rendered, zero JS) that override HTML elements in MDX via<Content components={...} />. Includes: headings (h2-h4), paragraph, link, strong, blockquote, lists (ul/ol), table.
Content Collections
- Schema defined in
src/(Zod validation)content. config. ts - Uses Astro 5
glob()loader with configurablebasedirectory from settings - Content directories:
docsDir(default:src/),content/ docs docsJaDir(default:src/)content/ docs- ja
Terminology: “Update docs”
When we say “update docs” or “update our doc,” it means updating the showcase documentation content in src/ (English) and src/ (Japanese). Since zudo-doc is a documentation framework, its own content directories serve as the default showcase. These are the pages visible when running pnpm dev.
i18n
- English (default):
/— content indocs/ . . . docsDir(default:src/)content/ docs - Japanese:
/— content inja/ docs/ . . . docsJaDir(default:src/)content/ docs- ja - Configured in
astro.config.tswithprefixDefaultLocale: false - Japanese docs should mirror the English directory structure
- Bilingual rule: When creating or updating any doc page, update both EN and JA versions. Keep code blocks identical — only translate prose.
- Exception: Pages with
generated: truein frontmatter do not require Japanese translations.
Writing Docs
Frontmatter Fields
Schema in src/. Required: title (string). Key optional fields:
| Field | Type | Description |
|---|---|---|
sidebar_position | number | Sort order within category (lower = higher). Always set this |
description | string | Subtitle below the title |
sidebar_label | string | Custom sidebar text (overrides title) |
tags | string[] | Cross-category grouping |
draft | boolean | Exclude from build entirely |
unlisted | boolean | Built but hidden from sidebar/nav |
generated | boolean | Build-time generated content (skip translation) |
hide_sidebar | boolean | Hide left sidebar |
hide_toc | boolean | Hide right-side TOC |
Content Rules
- No h1 in content: The frontmatter
titlerenders as the page h1. Start with## h2. - Always set
sidebar_position: Without it, pages sort alphabetically. - Kebab-case file names: Use
my-article.mdx, notmyArticle.mdx.
Admonitions
Available in all MDX files without imports (registered globally in doc page).
Directive syntax: :::note[Title] … :::
JSX syntax: <Note>, <Tip>, <Info>, <Warning>, <Danger> — each accepts optional title prop.
Linking Between Docs
Use relative file paths with .mdx extension:
[Link text](./sibling-page.mdx)
[Link text](../other-category/page.mdx#anchor)
Navigation Structure
Navigation is filesystem-driven. Directory structure becomes sidebar navigation.
- Pages ordered by
sidebar_position(ascending) - Category index pages (
index.mdx) control category position _category_.jsonfor category-level metadata (label, position, noPage)- Header nav defined in
src/viaconfig/ settings. ts headerNavwithcategoryMatch
Content Creation Workflow
- Create English
.mdxfile undersrc/withcontent/ docs/ titleandsidebar_position - Write content starting with
## h2headings (not# h1) - Create matching Japanese file under
src/content/ docs- ja/ - Keep code blocks and
<HtmlPreview>blocks identical — only translate prose - Run
pnpm format:mdthenpnpm buildto verify
Doc Skill (setup-doc-skill)
The doc-skill (scripts/) generates . and symlinks docs into it. It is gitignored — do NOT track the generated SKILL.md in git. Run pnpm setup:doc-skill to regenerate. To update the skill template, edit scripts/.
This script is also the source template copied to downstream projects by create-zudo-doc when the skillSymlinker feature is enabled.
Doc History Architecture
Document git history is handled by a standalone package @zudo-doc/doc-history-server (at packages/doc-history-server/). It is intentionally decoupled from the Astro build pipeline so that expensive git log --follow calls do not block the main build.
It runs in two modes:
- Server mode (local dev) — HTTP server on port 4322, started by
pnpm dev:history. The Astro integration atsrc/proxiesintegrations/ doc- history. ts /requests to it.doc- history/ * - CLI mode (CI) — batch-generates JSON files into
dist/doc-history/. Used by thebuild-historyCI job in parallel with the main Astro build.
SKIP_DOC_HISTORY env var
When SKIP_DOC_HISTORY=1 is set, the Astro integration skips inline history generation at build time. This is the default for the CI build-site job — history is generated by the separate build-history job and merged in at deploy time. For local pnpm build runs, leave it unset so history is embedded inline.
CI Pipeline
Production (main-deploy.yml) and PR (pr-checks.yml) workflows use parallel build jobs:
- build-site — shallow clone (
fetch-depth: 1),SKIP_DOC_HISTORY=1 pnpm build - build-history — full clone (
fetch-depth: 0),@zudo-doc/doc-history-server generate - deploy/preview — merges both artifacts, deploys to Cloudflare Pages
E2E tests run with full clone and inline doc-history generation (no SKIP_DOC_HISTORY).
Feature Change Checklist
When adding or removing a feature from zudo-doc, update the create-zudo-doc generator to stay in sync:
src/— Add/remove the setting fieldconfig/ settings. ts packages/— Add/remove the setting in generated outputcreate- zudo- doc/ src/ settings- gen. ts packages/— Create/update feature module with injectionscreate- zudo- doc/ src/ features/ <name>. ts packages/— Add/remove feature-specific filescreate- zudo- doc/ templates/ features/ <name>/ files/ packages/— Add/remove conditional imports/integrations if feature affects astro configcreate- zudo- doc/ src/ astro- config- gen. ts packages/— Add/remove dependencies increate- zudo- doc/ src/ scaffold. ts generatePackageJson()packages/— Update testscreate- zudo- doc/ src/ _ _ tests_ _ / scaffold. test. ts - Run
/to verify no drift remainsl- update- generator
Important: This checklist also applies to incremental improvements (CSS token migrations, icon sizing, spacing changes, etc.) — not just new features. If you change a file that has a template counterpart, update the template too. Run pnpm check:template-drift to verify (note: allowlisted files like global.css, header.astro, and doc-layout.astro are excluded from automated checks and need manual review).
Design Tokens & CSS
See src/ for design token system (three-tier color strategy, color rules, scheme configuration) and CSS conventions (component-first strategy, tight token strategy).