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 4.7.0 documentation host with MDX, Wind CSS, and native zudo-react islands (zudo-doc 7.1.0). 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 4.7.0 — documentation build framework; import configuration helpers from @takazudo/zfb/config

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

  • Wind — the host utility CSS engine; zudo-doc registers its Wind manifest automatically. Keep @layer zw-reset, zd-flow; and the public theme-before-feature CSS import order in src/styles/global.css. Token overrides belong in ordinary :root; do not add Tailwind directives or scan package dist/ files.

  • zudo-react — native host JSX and interactive islands; extend @takazudo/zudo-doc/tsconfig.base.json without React/Preact JSX aliases. The panel owns its separate Preact tree; never pass its VNodes into native host JSX or Island JSON props.

  • 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 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/

The docs dev scripts use scripts/dev-zfb.mjs to select ZFB's supported eager startup (ZFB_DEV_BOOT_LAZY=0). On 4.3.1, cold-lazy route discovery can produce incompatible native island identities during SPA navigation. Use dev:zfb (or dev:zfb:network) so the real server and current-host CI exercise the same mode; keep transport identity checks enabled. Retain this workaround on 4.7.0: the 4.5.2 ready-banner fix, the 4.5.3 include-parsing fix, the 4.5.4 islands build-identity change (which keys island bytes to the resolved browser graph), the 4.6.0 shadow-staging and Windows path fixes and the 4.7.0 Rolldown bundler switch do not claim cold-lazy transport identity safety. The packed current-host dev probe also passed with ZFB_DEV_BOOT_LAZY=1 on 4.7.0, but that probe was not shown to catch the original 4.3.1 failure, so it is not proof the workaround can go.

Key Directories

zfb.config.ts             # THE one config file — zudoDoc({ ...only fields you chose })
pages/
├── index.tsx             # package home re-export + local island scanner edge
└── docs/[[...slug]].tsx  # retained native doc-route stub (explicit host ownership)
  [locale]/docs/[[...slug]].tsx  # same, for non-default locales
src/
├── chrome-bindings.tsx   # typed native panel bootstrap boundary
├── 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.

The local DesignTokenPanelBootstrap boundary preserves early header clicks across native SPA swaps in zudo-doc 7.x. src/panel-bootstrap.tsx queues toggle parity between zfb:before-swap and incoming scope activation, then calls the public bootstrap controller with the native scope's abort signal and replays at most one intent. zudo-doc 7 limits its loading overlay to the content area, so the header trigger stays clickable while a navigation is still fetching (before zfb:before-swap); such a click toggles the live outgoing host and its state must survive the swap or a superseding navigation. Package code still owns lazy loading, cancellation, configuration and the opaque panel runtime. Keep direct route imports of the binding module: the virtual host-callables channel alone does not guarantee static island discovery. First-load, pending-navigation and incoming-unhydrated clicks are covered by the current-host probe.

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 the current ZFB/zudo-doc family. The native host does not render with Preact or require a shared host/panel Preact installation. The panel retains its own runtime dependency and DOM ownership. Treat a version or peer mismatch as a failed consumer check and resolve the boundary before claiming validation.

The informational consumer-smoke job in .github/workflows/ci.yml runs separately named current-host and legacy checks. Current-host checks repeat the packed-panel override, build the scratch doc, serve its static output, and use 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. Current-host remount coverage also exercises real SPA navigation and panel persistence. The retained legacy remount regression uses the self-contained ZFB 2.20.3 / zudo-doc 5.27.0 fixture in scripts/fixtures/legacy-doc/, not a copy of these migrated docs with only two packages repinned. Its shared Preact assertion applies only to that legacy host. Run scripts/verify-packed-remount-consumer.sh --host current or --host legacy (the default) to select the host explicitly. Legacy manifests remain templates until materialized outside the checkout; do not add old real package.json files to the dependency resolver's repository scan.

The scheduled .github/workflows/consumer-drift.yml workflow installs the latest zudo-doc for the consumer-manifest contract check, on the Node range that release declares in engines.node, so an upstream engine bump does not masquerade as manifest drift. 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 retain explicit host route ownership and local history/locale adaptations. Keep their native JSX, untranslated-page fallback, and existing URL/base-path behavior. Don't delete them.

  • Custom document-history bindings use the server DocHistoryBoundary. Keep server fallback markup outside finite JSON Island props; no host Preact VNodes may cross that boundary.

Enabled Features

  • search — Package-owned full-text search UI and generated search-index.json (the v6 browser runtime does not call 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