zudo-doc
GitHub repository

Type to search...

to open search from anywhere

/src/CLAUDE.md

CLAUDE.md at /src/CLAUDE.md

Path: src/CLAUDE.md

Source Code Rules

Components

  • All components are Preact .tsx — there are no .astro files. 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/lib/_body-end-islands.tsx (AiChatModal, ClientRouterBootstrap, DesignTokenPanelBootstrap, ImageEnlarge); pages/lib/_header-with-defaults.tsx (ThemeToggle — imported from @takazudo/zudo-doc/theme-toggle, SidebarToggle); pages/lib/_sidebar-with-defaults.tsx (SidebarTree); Toc and MobileToc are mounted from @takazudo/zudo-doc/toc via pages/lib/_doc-page-shell.tsx (tocOverride/mobileTocOverride).

  • Current client islands: sidebar-toggle.tsx, sidebar-tree.tsx, doc-history.tsx, image-enlarge.tsx, ai-chat-modal.tsx; the zdtp panel self-mounts via configurePanel() and needs no Island wrapper. ThemeToggle, Toc, and MobileToc come from the @takazudo/zudo-doc package — 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/components/content/): server-rendered Preact functions that override HTML elements emitted by MDX via the <Content components={...} /> mapping in pages/_mdx-components.ts. Includes: headings (h2-h4), paragraph, link, strong, blockquote, lists (ul/ol), table.

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-0 through --zd-15 (16 palette slots)

Tier 2 — Semantic tokens (in global.css @theme, resolved per scheme):

  • Palette access: p0p15bg-p0, text-p8, border-p1, etc.

  • Base: bg, fgbg-bg, text-fg

  • UI: surface, muted, accent, accent-hover, sel-bg, sel-fg

  • Content: code-bg, code-fg, success, danger, warning, info

Tier 3 — Component tokens (scoped to specific components):

  • Content: .zd-content direct element styling in the shared @takazudo/zudo-doc/content.css (imported by 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 to initial

  • NEVER use hardcoded color values (rgba(), #hex, rgb()) — use semantic tokens or color-mix() with tokens

  • ALWAYS use project tokens: text-fg, bg-surface, border-muted, text-accent, etc.

  • Prefer semantic tokens (text-accent, bg-code-bg, text-danger) for standard UI

  • Use palette tokens (p0p15) only when no semantic token fits

  • For overlays/backdrops: use bg-overlay/{opacity} (e.g., bg-overlay/50) or color-mix(in oklch, var(--color-overlay) 50%, transparent) in CSS

  • For highlights (search, find-in-page): use color-mix() with var(--color-warning) at varying opacity levels

  • Acceptable 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 colorScheme in src/config/settings.ts

  • Available: Dracula, Catppuccin Mocha, Nord, TokyoNight, Gruvbox Dark, Atom One Dark

  • Add schemes in src/config/color-schemes.ts (22 color props + an optional, vestigial shikiTheme — no effect on rendering; highlighting is syntect's, configured via codeHighlight in zfb.config.ts)

  • ColorRef type: background, foreground, cursor, selectionBg, selectionFg, and semantic overrides accept number | string — number = palette index, string = direct color

Design Token Panel (zdtp)

  • Enabled via designTokenPanel: true in settings

  • Implemented by the external @takazudo/zdtp (zdtp) package; wired via configurePanel(designTokenPanelConfig) in src/lib/design-token-panel-bootstrap.ts; self-mounts as a side-effect — no Preact island registration needed

  • 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-panel on window; zdtp listens for this event natively

  • Storage prefix is zudo-doc-tweak. The installed zdtp persists the unified tweak envelope under zudo-doc-tweak-state-v3 (current) and auto-migrates the legacy zudo-doc-tweak-state-v2 and zudo-doc-tweak-state (v1) keys into it on first load. The prefix is set via storagePrefix in src/config/design-token-panel-config.ts and is guaranteed not to change — existing user saves carry over automatically. Toggling light/dark does NOT delete saved tweaks: ThemeToggle (packages/zudo-doc/src/theme-toggle/color-scheme-sync.ts) dispatches 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 earlier applyColorScheme wiped 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 :root intentionally — avoids generating Tailwind text-scale-* utility classes that would bypass the semantic layer

  • NEVER 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 a referencesTier: "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 (title covers h2 / card / modal / section headings). subheading was renamed to title because 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-content typography (shipped in @takazudo/zudo-doc/content.css, imported by global.css) also references Tier 2 tokens

  • For 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 height

  • Keep as arbitrary values until the pattern recurs enough to justify a token

Rules:

  • No abstract numeric scale (no size-4, size-8) — semantic names only

  • Tokenize 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/styles/global.css is code-generated from the single source of truth in src/config/z-index-tokens.ts. The tooling that does this now ships as a package bin from @takazudo/zudo-doc (S9b #2334):

  • Source of truth (project-side): src/config/z-index-tokens.ts — defines Z_INDEX_TIERS. Edit here; never hand-edit the generated @theme block.

  • Generator bin (package-side): gen-z-index — provided by @takazudo/zudo-doc. Reads src/config/z-index-tokens.ts and writes the GENERATED:Z_INDEX_BEGIN…END block in src/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 /zudo-doc-design-system to load project-specific rules

  • Tailwind v4: imports tailwindcss/preflight + tailwindcss/utilities (no default theme)

  • @theme has --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/components/content/ registered through 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-content in the package-shipped @takazudo/zudo-doc/content.css (source: packages/zudo-doc/src/content.css), imported by global.css. This is the single source of truth for content rendering — both this showcase and every create-zudo-doc project @import it, so edit content.css there, not per-project global.css (zudolab/zudo-doc#2188). global.css keeps only @theme tokens, 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.

Revision History

CreatedUpdated

AI Assistant

Ask a question about the documentation.