Zudo Token Panel
GitHub repository

Type to search...

to open search from anywhere

/CLAUDE.md

CLAUDE.md at /CLAUDE.md

Path: CLAUDE.md

Zudo Design Token Panel

Documentation site built with zudo-doc — a zfb-based documentation framework with MDX, Tailwind CSS v4, and Preact islands. This project is intentionally minimal: one config file (zfb.config.ts) plus markdown content — layout, chrome, and islands all ship from @takazudo/zudo-doc in node_modules.

Tech Stack

  • zfb — documentation build framework

  • MDX — content format, authored under src/content/

  • Tailwind CSS v4 — compiled by zfb's embedded Tailwind engine (no @tailwindcss/vite plugin, no tailwindcss dependency); src/styles/global.css imports tailwindcss/preflight + tailwindcss/utilities and zfb's internal resolver serves both

  • Preact — for interactive islands only (with compat mode for React API)

  • zfb semantic highlighting — native build-time fenced-code rendering plus lazy @takazudo/zfb-md-wasm for HtmlPreview; both emit hi-* classes resolved through --zd-syntax-* design tokens

  • @takazudo/zudo-doc — the package that owns everything: layout, chrome, islands, default @theme design tokens, and (via packageOwnedRoutes, on by default) the doc routes themselves

Commands

  • pnpm dev — runs the zfb dev server (port 4321) and the doc-history API server (port 4322) concurrently via run-p (pnpm dev:zfb / pnpm dev:history individually)

  • pnpm dev:network — same, but zfb binds --host 0.0.0.0 for LAN access (pnpm dev:zfb:network individually); the doc-history server stays loopback-only and LAN clients reach it through zfb's /doc-history/* dev proxy

  • Trusted networks only: this also serves your git doc-history — including UNPUBLISHED local commits — to anyone on the LAN via the /doc-history/* proxy

  • run-p swallows trailing args, so other zfb flags don't forward through pnpm dev — pass them directly instead: pnpm run dev:zfb -- <flags>

  • pnpm build — static HTML export to dist/

  • pnpm check — TypeScript type checking

  • pnpm preview — serve the built dist/

Key Directories

zfb.config.ts             # THE one config file — zudoDoc({ ...only fields you chose })
pages/
├── index.tsx             # 1-line re-export of the package home route
└── docs/[[...slug]].tsx  # self-contained doc-route stub (required for `pnpm dev`)
  [locale]/docs/[[...slug]].tsx  # same, for non-default locales
src/
├── chrome-bindings.tsx   # optional typed primary chrome / named header / MDX bindings
├── content/
│   └── docs/             # MDX content (this project's showcase docs)
│   └── docs-ja/         # Japanese MDX content (mirrors docs/)
└── styles/
    └── global.css        # @import chain + a token-override slot — that's it

Everything else — layout, header, sidebar, footer, doc chrome, islands, and the default design tokens — lives in node_modules/@takazudo/zudo-doc. For supported markup replacement, create src/chrome-bindings.tsx with defineChromeBindings, set chromeBindingsModule, and use the primary Header / Footer / Sidebar / Toc / Breadcrumb / DocPager slots or the named headerRightComponents registry. The generated default, locale, and doc-history route shapes already consume the same binding object; do not fork a route stub for presentational customization. npx zudo-doc eject <component> only copies source: heed its primary, nested-chrome, or content-layer remediation before expecting the copy to render. Settings you didn't set explicitly in zfb.config.ts use the package's documented defaults — hover zudoDoc's ZudoDocConfig argument in your editor to see every field and its @default.

zdtp ↔ zudo-doc relationship

The doc/ workspace intentionally consumes the pinned npm release of @takazudo/zdtp; never force-link it to packages/zdtp. The pin governs which panel build the site runs — the embedded panel widget and the three-site demo split below — not what the documentation prose may describe. Doc content is free to document main-branch panel behavior ahead of the pinned release; that split is stated publicly in the note at the top of getting-started/index.mdx, which this section cross-references rather than restates: read the two together as one rule, not two that can be read as contradicting each other.

This is a deliberate three-site split, kept separate because of the honesty problem tracked in #593: doc/ answers what can be installed from the pinned npm release, examples/minimal/ runs the workspace build as the smallest wiring that works, and playground/ runs the workspace build at full size, including the real vendored zudo-doc PanelConfig and prose pages. Do not make either workspace demo consume the pinned doc/ dependency, or make doc/ consume the workspace package, to make their versions appear consistent.

Use the root playground/ workspace to exercise unpublished panel changes in a real zfb consumer. Its default manifest covers the panel's control kinds, while ?manifest=zudo-doc uses the real zudo-doc PanelConfig vendored by scripts/vendor-consumer-manifest.mjs (the S17 vendor script). The generated file records the source @takazudo/zudo-doc version so drift is visible.

Verifying an unpublished panel in the real doc site

The committed doc/ workspace remains pinned to the published panel release. To inspect an unpublished panel build in the real zudo-doc consumer, run this from the repository root:

bash scripts/doc-with-local-panel.sh

The script builds and packs packages/zdtp, copies the doc source into a temporary directory, and installs that scratch site with a file override for the packed panel. It prints the local panel version, then runs the scratch site's pnpm dev; open the printed URL and activate the design-token-panel header trigger. The terminal output includes the exact local package version being served (the fixed window.zdtp API itself intentionally exposes only show, hide, and toggle). The temporary directory, workspace override, install lock, and generated build output are removed when the dev command exits. The committed doc/package.json and root lockfile are never modified.

The override belongs in the temporary pnpm-workspace.yaml rather than a package-level pnpm field because pnpm 11 no longer reads that package.json configuration. The script also verifies that the scratch site resolved the packed panel version and that the panel and zudo-doc share one Preact installation. A mismatch is a peer/bootstrap spike blocker: capture its logs in the PR and ship only the scheduled drift re-exam until the dependency boundary is resolved; do not force a package or lockfile change.

The informational consumer-smoke job in .github/workflows/ci.yml repeats the packed-panel override, builds the scratch doc, serves its static output, and uses Chromium to open one doc page, activate the header trigger, assert the real zudo-doc panel tabs are mounted, and reject console or page errors. The scheduled .github/workflows/consumer-drift.yml workflow installs the latest zudo-doc for the consumer-manifest contract check. Its five-example matrix is manual-dispatch-only and informational while those public examples still pin older panel APIs; failures open or update one deduplicated issue per job.

Content Conventions

Frontmatter

  • Required: title (string)

  • Optional: description, sidebar_position (number), category

  • Sidebar order is driven by sidebar_position

Admonitions

Available in all MDX files without imports, via directive syntax: :::note, :::tip, :::info, :::warning, :::danger, :::caution, :::details. Each accepts an optional bracketed title: :::note[Custom Title].

Docusaurus-style {title="..."} is NOT supported. MDX parses the braces as a JS expression, so it either fails the build with ReferenceError: title is not defined or is silently ignored. Always use the bracketed form.

Headings

Do NOT use h1 (#) in doc content — the page title from frontmatter is rendered as h1. Start content headings from h2 (##).

Built-in MDX components

@takazudo/zudo-doc ships a few globally-available MDX components — usable in any .mdx file with no import. The seeded getting-started/index.mdx already uses one:

  • <CategoryNav category="..." /> — a card-grid list of the pages in a docs category (this is the one seeded into getting-started/index.mdx).

  • <CategoryTreeNav category="..." /> — the same listing as a compact nested tree, better for deeper hierarchies.

  • <SiteTreeNavDemo /> — a full-site documentation tree (the MDX-available wrapper of the SiteTreeNav island).

Admonitions (above), tabbed content (<Tabs> / <TabItem>, <CodeGroup>), and block math (<MathBlock>) work the same way — no import. Full reference: https://zudo-doc.takazudomodular.com/docs/components/

i18n

  • English (default): /docs/... — content in src/content/docs/

  • Japanese: /ja/docs/... — content in src/content/docs-ja/

  • Japanese docs should mirror the English directory structure

  • Both pages/docs/[[...slug]].tsx and pages/[locale]/docs/[[...slug]].tsx are self-contained doc-route stubs shipped by the generator — required so pnpm dev doesn't 404 on doc pages (a zfb dev-mode limitation on package-injected dynamic routes). Don't delete them.

Enabled Features

  • search — Full-text search via Pagefind

  • claudeResources — Auto-generated docs for Claude Code resources

  • designTokenPanel — Interactive tabbed panel for tweaking spacing, font, size, and color tokens

  • sidebarResizer — Draggable sidebar width

  • sidebarToggle — Show/hide desktop sidebar

  • versioning — Multi-version documentation support

  • docHistory — Document edit history

  • llmsTxt — Generates llms.txt for LLM consumption

  • changelog — Per-version EN/JA pages under src/content/docs*/changelog/ are the source of truth; the docs build generates ../packages/zdtp/CHANGELOG.md from the English pages, so do not edit that package file directly

Revision History

CreatedUpdated