cloudflare/kumo

Public

mirrored fromhttps://github.com/cloudflare/kumoAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
6dc9a73c0bb7ae2731f474f987d92742b4e3b764

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

AGENTS.md

1014lines · modecode

1# AGENTS.md
2
3Comprehensive guide for AI agents and developers working with Kumo.
4
5## Quick Start
6
7```bash
8pnpm add @cloudflare/kumo
9```
10
11```tsx
12import { Button } from "@cloudflare/kumo";
13```
14
15**CRITICAL:** Only use semantic tokens (`bg-kumo-base`, `text-kumo-default`). Never raw Tailwind colors (`bg-blue-500`).
16
17```bash
18pnpm --filter @cloudflare/kumo codegen:registry # Generate component-registry.{json,md}
19```
20
21## Repository Overview
22
23`Kumo` is Cloudflare's component library for building modern web applications. It is a `pnpm` monorepo containing a React component library and its documentation site. The library provides accessible, design-system-compliant UI components built on [Base UI](https://base-ui.com/).
24
25## Dynamic Code Analysis Features
26
27Kumo provides extensive automated tooling (`packages/kumo/scripts/`):
28
29**1. Component Registry + CLI** (`scripts/component-registry/`, `src/command-line/`) - AI-readable metadata & CLI
30
31- Auto-generates `ai/component-registry.{json,md}` from TypeScript types + demo files
32- **Demo examples** are extracted from `kumo-docs-astro/src/components/demos/` (not kumo)
33- Includes: props, variants, examples, semantic tokens, sub-components
34- **Exported CLI:** `npx @cloudflare/kumo {ls|doc|docs}` - Quick component reference
35
36**Build Pipeline:**
37
38```
39kumo-docs-astro/src/components/demos/*.tsx
40 ↓ (pnpm codegen:demos)
41kumo-docs-astro/dist/demo-metadata.json
42 ↓ (pnpm codegen:registry)
43kumo/ai/component-registry.{json,md}
44```
45
46**2. Figma Plugin** (`packages/kumo-figma/`) - React → Figma components
47
48- Separate package: `@cloudflare/kumo-figma`
49- 30+ generators (Button, Dialog, Tabs, Toast, etc.)
50- Parses Tailwind → Figma auto-layout, binds semantic tokens to variables
51- Icon library generation, loader variants, opacity modifiers
52- **IMPORTANT:** After modifying any generator in `packages/kumo-figma/src/generators/`, you must rebuild the plugin with `pnpm --filter @cloudflare/kumo-figma build` before testing in Figma
53
54**3. Figma Token Sync** (`packages/kumo-figma/scripts/`) - CSS → Figma Variables API
55
56- Syncs semantic tokens from kumo theme CSS to Figma
57- Parses `light-dark()`, converts colors (oklch/hex → Figma RGB)
58- Run with `pnpm --filter @cloudflare/kumo-figma figma:sync`
59
60**4. Custom Lint Rules** (`lint/`) - Design system enforcement
61
62- `no-primitive-colors`: Blocks `bg-blue-500`, enforces semantic tokens
63- `no-tailwind-dark-variant`: Prevents `dark:` (auto via tokens)
64
65**5. Color Analysis** (`scripts/color/`) - Token extraction & usage stats
66
67- Analyzes semantic token usage, generates color docs
68
69**6. Primitives Generator** (`scripts/generate-primitives.ts`) - Base UI exports
70
71- Auto-generates tree-shakeable primitive exports, updates package.json
72
73**Key Commands:**
74
75```bash
76pnpm --filter @cloudflare/kumo codegen:registry # Component registry
77pnpm --filter @cloudflare/kumo codegen # All codegen (primitives + registry)
78npx @cloudflare/kumo doc # CLI docs (works in any project)
79pnpm --filter @cloudflare/kumo-figma build # Build Figma plugin
80pnpm --filter @cloudflare/kumo-figma figma:sync # Sync tokens to Figma
81pnpm lint # Custom rules + oxlint
82```
83
84## Project Structure
85
86```
87kumo/
88├── packages/
89│ ├── kumo/ # Component library (@cloudflare/kumo)
90│ │ ├── src/
91│ │ │ ├── components/ # UI components (button, dialog, input, etc.)
92│ │ │ ├── blocks/ # Composite components (breadcrumbs, page-header)
93│ │ │ ├── pages/ # Full page components
94│ │ │ ├── styles/ # CSS including kumo-binding.css
95│ │ │ ├── utils/ # Utilities (cn, link-provider)
96│ │ │ └── index.ts # Main exports
97│ │ ├── ai/ # Component registry and JSON UI catalog
98│ │ ├── scripts/ # Build and linting scripts
99│ │ └── package.json
100│ ├── kumo-docs-astro/ # Documentation site (Astro)
101│ │ ├── src/
102│ │ │ ├── components/demos/ # Interactive component demos
103│ │ │ ├── pages/ # File-based routing
104│ │ │ └── layouts/ # Page layouts
105│ │ └── package.json
106│ └── kumo-figma/ # Figma plugin (@cloudflare/kumo-figma)
107│ ├── src/
108│ │ ├── generators/ # 30+ component generators
109│ │ ├── parsers/ # Tailwind → Figma conversion
110│ │ └── code.ts # Plugin entry point
111│ ├── scripts/ # Token sync to Figma
112│ └── package.json
113├── ci/ # CI/CD scripts and versioning
114│ ├── reporters/ # MR report generation
115│ ├── scripts/ # Deployment scripts
116│ └── versioning/ # Beta/production release scripts
117├── lint/ # Custom ESLint rules
118├── .changeset/ # Changeset files for versioning
119└── package.json # Workspace root
120```
121
122## Architecture
123
124### Component Library (`packages/kumo`)
125
126- **Built with**: React, TypeScript, Tailwind CSS v4, Base UI
127- **Icons**: `@phosphor-icons/react`
128- **Styling**: `cn()` utility combining `clsx` + `tailwind-merge`
129- **Build**: Vite in library mode with tree-shakeable exports
130
131### Documentation Site (`packages/kumo-docs-astro`)
132
133- **Framework**: Astro + React
134- **Deployment**: Cloudflare Workers
135- **Dev server**: `http://localhost:4321`
136- **Routes**: `/cli`, `/colors`, `/registry` for internal tools
137
138## Component Registry (Source of Truth)
139
140**Location:**
141
142- `packages/kumo/ai/component-registry.json` - Machine-readable (28 components)
143- `packages/kumo/ai/component-registry.md` - Human-readable (1575 lines)
144
145### CLI Commands
146
147The Kumo CLI provides quick access to component documentation, especially useful when `node_modules` is gitignored:
148
149```bash
150# List all components grouped by category
151npx @cloudflare/kumo ls
152
153# Get documentation for a specific component
154npx @cloudflare/kumo doc Button
155npx @cloudflare/kumo doc Dialog
156
157# Get documentation for ALL components
158npx @cloudflare/kumo docs
159
160# Show help
161npx @cloudflare/kumo help
162```
163
164**Note:** `kumo doc` (without a component name) is equivalent to `kumo docs`.
165
166### Query examples (using jq):
167
168```bash
169# Get Button props
170jq '.components.Button.props' component-registry.json
171
172# List Action category components
173jq '.search.byCategory.Action' component-registry.json
174
175# Get all component names
176jq '.search.byName' component-registry.json
177
178# Find components using a specific token
179grep "bg-kumo-base" component-registry.md
180```
181
182**Registry contains:**
183
184- Props (type, required/optional, default values, descriptions)
185- Variants (enum values with descriptions)
186- Examples (real code from stories)
187- Semantic colors used (kumo tokens only)
188- Sub-components (for compound patterns like Dialog.Root, Dialog.Trigger)
189
190## Critical Rules
191
192### ❌ NEVER
193
194- **Raw Tailwind colors:** `bg-blue-500`, `text-gray-900` → Breaks theming, fails lint
195- **Dark mode variants:** `dark:bg-black` → Dark mode is automatic via semantic tokens
196- **Missing displayName:** forwardRef components must set `displayName` for debugging
197- **Skipping registry:** Always check `component-registry.json` for component API before use
198
199### ✅ ALWAYS
200
201- **Semantic tokens:** `bg-kumo-base`, `text-kumo-default`, `border-kumo-line`, `ring-kumo-ring`
202- **Query registry first:** Props, variants, and examples are always current
203- **Use `cn()` utility:** For className composition (`cn("base", conditional && "extra", className)`)
204- **Forward refs:** Components wrapping DOM elements must use `forwardRef`
205
206## Styling System
207
208### Kumo Semantic Color Tokens
209
210**CRITICAL**: Always use Kumo semantic color classes, never raw Tailwind colors.
211
212The color system is defined in `packages/kumo/src/styles/kumo-binding.css`. Colors automatically adapt to light/dark mode via CSS `light-dark()` function.
213
214**Full token reference:** See `packages/kumo/ai/component-registry.md` - the "Kumo Color System" section contains all available tokens with usage counts, organized by category (surfaces, text, state, interactive, borders).
215
216### Key Patterns
217
218```tsx
219// ✅ CORRECT - Using Kumo semantic tokens
220<div className="bg-kumo-base border border-kumo-line rounded-lg"> // Card
221<button className="bg-kumo-brand text-white">Primary</button> // Primary button
222<button className="bg-kumo-control text-kumo-default ring ring-kumo-line"> // Secondary button
223<input className="bg-kumo-control text-kumo-default ring ring-kumo-line" /> // Form input
224<div className="bg-kumo-danger/20 border-kumo-danger text-kumo-danger">Error</div> // Error state
225
226// ❌ WRONG - Raw Tailwind colors break theming
227<button className="bg-blue-500 text-white">Submit</button>
228<div className="bg-white dark:bg-gray-900">Content</div>
229```
230
231### Dark Mode
232
233**NEVER use Tailwind's `dark:` variant**. Semantic tokens handle dark mode automatically via `light-dark()`.
234
235```tsx
236// ❌ WRONG
237<div className="bg-white dark:bg-black" />
238
239// ✅ CORRECT
240<div className="bg-kumo-base text-kumo-default" />
241```
242
243### Dark Mode
244
245**NEVER use Tailwind's `dark:` variant**. The Kumo color system handles dark mode automatically through CSS custom properties and `light-dark()`.
246
247All semantic tokens use `light-dark()` internally. **Never use `dark:` variant.**
248
249```tsx
250// ❌ WRONG - Manual dark mode handling
251<div className="bg-white dark:bg-black text-black dark:text-white" />
252
253// ✅ CORRECT - Automatic dark mode via semantic tokens
254<div className="bg-kumo-base text-kumo-default" />
255```
256
257### Surface Hierarchy
258
259Use layered surfaces for visual depth:
260
261```
262bg-kumo-base → bg-kumo-elevated → bg-kumo-recessed
263```
264
265### Mode & Theme System
266
267Kumo uses two data attributes for styling control:
268
269- **`data-mode`**: Controls light/dark mode (`"light"` | `"dark"`)
270- **`data-theme`**: Controls theme variants (e.g., `"fedramp"`)
271
272#### Dark Mode (`data-mode`)
273
274Set `data-mode` on a parent element (typically `<html>` or `<body>`) to control color scheme:
275
276```tsx
277// Light mode
278<html data-mode="light">
279
280// Dark mode
281<html data-mode="dark">
282```
283
284The CSS uses `color-scheme` and `light-dark()` to automatically adapt all semantic tokens:
285
286```css
287:root {
288 color-scheme: light;
289}
290
291[data-mode="dark"] {
292 color-scheme: dark;
293}
294```
295
296#### Themes (`data-theme`)
297
298Themes override semantic color tokens defined in `packages/kumo/src/styles/kumo-binding.css`.
299
300**Existing Themes:**
301
302- **Default**: No `data-theme` attribute required
303- **FedRAMP**: `data-theme="fedramp"` - Government compliance styling
304
305#### Adding a New Theme
306
3071. Add theme overrides in `kumo-binding.css` within `@layer base`:
308
309```css
310@layer base {
311 [data-theme="my-theme"] {
312 --color-surface: light-dark(#custom-light, #custom-dark);
313 --color-active: light-dark(#custom-light, #custom-dark);
314 --text-color-surface: light-dark(#custom-light, #custom-dark);
315 /* Override any semantic tokens as needed */
316 }
317}
318```
319
3202. Apply the theme by setting the `data-theme` attribute on a parent element:
321
322```tsx
323<div data-theme="my-theme">
324 {/* All Kumo components inside will use theme overrides */}
325</div>
326```
327
328#### Theme Guidelines
329
330- **Use `light-dark()`**: Ensures themes work with both light and dark modes
331- **Override sparingly**: Only override tokens that need to change
332- **Semantic tokens only**: Themes should override `--color-*` and `--text-color-*` variables, not component-specific styles
333- **Test both modes**: Verify theme looks correct in light and dark mode
334
335## Component Patterns
336
337### Standard Component Structure
338
339Each component follows this file structure:
340
341```
342components/
343└── button/
344 ├── button.tsx # Component implementation
345 └── index.ts # Re-exports
346```
347
348Demo files for documentation live in `packages/kumo-docs-astro/src/components/demos/`.
349
350### Component Implementation Pattern
351
352```tsx
353import { cn } from "../../utils/cn";
354import { forwardRef } from "react";
355
356export type ButtonProps = {
357 variant?: "primary" | "secondary" | "ghost" | "destructive";
358 size?: "xs" | "sm" | "base" | "lg";
359 // ... other props
360};
361
362export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
363 ({ variant = "secondary", size = "base", className, ...props }, ref) => {
364 return (
365 <button
366 ref={ref}
367 className={cn(
368 // Base styles
369 "flex items-center font-medium",
370 // Variant styles using Kumo tokens
371 variant === "primary" && "bg-kumo-brand text-white",
372 variant === "secondary" &&
373 "text-secondary bg-kumo-control ring ring-kumo-line",
374 // Size styles
375 size === "base" && "h-9 px-3 text-base",
376 className,
377 )}
378 {...props}
379 />
380 );
381 },
382);
383
384Button.displayName = "Button";
385```
386
387### Using Base UI
388
389Components are built on Base UI primitives:
390
391```tsx
392import { Dialog as DialogBase } from "@base-ui/react/dialog";
393
394function DialogContent({ children }) {
395 return (
396 <DialogBase.Portal>
397 <DialogBase.Backdrop className="bg-kumo-overlay opacity-80" />
398 <DialogBase.Popup className="rounded-xl bg-kumo-base">
399 {children}
400 </DialogBase.Popup>
401 </DialogBase.Portal>
402 );
403}
404```
405
406### Variants System
407
408Components export `KUMO_<NAME>_VARIANTS` constants defining available variants.
409
410**Check registry for:**
411
412- `props[].values` - Available variant values (e.g., `["primary", "secondary"]`)
413- `props[].default` - Default variant (e.g., `"secondary"`)
414- `props[].descriptions` - Variant descriptions (when to use each)
415
416**Example from registry:**
417
418```json
419{
420 "Button": {
421 "props": {
422 "variant": {
423 "type": "enum",
424 "values": ["primary", "secondary", "ghost", "destructive"],
425 "default": "secondary",
426 "descriptions": {
427 "primary": "Primary action button",
428 "secondary": "Secondary action button with border"
429 }
430 }
431 }
432 }
433}
434```
435
436### Compound Components
437
438Check registry `subComponents` field for compound component patterns.
439
440**Example:** Dialog has sub-components: `Dialog.Root`, `Dialog.Trigger`, `Dialog.Title`, `Dialog.Description`, `Dialog.Close`
441
442```json
443{
444 "Dialog": {
445 "subComponents": {
446 "Root": {
447 "description": "Controls the open state",
448 "props": { "open": { "type": "boolean" } }
449 },
450 "Trigger": {
451 "description": "Button that opens the dialog",
452 "renderElement": "<button>"
453 }
454 }
455 }
456}
457```
458
459### Component Requirements
460
461All components must:
462
4631. Export `KUMO_<NAME>_VARIANTS` (variants config)
4642. Export `KUMO_<NAME>_DEFAULT_VARIANTS` (default values)
4653. Use `forwardRef` when wrapping DOM elements
4664. Set `displayName` for React DevTools
467
468## Adding Components
469
470### Workflow
471
4721. **Run the scaffolding tool:**
473
474 ```bash
475 pnpm --filter @cloudflare/kumo new-component
476 ```
477
4782. **Implement the component:**
479 - Use semantic tokens only (never raw Tailwind colors)
480 - Add KUMO*\*\_VARIANTS and KUMO*\*\_DEFAULT_VARIANTS exports
481 - Use `forwardRef` when wrapping DOM elements
482 - Set `displayName` for React DevTools
483
4843. **Write demo files** in `packages/kumo-docs-astro/src/components/demos/{Name}Demo.tsx`
485
4864. **Regenerate the component registry:**
487 ```bash
488 pnpm --filter @cloudflare/kumo codegen:registry
489 ```
490
491### What Gets Scaffolded
492
493- `src/components/{name}/{name}.tsx` - Component implementation
494- `src/components/{name}/index.ts` - Re-exports
495- Updates `src/index.ts` exports
496- Updates `vite.config.ts` build entries
497- Updates `package.json` exports
498
499## Development & Tooling
500
501### Package Management (`pnpm`)
502
503```bash
504pnpm install # Install all dependencies
505pnpm --filter @cloudflare/kumo build # Build component library
506pnpm --filter @cloudflare/kumo-docs dev # Run docs dev server
507```
508
509### Common Scripts
510
511```bash
512# From workspace root
513pnpm dev # Start docs dev server
514pnpm build # Build docs site
515pnpm lint # Run linting
516pnpm typecheck # Type check all packages
517
518# From packages/kumo
519pnpm test # Run tests in watch mode
520pnpm test:run # Run tests once
521pnpm new-component # Scaffold new component
522```
523
524### Build & Test
525
526```bash
527# Testing
528pnpm --filter @cloudflare/kumo test # Vitest watch mode
529pnpm --filter @cloudflare/kumo test:run # Single run
530pnpm --filter @cloudflare/kumo test:ui # UI mode
531
532# Linting (includes custom rules)
533pnpm --filter @cloudflare/kumo lint # oxlint with:
534 # - no-primitive-colors (fails on bg-blue-500)
535 # - no-tailwind-dark-variant (fails on dark:)
536
537# Build
538pnpm --filter @cloudflare/kumo build # Full build with CSS
539pnpm --filter @cloudflare/kumo codegen:registry # Regenerate component-registry
540```
541
542### Linting (`oxlint`)
543
544The project uses `oxlint` with type-aware linting and custom rules:
545
546```bash
547pnpm --filter @cloudflare/kumo lint
548```
549
550#### Custom Lint Rules
551
5521. **`no-primitive-colors`** (`lint/no-primitive-colors.js`)
553 - Disallows Tailwind primitive colors (e.g., `bg-blue-500`, `text-gray-900`)
554 - Validates that semantic tokens exist in theme CSS files
555 - Enforces use of Kumo semantic tokens (e.g., `bg-kumo-base`, `text-kumo-subtle`)
556
5572. **`no-tailwind-dark-variant`** (`lint/no-tailwind-dark-variant.js`)
558 - Disallows `dark:` variant in class names
559 - Dark mode is handled automatically by Kumo tokens
560
5613. **`enforce-variant-standard`** (`lint/enforce-variant-standard.js`)
562 - Enforces the KUMO\_\*\_VARIANTS naming convention for component exports
563 - Only applies to files matching `src/components/{name}/{name}.tsx`
564 - Extracts component name from path (e.g., `button.tsx` → `BUTTON`, `clipboard-text.tsx` → `CLIPBOARD_TEXT`)
565
5664. **`no-cross-package-imports`** (`lint/no-cross-package-imports.js`)
567 - Disallows relative imports that reach into sibling packages in the monorepo
568 - Catches patterns like `../../kumo/src/...` from other packages
569 - Enforces using proper package imports (e.g., `@cloudflare/kumo`) instead
570
571 ```tsx
572 // ❌ WRONG - Cross-package relative import
573 import { Button } from "../../kumo/src/components/button";
574
575 // ✅ CORRECT - Use the package export
576 import { Button } from "@cloudflare/kumo";
577 ```
578
579 **Required Exports:**
580 - `KUMO_{COMPONENT}_VARIANTS` - Variant configuration object
581 - `KUMO_{COMPONENT}_DEFAULT_VARIANTS` - Default variant values
582
583 **Optional Exports:**
584 - `KUMO_{COMPONENT}_BASE_STYLES` - Base styles (must have `KUMO_` prefix if present)
585
586 **Examples:**
587
588 ```tsx
589 // ✅ CORRECT - Valid exports in button.tsx
590 export const KUMO_BUTTON_VARIANTS = {
591 variant: ["primary", "secondary", "ghost", "destructive"],
592 size: ["xs", "sm", "base", "lg"],
593 };
594
595 export const KUMO_BUTTON_DEFAULT_VARIANTS = {
596 variant: "secondary",
597 size: "base",
598 };
599
600 // Optional base styles
601 export const KUMO_BUTTON_BASE_STYLES = "flex items-center font-medium";
602 ```
603
604 ```tsx
605 // ✅ CORRECT - Valid exports in clipboard-text.tsx (kebab-case → UPPER_SNAKE_CASE)
606 export const KUMO_CLIPBOARD_TEXT_VARIANTS = {
607 /* ... */
608 };
609 export const KUMO_CLIPBOARD_TEXT_DEFAULT_VARIANTS = {
610 /* ... */
611 };
612 ```
613
614 ```tsx
615 // ❌ WRONG - Missing KUMO_ prefix
616 export const BUTTON_VARIANTS = {
617 /* ... */
618 };
619 export const BUTTON_DEFAULT_VARIANTS = {
620 /* ... */
621 };
622 ```
623
624 ```tsx
625 // ❌ WRONG - Wrong component name
626 // In button.tsx:
627 export const KUMO_INPUT_VARIANTS = {
628 /* ... */
629 };
630 export const KUMO_INPUT_DEFAULT_VARIANTS = {
631 /* ... */
632 };
633 ```
634
635 ```tsx
636 // ❌ WRONG - BASE_STYLES without KUMO_ prefix
637 export const BUTTON_BASE_STYLES = "..."; // Should be KUMO_BUTTON_BASE_STYLES
638 ```
639
640 ```tsx
641 // ❌ WRONG - Missing required exports
642 // In button.tsx - missing KUMO_BUTTON_DEFAULT_VARIANTS
643 export const KUMO_BUTTON_VARIANTS = {
644 /* ... */
645 };
646 // Error: Component must export KUMO_BUTTON_DEFAULT_VARIANTS
647 ```
648
649### Testing (`vitest`)
650
651```bash
652pnpm --filter @cloudflare/kumo test # Watch mode
653pnpm --filter @cloudflare/kumo test:run # Single run
654pnpm --filter @cloudflare/kumo test:ui # UI mode
655```
656
657## Icon System
658
659Kumo uses [Phosphor Icons](https://phosphoricons.com/) directly via `@phosphor-icons/react`. This is a peer dependency that consumers must install.
660
661### Installation
662
663```bash
664pnpm add @phosphor-icons/react
665```
666
667### Using Icons
668
669```tsx
670import { Check, ArrowRight, X } from "@phosphor-icons/react";
671
672// Basic usage
673<Check />
674<ArrowRight size={24} />
675
676// With Kumo semantic colors
677<X className="text-kumo-subtle" />
678<Check className="text-success" />
679
680// Different weights
681import { CheckBold, CheckLight } from "@phosphor-icons/react";
682```
683
684### Size Guidelines
685
686| Context | Size | Phosphor prop |
687| ---------------- | ---- | ------------- |
688| Inline with text | 16px | `size={16}` |
689| Buttons (sm) | 16px | `size={16}` |
690| Buttons (base) | 20px | `size={20}` |
691| Buttons (lg) | 24px | `size={24}` |
692| Empty states | 48px | `size={48}` |
693
694### Figma Plugin
695
696The Figma plugin embeds a subset of Phosphor icons needed for component generation. Icons are created on-demand using `figma.createNodeFromSvg()`.
697
698To add new icons to the Figma plugin, update `packages/kumo-figma/src/build-phosphor-icons.ts`.
699
700## Changesets & Version Management
701
702Kumo uses [Changesets](https://github.com/changesets/changesets) for version management with automated validation and releases.
703
704### ⚠️ IMPORTANT: AI Agents - Do NOT Version or Publish
705
706**AI agents should NEVER run these commands:**
707
708- ❌ `pnpm version` - Versions packages (human-only)
709- ❌ `pnpm release` - Publishes to npm (human-only)
710- ❌ `pnpm publish:beta` - Publishes beta versions (CI-only)
711- ❌ `pnpm release:production` - Production release script (human-only)
712
713**AI agents SHOULD:**
714
715- ✅ Create changesets: `pnpm changeset`
716- ✅ Validate changesets exist
717- ✅ Build and test: `pnpm build`, `pnpm test`
718
719**Reasoning:** Versioning and publishing are sensitive operations that require human oversight and proper npm credentials. Beta releases are automated via CI. Production releases require manual verification.
720
721### Creating Changesets
722
723**CRITICAL:** Changes to `packages/kumo/` **require** a changeset. Pre-push hooks enforce this locally, and CI validates in pull requests.
724
725```bash
726pnpm changeset
727```
728
7291. Select `@cloudflare/kumo` from the package list
7302. Choose change type:
731 - **patch** (`0.0.1`) - Bug fixes, small updates
732 - **minor** (`0.1.0`) - New components, backwards-compatible features
733 - **major** (`1.0.0`) - Breaking changes, removed components
7343. Write a clear description (appears in CHANGELOG.md)
7354. Commit the generated `.changeset/*.md` file
736
737### Pre-Push Validation
738
739Lefthook enforces changeset validation before pushing:
740
741```bash
742# Push normally - validation runs automatically
743git push
744
745# Skip validation if needed (use sparingly)
746git push --no-verify
747LEFTHOOK=0 git push
748LEFTHOOK_EXCLUDE=validate-changeset git push
749```
750
751**What it validates:**
752
753- Detects changes to `packages/kumo/` via `git merge-base origin/main HEAD`
754- Ensures a **new** changeset exists targeting `@cloudflare/kumo`
755- Blocks push with clear instructions if validation fails
756
757**Troubleshooting:**
758
759- **Missing origin/main**: Run `git fetch origin main`
760- **GUI clients (Tower, SourceTree)**: Configure PATH in client settings
761- **Hook not installed**: Run `pnpm lefthook install`
762
763### Beta Releases (Automated)
764
765Beta versions are automatically published for pull requests:
766
767**Format:** `{version}-beta.{commit-hash}` (e.g., `0.1.0-beta.a1b2c3d`)
768
769**Process:**
770
7711. Create PR with changeset
7722. CI validates changeset exists
7733. CI publishes beta version with `beta` tag
7744. PR receives comment with installation instructions
775
776**Install beta:**
777
778```bash
779pnpm add @cloudflare/kumo@0.1.0-beta.a1b2c3d
780```
781
782### Production Releases
783
784```bash
785# 1. Ensure on main with latest changes
786git checkout main && git pull
787
788# 2. Version packages (consumes changesets)
789pnpm version
790
791# 3. Build all packages
792pnpm build:all
793
794# 4. Publish to npm
795pnpm release
796
797# 5. Commit and push
798git add .
799git commit -m "chore: release @cloudflare/kumo@{version}"
800git push --follow-tags
801```
802
803**What happens:**
804
805- Updates `package.json` version
806- Generates/updates `CHANGELOG.md`
807- Removes consumed changeset files
808- Publishes to npm registry
809- Creates git tags
810
811## Figma Token Sync
812
813The `kumo-figma` package provides scripts to sync semantic color tokens from CSS to Figma design variables, ensuring design tokens stay in sync between code and design.
814
815### Purpose
816
817The Figma sync script automates synchronization of Kumo's semantic color tokens (defined in `packages/kumo/src/styles/theme-kumo.css`) to Figma variables:
818
8191. Parses CSS tokens from `theme-kumo.css`
8202. Extracts light and dark mode values from `light-dark()` functions
8213. Resolves color values (oklch, hex, rgb) to Figma RGB format
8224. Pushes tokens to Figma via the Variables API
823
824This enables:
825
826- Designers to use semantic tokens in Figma
827- Automatic updates when tokens change in code
828- Single source of truth for color values
829
830### Environment Setup
831
8321. **Get a Figma personal access token:**
833 - Go to [Figma Settings > Personal Access Tokens](https://www.figma.com/developers/api#authentication)
834 - Create a new token with a descriptive name (e.g., "Kumo Token Sync")
835 - Copy the token (you won't see it again)
836
8372. **Copy `.env.example` to `.env`:**
838
839 ```bash
840 cp packages/kumo-figma/scripts/.env.example packages/kumo-figma/scripts/.env
841 ```
842
8433. **Add your token to `.env`:**
844 ```bash
845 FIGMA_TOKEN=your-token-here
846 FIGMA_FILE_KEY=sKKZc6pC6W1TtzWBLxDGSU
847 ```
848
849### Running the Sync
850
851```bash
852# With environment variable
853FIGMA_TOKEN="your-token" pnpm --filter @cloudflare/kumo-figma figma:sync
854
855# Or load from .env
856source packages/kumo-figma/scripts/.env
857pnpm --filter @cloudflare/kumo-figma figma:sync
858```
859
860### Security Warning
861
862**⚠️ NEVER commit your Figma token to the repository.**
863
864- `.env` is gitignored by default
865- Always use environment variables for tokens
866- Rotate tokens if accidentally exposed
867
868For detailed documentation, see the Figma Plugin section below.
869
870## Code Review Guidelines
871
872When reviewing code, focus on:
873
874### Styling
875
876- **Verify Kumo tokens**: Ensure `bg-*`, `text-*`, `border-*` semantic classes are used (e.g., `bg-kumo-base`, `text-kumo-subtle`, `border-kumo-line`)
877- **No raw Tailwind colors**: Flag any `bg-blue-500`, `text-gray-*`, etc.
878- **No `dark:` variants**: Dark mode should be automatic via tokens
879- **Use `cn()` utility**: For conditional class composition
880
881### Component Quality
882
883- **Accessibility**: Components should use Base UI primitives for a11y
884- **TypeScript**: Proper typing with exported types
885- **forwardRef**: Components should forward refs when wrapping DOM elements
886- **displayName**: Set for debugging in React DevTools
887
888### Performance
889
890- **Tree-shaking**: Components should be individually importable
891- **Bundle size**: Avoid unnecessary dependencies
892- **Re-renders**: Check for unnecessary re-renders in complex components
893
894### Testing
895
896- **Demo files**: Components should have demo files in the docs site for documentation
897- **Edge cases**: Consider loading, error, empty, and disabled states
898
899## Workflow Best Practices
900
901### Before Writing Code
902
9031. **Always check the component registry first** (`packages/kumo/ai/component-registry.{json,md}`)
904 - Use `jq` to query component props, variants, and examples
905 - Never guess component APIs - the registry is always current
906 - Example: `jq '.components.Button.props' packages/kumo/ai/component-registry.json`
907
9082. **Read related components before modifying or creating similar ones**
909 - Examine existing implementations for patterns
910 - Maintain consistency with established conventions
911
912### Tool Usage for AI Agents
913
914When working with this codebase as an AI agent:
915
9161. **Read files** to examine component implementations before modifying them
9172. **Use `jq`** to query the component registry (`packages/kumo/ai/component-registry.json`)
9183. **Use search tools** for complex searches across the codebase (e.g., "find all components using bg-kumo-base")
9194. **Run commands** for scaffolding, build, test, and lint operations
920
921### When Modifying Components
922
9231. **Read the component first**
9242. **Verify semantic tokens** - Ensure no raw Tailwind colors exist
9253. **Run linting** - Custom rules will catch color and dark mode violations
9264. **Update demos** - Ensure demo files in docs site reflect changes
9275. **Regenerate registry** - Run `pnpm --filter @cloudflare/kumo codegen:registry` after changes
928
929## Important Notes
930
931- The component registry (`packages/kumo/ai/component-registry.{json,md}`) is the source of truth for component APIs
932- Always regenerate the registry (`pnpm --filter @cloudflare/kumo codegen:registry`) after modifying component props or variants
933- Custom lint rules enforce semantic token usage and prevent `dark:` variants
934
935### Common Mistakes to Avoid
936
937- Using raw Tailwind colors (`bg-blue-500`) instead of semantic tokens (`bg-kumo-base`)
938- Using `dark:` variants instead of letting semantic tokens handle dark mode
939- Forgetting to set `displayName` on `forwardRef` components
940- Not checking the component registry before using a component
941- Creating new components without running the scaffolding tool
942- Forgetting to regenerate the component registry after changes
943
944## CI/CD Pipeline
945
946### Pipeline Stages
947
948| Stage | Purpose |
949| -------------------- | ------------------------------------------ |
950| `build` | Build packages |
951| `checks` | Linting, typechecking, validation |
952| `test` | Run tests |
953| `review` | AI-powered code review |
954| `beta-release` | Publish beta npm packages |
955| `beta-preview` | Deploy docs previews |
956| `mr-report` | Post consolidated MR comment |
957| `production-release` | Deploy staging, manual production releases |
958
959### Deployment Environments
960
961| Package | Staging | Production |
962| --------------- | --------------------- | ------------- |
963| kumo-docs-astro | `staging.kumo-ui.com` | `kumo-ui.com` |
964
965### MR Reporter System
966
967The PR reporter collects artifacts from CI jobs and posts a consolidated comment:
968
969```
970ci/
971├── reporters/ # NPM, docs reporters
972├── scripts/ # post-pr-report.ts, write-*-report.ts
973├── utils/ # GitHub API, PR comment utilities
974└── versioning/ # deploy-*.sh, publish-beta.sh
975```
976
977## Figma Plugin (`packages/kumo-figma`)
978
979### Quick Start
980
981```bash
982# Build the plugin
983pnpm --filter @cloudflare/kumo-figma build
984
985# Run in Figma: Plugins > Development > Import plugin from manifest...
986# Select: packages/kumo-figma/src/manifest.json
987```
988
989### Workflow
990
9911. **Sync tokens first**: `pnpm --filter @cloudflare/kumo-figma figma:sync`
9922. **Build plugin**: `pnpm --filter @cloudflare/kumo-figma build`
9933. **Run in Figma**: Plugins > Development > Kumo UI Kit Generator
994
995### Adding New Component Generators
996
9971. Create `generators/yourcomponent.ts`
9982. Register in `code.ts` GENERATORS array
9993. Run `pnpm --filter @cloudflare/kumo-figma validate` (drift detection)
1000
1001### Drift Prevention
1002
1003- `drift-detection.test.ts` validates generators match `component-registry.json`
1004- CI enforces on MRs touching `component-registry.json` or generators
1005- Excluded components: Add to `EXCLUDED_COMPONENTS` in drift-detection.test.ts
1006
1007## Resources
1008
1009- **Component Registry** - `packages/kumo/ai/component-registry.{json,md}` - Always-current component metadata
1010- **Docs Site** - `pnpm dev` - Documentation at `http://localhost:4321`
1011- **Source** - `packages/kumo/src/` - Component source code organized by type:
1012 - `components/` - UI primitives (Button, Input, Dialog)
1013 - `blocks/` - Composite components (Breadcrumbs, PageHeader, Empty)
1014 - `styles/` - CSS including `kumo-binding.css` (semantic token definitions)
1015