/src/CLAUDE.md
CLAUDE.md at /src/CLAUDE.md
Path: src/
Source Code Rules
Components
All components are Preact
.tsx— there are no.astrofiles. Pages, layouts, and component overrides are all written as Preact function components.Default to server-rendered Preact (no
client:*directive) — emits zero JS for static markup.Promote a component to a client island only when it needs interactivity. zfb hydration is opt-in — islands are wired by direct
<Island>wrapping (no central registry file).Island wiring locations:
pages/(AiChatModal, ClientRouterBootstrap, DesignTokenPanelBootstrap, ImageEnlarge);lib/ _ body- end- islands. tsx pages/(ThemeToggle — imported fromlib/ _ header- with- defaults. tsx @takazudo/, SidebarToggle);zudo- doc/ theme- toggle pages/(SidebarTree); Toc and MobileToc are mounted fromlib/ _ sidebar- with- defaults. tsx @takazudo/viazudo- doc/ toc pages/(tocOverride/mobileTocOverride).lib/ _ doc- page- shell. tsx Current client islands:
sidebar-toggle.tsx,sidebar-tree.tsx,doc-history.tsx,image-enlarge.tsx,ai-chat-modal.tsx; the zdtp panel self-mounts viaconfigurePanel()and needs no Island wrapper. ThemeToggle, Toc, and MobileToc come from the@takazudo/zudo-docpackage — their npm-dist"use client"modules are scanned by zfb >= 0.1.0-next.39 (zfb#999/#1001), so no local scanner-visible shims exist (re-adding one creates an island marker-name collision).Content typography components (
src/): server-rendered Preact functions that override HTML elements emitted by MDX via thecomponents/ content/ <Content components={...} />mapping inpages/. Includes: headings (h2-h4), paragraph, link, strong, blockquote, lists (ul/ol), table._ mdx- components. ts
Design Token System
Uses a 16-color palette system.
Three-Tier Color Strategy
Tier 1 — Palette (injected by ColorSchemeProvider on :root):
--zd-bg,--zd-fg,--zd-sel-bg,--zd-sel-fg,--zd-cursor--zd-0through--zd-15(16 palette slots)
Tier 2 — Semantic tokens (in global.css @theme, resolved per scheme):
Palette access:
p0–p15→bg-p0,text-p8,border-p1, etc.Base:
bg,fg→bg-bg,text-fgUI:
surface,muted,accent,accent-hover,sel-bg,sel-fgContent:
code-bg,code-fg,success,danger,warning,info
Tier 3 — Component tokens (scoped to specific components):
Content:
.zd-contentdirect element styling in the shared@takazudo/(imported byzudo- doc/ content. css global.css; consumes Tier 2 tokens the project defines)
Each tier only references the tier above it.
Color Rules
NEVER use Tailwind default colors (
bg-gray-500,text-blue-600) — they are reset toinitialNEVER use hardcoded color values (
rgba(),#hex,rgb()) — use semantic tokens orcolor-mix()with tokensALWAYS use project tokens:
text-fg,bg-surface,border-muted,text-accent, etc.Prefer semantic tokens (
text-accent,bg-code-bg,text-danger) for standard UIUse palette tokens (
p0–p15) only when no semantic token fitsFor overlays/backdrops: use
bg-overlay/{opacity}(e.g.,bg-overlay/50) orcolor-mix(in oklch, var(--color-overlay) 50%, transparent)in CSSFor highlights (search, find-in-page): use
color-mix()withvar(--color-warning)at varying opacity levelsAcceptable exceptions: CSS fallback values (
var(--color-fg, #fff)), color manipulation code (e.g., color-tweak-panel), intentional theme-independent colors (e.g., white iframe canvas with a comment explaining why)
Changing Scheme
Edit
colorSchemeinsrc/config/ settings. ts Available: Dracula, Catppuccin Mocha, Nord, TokyoNight, Gruvbox Dark, Atom One Dark
Add schemes in
src/(22 color props + an optional, vestigialconfig/ color- schemes. ts shikiTheme— no effect on rendering; highlighting is syntect's, configured viacodeHighlightinzfb.config.ts)ColorReftype:background,foreground,cursor,selectionBg,selectionFg, and semantic overrides acceptnumber | string— number = palette index, string = direct color
Design Token Panel (zdtp)
Enabled via
designTokenPanel: truein settingsImplemented by the external
@takazudo/zdtp(zdtp) package; wired viaconfigurePanel(designTokenPanelConfig)insrc/; self-mounts as a side-effect — no Preact island registration neededlib/ design- token- panel- bootstrap. ts Interactive tabbed panel for live editing of spacing, font, size, and color tokens; includes JSON export/import workflow for AI-assisted token round-trips
The header trigger button dispatches
toggle-design-token-panelonwindow; zdtp listens for this event nativelyStorage prefix is
zudo-doc-tweak. The installed zdtp persists the unified tweak envelope underzudo-doc-tweak-state-v3(current) and auto-migrates the legacyzudo-doc-tweak-state-v2andzudo-doc-tweak-state(v1) keys into it on first load. The prefix is set viastoragePrefixinsrc/and is guaranteed not to change — existing user saves carry over automatically. Toggling light/dark does NOT delete saved tweaks:config/ design- token- panel- config. ts ThemeToggle(packages/) dispatcheszudo- doc/ src/ theme- toggle/ color- scheme- sync. ts color-scheme-changed, and zdtp's own listener clears applied inline styles and re-seeds the color slice from the newly active scheme while preserving the persisted envelope. The host must NOT reach into zdtp's private storage keys (an earlierapplyColorSchemewiped v1/v2 on every toggle — stale after zdtp moved to v3, and a contradiction of this carry-over guarantee; removed in #2037)
Three-Tier Font-Size Strategy
Uses the same three-tier approach as colors: abstract scale → semantic roles → component usage.
Tier 1 — Abstract scale (--text-scale-* in :root, NOT @theme):
Raw size values only:
2xs(12px),xs(14px),sm(16px),md(19.2px),lg(22.4px),xl(48px),2xl(60px)Kept in
:rootintentionally — avoids generating Tailwindtext-scale-*utility classes that would bypass the semantic layerNEVER use scale tokens directly in components — they exist only as a single source of truth for Tier 2
Tier 2 — Semantic tokens (--text-* in @theme, reference Tier 1):
micro(2xs/12px),caption(xs/14px),small(sm/16px),body(md/19.2px),title(lg/22.4px),heading(xl/48px),display(2xl/60px)Each is a pure
var(--text-scale-*)reference — Tier 2 carries the role, Tier 1 carries the value. The Design Token Panel models this exactly: the Font tab's role tier is areferencesTier: "font-scale"tier (dropdowns picking a scale step), mirroring the Color tab's semantic→palette tier. Editing a scale step propagates to every role live.Use these via Tailwind classes:
text-body,text-caption,text-micro,text-heading, etc.Name roles by their role, broadly enough to cover every usage (
titlecovers h2 / card / modal / section headings).subheadingwas renamed totitlebecause its name implied a narrower scope than its actual broad use. A role used in only one place should instead be a scoped Tier 3 token.
Tier 3 — Component usage (Tailwind classes in markup):
Components consume Tier 2 tokens:
<p class="text-body">,<h1 class="text-heading">.zd-contenttypography (shipped in@takazudo/, imported byzudo- doc/ content. css global.css) also references Tier 2 tokensFor a genuinely component-specific size that should not become a global role, add a scoped CSS custom property on the component (e.g.
--_card-amount: var(--text-scale-2xl)) referencing Tier 1/Tier 2 — do NOT widen a Tier 2 role to fit one component.
To add a new font size: add the raw value to Tier 1, then create a semantic token in Tier 2 that references it. Keep the panel in sync by adding the role→scale mapping in FONT_ROLE_TO_SCALE (design-token-panel-config.ts).
Two-Tier Size Strategy
Element dimensions (icons, toggles, etc.) follow a two-tier approach:
Tier 1 — Semantic tokens (in global.css @theme): shared design decisions with meaningful names.
Icon sizes:
icon-xs(12px),icon-sm(16px),icon-md(20px),icon-lg(24px)Usage:
w-icon-sm h-icon-sm,w-icon-md h-icon-md, etc.Add new tokens only when a size is used in 2+ unrelated components with the same semantic role
Tier 2 — Arbitrary values: one-off component dimensions that don't recur.
Example:
w-[1.575rem]for a breadcrumb home icon,h-[3rem]for a toggle button heightKeep as arbitrary values until the pattern recurs enough to justify a token
Rules:
No abstract numeric scale (no
size-4,size-8) — semantic names onlyTokenize when 2+ components share the same size for the same purpose (e.g., "standard icon")
Keep arbitrary values for layout dimensions, modal sizes, and component-specific one-offs
Z-index Tooling (gen-z-index)
The @theme z-index block in src/ is code-generated from the single source of truth in src/. The tooling that does this now ships as a package bin from @takazudo/zudo-doc (S9b #2334):
Source of truth (project-side):
src/— definesconfig/ z- index- tokens. ts Z_INDEX_TIERS. Edit here; never hand-edit the generated@themeblock.Generator bin (package-side):
gen-z-index— provided by@takazudo/zudo-doc. Readssrc/and writes theconfig/ z- index- tokens. ts GENERATED:Z_INDEX_BEGIN…ENDblock insrc/.styles/ global. css Scripts:
pnpm gen:z-index(rewrite) ·pnpm check:z-index(drift check, used by b4push).
CSS & Components
Before writing or editing CSS, Tailwind classes, color tokens, or component markup, invoke
/to load project-specific ruleszudo- doc- design- system Tailwind v4: imports
tailwindcss/preflight+tailwindcss/utilities(no default theme)@themehas--color-*: initial;at the top — project tight-token guardrail: wipes all Tailwind default color tokens so only project-defined tokens are available. The upstream split-import fix (zfb#159 / 9e37551) shipped in f68a9ba and eliminated the original leak cause; the reset is retained as an explicit design rule per the "NEVER use Tailwind default colors" policy. Do NOT remove.Content typography: component-first approach — major HTML elements (h2-h4, p, a, strong, blockquote, ul, ol, table) are overridden via Preact components in
src/registered throughcomponents/ content/ component-map.ts. Minor elements (li, th/td, code, pre, hr, img, h5/h6, dt/dd, etc.) and structural rules (flow-space, consecutive heading tightening, hash-links) plus the admonitions live in.zd-contentin the package-shipped@takazudo/(source:zudo- doc/ content. css packages/), imported byzudo- doc/ src/ content. css global.css. This is the single source of truth for content rendering — both this showcase and everycreate-zudo-docproject@importit, so editcontent.cssthere, not per-projectglobal.css(zudolab/zudo-doc#2188).global.csskeeps only@themetokens, feature styles, and slots.Component-first strategy: always use Tailwind utility classes directly in component markup — never create CSS module files or custom CSS class names. The component itself is the abstraction.
Tight token strategy: prefer existing spacing (
hsp-*,vsp-*), typography (text-caption,text-small, etc.), and color tokens. Avoid arbitrary values (text-[0.8rem],py-[0.35rem]) when an existing token is close enough.