@create-ui/cli 0.1.0-beta.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,213 @@
1
+ # Contributing to the Create UI Monorepo
2
+
3
+ This guide is for contributors working **inside** the Create UI monorepo — adding or editing
4
+ registry components, the CLI, or the documentation site. If you only want to consume Create UI in
5
+ your own app, see [`cli.md`](./cli.md) instead.
6
+
7
+ ## Contents
8
+
9
+ - [Monorepo layout](#monorepo-layout)
10
+ - [Dev, build & quality commands](#dev-build--quality-commands)
11
+ - [Tests](#tests)
12
+ - [The registry](#the-registry)
13
+ - [Authoring a component](#authoring-a-component)
14
+ - [Scaffolding & validation](#scaffolding--validation)
15
+ - [Testing the CLI locally](#testing-the-cli-locally)
16
+ - [Website: three-layer architecture](#website-three-layer-architecture)
17
+ - [Component rules recap](#component-rules-recap)
18
+ - [Commit convention](#commit-convention)
19
+
20
+ ## Monorepo layout
21
+
22
+ Create UI is a **pnpm 9.0.6 + Turbo** monorepo with two workspaces:
23
+
24
+ | Workspace | What it is | Stack |
25
+ |---|---|---|
26
+ | `apps/v4` | Documentation site & component showcase | Next.js 16 (App Router), React 19, Tailwind CSS v4 |
27
+ | `packages/createui` | The `createui` CLI published to npm | Commander.js, tsup (ESM-only) |
28
+
29
+ The site is also where the **registry** lives (`apps/v4/registry/`). The CLI reads that registry —
30
+ in the monorepo it points at the local dev server (`http://localhost:4000/r`).
31
+
32
+ ## Dev, build & quality commands
33
+
34
+ Run all commands from the repo root. Package manager is **pnpm** — do not use npm or yarn.
35
+
36
+ ```bash
37
+ # Develop
38
+ pnpm dev # everything, in parallel via Turbo
39
+ pnpm v4:dev # docs/showcase site only (port 4000)
40
+ pnpm createui:dev # CLI only, in watch mode
41
+
42
+ # Build
43
+ pnpm build # all workspaces
44
+ pnpm v4:build # site only
45
+ pnpm createui:build # CLI only
46
+
47
+ # Quality
48
+ pnpm check # lint + typecheck + format:check (run this before opening a PR)
49
+ pnpm lint # ESLint
50
+ pnpm lint:fix # ESLint with --fix
51
+ pnpm typecheck # TypeScript
52
+ pnpm format:write # Prettier write
53
+ pnpm format:check # Prettier check
54
+ ```
55
+
56
+ ## Tests
57
+
58
+ The test suite needs the v4 dev server running; `pnpm test` handles that for you.
59
+
60
+ ```bash
61
+ pnpm test # starts the v4 dev server, then runs Vitest
62
+ pnpm test:dev # runs Vitest against an already-running server (no startup)
63
+ ```
64
+
65
+ ## The registry
66
+
67
+ Every UI component is defined under `apps/v4/registry/` and served to users through the CLI.
68
+
69
+ ```
70
+ apps/v4/registry/
71
+ ui/ core UI components (button, select, dialog, …)
72
+ examples/ demos shown in the docs
73
+ blocks/ larger composed blocks
74
+ hooks/ custom React hooks
75
+ lib/ utilities (e.g. cn())
76
+ internal/ internal-only components (not exposed to users)
77
+ components/ shared registry components
78
+ ```
79
+
80
+ Each subdirectory has a `_registry.ts` that exports a metadata array, and every array is aggregated
81
+ in `apps/v4/registry/registry.ts`.
82
+
83
+ In-repo registry entries **omit `content`** — `pnpm registry:build` injects each file's source when
84
+ it generates `apps/v4/public/r/<name>.json`. Real entry shapes:
85
+
86
+ ```ts
87
+ // apps/v4/registry/ui/_registry.ts
88
+ {
89
+ name: "button",
90
+ type: "registry:ui",
91
+ dependencies: ["class-variance-authority", "radix-ui"],
92
+ files: [{ path: "ui/button.tsx", type: "registry:ui" }],
93
+ }
94
+
95
+ {
96
+ name: "select",
97
+ type: "registry:ui",
98
+ registryDependencies: ["field", "dropdown-menu"],
99
+ files: [{ path: "ui/select.tsx", type: "registry:ui" }],
100
+ }
101
+ ```
102
+
103
+ The `type` values, file objects (`{ path, type, content?, target? }`), and item fields are defined by
104
+ the registry-item schema (`$schema: https://createui.co/schema/registry-item.json`). Use
105
+ `dependencies` for npm packages and `registryDependencies` for other registry items the component
106
+ needs.
107
+
108
+ ## Authoring a component
109
+
110
+ 1. Create `apps/v4/registry/ui/<name>.tsx`:
111
+ - use **`cva`** for variants and **`cn()`** (from `@/registry/lib/utils`) to merge classes
112
+ - put `data-slot="<name>"` on the root element
113
+ - support polymorphism with **`asChild`** via the Radix `Slot`
114
+ - type props as `React.ComponentProps<"el"> & VariantProps<typeof variants> & { … }`
115
+ - use a **named export** (`export { Name }`)
116
+ 2. Add an entry to `apps/v4/registry/ui/_registry.ts` (shape above).
117
+ 3. Add a demo under `apps/v4/registry/examples/<name>-demo.tsx` and register it in
118
+ `apps/v4/registry/examples/_registry.ts`.
119
+ 4. Run **`pnpm registry:build`** to rebuild the registry (it also runs `lint:fix` + format and
120
+ regenerates the `public/r/*.json` files).
121
+
122
+ > Filenames are **kebab-case**; exports are PascalCase named exports. There is **no** `pnpm tokens:build` —
123
+ > tokens live in `apps/v4/styles/globals.css` and are edited directly.
124
+
125
+ ## Scaffolding & validation
126
+
127
+ ```bash
128
+ pnpm scaffold <name> # create a component + example + registry entry
129
+ pnpm scaffold <name> --existing # generate an example from an existing component (parses CVA)
130
+ pnpm scaffold <name> --dry-run # preview output without writing files
131
+ pnpm scaffold <name> --force # overwrite existing files
132
+
133
+ pnpm validate:registries # validate every _registry.ts against the schema
134
+ ```
135
+
136
+ ## Testing the CLI locally
137
+
138
+ The root `pnpm createui` script runs the **local CLI build** against `http://localhost:4000/r`, so
139
+ start the site first:
140
+
141
+ ```bash
142
+ pnpm v4:dev # serves the local registry at http://localhost:4000/r
143
+ pnpm createui add -c ~/path/to/app # run the local CLI against a target app
144
+ ```
145
+
146
+ `-c` (`--cwd`) points at the project you want to add components to.
147
+
148
+ ## Website: three-layer architecture
149
+
150
+ Site work follows a strict three-layer model:
151
+
152
+ ```
153
+ registry/ui/ primitives — SACROSANCT, never edited by site work
154
+ ↓ composed by
155
+ components/site/ shared composites (reused across ≥2 route groups)
156
+ ↓ composed by
157
+ app/(group)/_components/ route-local composites (used by one route group)
158
+ ```
159
+
160
+ A new composite belongs in `components/site/` only if it is reused across **two or more** route
161
+ groups; otherwise it lives in the route group's `_components/`. If a primitive is missing, **ask
162
+ first** — never edit `registry/ui/` to make a page work.
163
+
164
+ The authoritative website guides live in **`mds/website/`** — start at
165
+ [`mds/website/BRIEF.md`](../../mds/website/BRIEF.md) (it is written in Turkish). Consult those guides
166
+ for any website task; do not duplicate them here.
167
+
168
+ ## Component rules recap
169
+
170
+ These conventions keep every component consistent (see [`rules/styling.md`](./rules/styling.md),
171
+ [`rules/composition.md`](./rules/composition.md), and [`rules/icons.md`](./rules/icons.md) for the
172
+ full rules):
173
+
174
+ - **`data-slot`** on the root element (and on meaningful sub-parts) for semantic styling hooks.
175
+ - **`cn()`** for all class merging — never string-concatenate classes.
176
+ - **`cva`** for variant-based styling; hoist the variants object out of the component.
177
+ - **Semantic tokens** for color: `bg-primary-base`, `text-error-base`, `bg-weak`, `text-body` —
178
+ never `bg-background` / `text-foreground`-style names.
179
+ - **Radix UI** primitives for accessibility; polymorphism via **`asChild`** + Radix `Slot` only.
180
+ - **Focus is `outline-*`**, never `ring-*` (e.g. `focus-visible:outline-primary-700`).
181
+ - Intersection prop types: `React.ComponentProps<"button"> & VariantProps<…> & { … }`.
182
+ - **kebab-case** filenames, **named** exports.
183
+
184
+ A correct root element looks like:
185
+
186
+ ```tsx
187
+ // Incorrect — ring focus, shadcn-style token, anonymous default export
188
+ <button className={`${base} focus-visible:ring-2 bg-primary`}>{children}</button>
189
+
190
+ // Correct — data-slot, cn(), outline focus, semantic token
191
+ <Comp
192
+ data-slot="button"
193
+ className={cn(buttonVariants({ variant, appearance, size, className }))}
194
+ {...props}
195
+ />
196
+ ```
197
+
198
+ When you reference a component in an example, **read its source** at
199
+ `apps/v4/registry/ui/<name>.tsx` first — never guess props. For instance, `Button` takes
200
+ `variant` (`primary` | `neutral-solid` | `neutral-light` | `danger` | `success` | `inverse-solid` |
201
+ `inverse-light`), `appearance` (`solid` | `outline` | `ghost` | `soft`), `size`, `shape`, `loading`,
202
+ `iconOnly`, `leadingIcon`, `trailingIcon`, and `asChild` — there is no `variant="outline"` or
203
+ `variant="destructive"`.
204
+
205
+ ## Commit convention
206
+
207
+ Conventional commits: `category(scope): message`.
208
+
209
+ Categories: `feat`, `fix`, `refactor`, `docs`, `build`, `test`, `ci`, `chore`.
210
+
211
+ ```
212
+ feat(components): add loading prop to the button component
213
+ ```
@@ -0,0 +1,284 @@
1
+ # Customization & Theming
2
+
3
+ Create UI is **one styling system with many themes**. Components reference semantic CSS variable tokens; change the tokens (or swap the theme) and every component follows. Values are **HEX**, never OKLCH.
4
+
5
+ ## Contents
6
+
7
+ - How it works (CSS variables → Tailwind utilities → components)
8
+ - Token families (surfaces, text, primary scale, status, shadows, focus, radius)
9
+ - shadcn → Create UI token map (for migrants)
10
+ - Semantic spacing & typography tokens
11
+ - Theming (primary themes, neutral themes, font variants)
12
+ - Dark mode setup
13
+ - Adding a custom color / changing radius
14
+ - Customizing components (props, className, variants, wrappers)
15
+ - Checking for updates
16
+
17
+ ---
18
+
19
+ ## How It Works
20
+
21
+ 1. CSS variables are defined in `:root` (light) and overridden under `.dark` (dark mode), as **HEX** values.
22
+ 2. Tailwind v4 auto-generates utilities from those `--color-*` / `--spacing-*` / `--radius-*` variables (`bg-weakest`, `text-body`, `gap-component-sm`, …).
23
+ 3. Components consume those utilities — change a variable, or swap the active theme, and every component that references it updates.
24
+
25
+ There is no OKLCH, no `--primary`/`--muted` convention, and no parallel style/base stack. One system, layered themes.
26
+
27
+ ---
28
+
29
+ ## Token Families
30
+
31
+ Create UI uses **semantic** token names. Backgrounds, borders, and text share a weak→strong scale; status colors and the primary scale have their own families.
32
+
33
+ ### Surfaces
34
+
35
+ | Utility | Purpose |
36
+ | --- | --- |
37
+ | `bg-weakest` … `bg-strongest` | Neutral surface scale (`weakest`, `weak`, `light`, `medium`, `heavy`, `strong`, `strongest`) |
38
+ | `bg-static` | Page/card surface that swaps with theme (white in light, black in dark) |
39
+ | `bg-static-white` / `bg-static-black` | Surfaces that never swap |
40
+ | `border-weakest` … `border-strongest` | Border scale (use `border-light` / `border-medium` for inputs and dividers) |
41
+
42
+ ### Text
43
+
44
+ | Utility | Purpose |
45
+ | --- | --- |
46
+ | `text-body` | Default body text |
47
+ | `text-placeholder` | Hints, secondary, muted text |
48
+ | `text-disabled` | Disabled text |
49
+ | `text-strongest` | High-contrast headings |
50
+ | `text-static` / `text-static-white` | Text that never swaps with theme |
51
+
52
+ ### Primary scale
53
+
54
+ `bg-primary-50` … `bg-primary-950`, plus `bg-primary-base` (= `bg-primary-500`), `text-primary-base`, and the alphas `bg-primary-alpha-16` / `bg-primary-alpha-48` (subtle/hover tints). Focus uses `outline-primary-500` / `outline-primary-700`.
55
+
56
+ ### Status families
57
+
58
+ Each of `error`, `success`, `warning`, `info` has a `-base` plus a `-weakest` … `-strongest` scale, e.g. `bg-error-base`, `text-error-base`, `outline-error-strongest`, `bg-success-base`, `bg-info-base`. **Prefer the semantic status tokens** in your own code. The shipped Button implements its danger/success variants with the raw `red-*` / `green-*` scales (e.g. `bg-red-600`, `bg-red-alpha-16`) — that is the implementation detail, not a pattern you need to copy.
59
+
60
+ ### Shadows
61
+
62
+ Neutral elevation: `shadow-neutral-{2xs,xs,sm,md,lg,…}`. Component state shadows: `shadow-component-{primary,neutral,error,success,info,inverted}-{default,hover,focused}`. Text shadows: `text-shadow-{2xs,xs,…}`.
63
+
64
+ ### Focus
65
+
66
+ Focus is an **outline**, never a ring. The pattern is a transparent base outline that becomes visible on focus:
67
+
68
+ ```tsx
69
+ "outline-2 outline-transparent focus-visible:outline-primary-700"
70
+ ```
71
+
72
+ Use `outline-primary-700` (or `outline-strongest` / `outline-strong`) for focus. Never use `ring-*`.
73
+
74
+ ### Radius
75
+
76
+ `--radius-none/xs/sm/md/lg/xl/2xl/3xl/4xl/5xl/full` back the `rounded-sm`/`rounded-md`/`rounded-lg`/`rounded-xl`/`rounded-2xl` utilities. Radius is set per component (e.g. Button maps each size to a radius via compound variants).
77
+
78
+ ---
79
+
80
+ ## shadcn → Create UI Token Map
81
+
82
+ If you are migrating markup written against shadcn token names, translate them:
83
+
84
+ | shadcn | Create UI |
85
+ | --- | --- |
86
+ | `bg-background` | `bg-static` |
87
+ | `bg-card` | `bg-static` (or `bg-weakest` for subtle surfaces) |
88
+ | `text-foreground` | `text-body` |
89
+ | `text-muted-foreground` | `text-placeholder` |
90
+ | `bg-primary` | `bg-primary-base` (or `bg-primary-500`) |
91
+ | `text-primary-foreground` | `text-white` (on solid primary) |
92
+ | `border-border` / `border-input` | `border-light` or `border-medium` |
93
+ | `bg-muted` | `bg-weak` |
94
+ | `bg-destructive` | `bg-error-base` |
95
+ | `text-destructive` | `text-error-base` |
96
+ | `bg-accent` | `bg-primary-alpha-16` |
97
+ | `ring-ring` (focus) | `outline-primary-700` (primary) / `outline-strong` (neutral) |
98
+
99
+ ---
100
+
101
+ ## Semantic Spacing & Typography Tokens
102
+
103
+ Tailwind v4 also auto-generates spacing and typography utilities from `--spacing-*` and the typography tokens. These **mirror Figma's semantic variables**.
104
+
105
+ ### Spacing
106
+
107
+ | Family | Utilities |
108
+ | --- | --- |
109
+ | component | `gap-component-none`, `gap-component-xs`, `gap-component-sm`, `p-component-md`, `gap-component-lg`, `p-component-xl`, `px-component-none` |
110
+ | layout | `gap-layout-xs`, `p-layout-sm`, `gap-layout-md`, `p-layout-lg`, `p-layout-xl` |
111
+
112
+ **Figma-token rule:** use a semantic spacing class **only when Figma references a semantic token** (e.g. `var(--component/sm,8px)` → `gap-component-sm`). When Figma shows a static value (`space-space-4`), use the standard Tailwind class (`gap-4`). Prefer `px-component-none` over `px-0` when it is an intentional "no padding" override of a token.
113
+
114
+ ### Typography
115
+
116
+ `text-display-{lg,xl}`, `text-heading-h1` … `text-heading-h6`, `text-body-{xs,sm,md,lg,xl}`, `text-paragraph-{xs…xl}`, `text-ui-{xs,sm,md,lg,xl}`, `text-ui-overline-*`, `text-ui-caption-*`, `text-numeric-{xs…xl}`.
117
+
118
+ Spacing and typography tokens **auto-scale across breakpoints** — never add `md:` / `xl:` prefixes to `gap-component-sm`, `text-heading-h2`, and the like.
119
+
120
+ ---
121
+
122
+ ## Theming
123
+
124
+ One system, many themes. A theme is a swappable **token set** (a `registry:theme` item carrying a `primary` 50…950 palette), layered on the single foundation — it is not a style/base split and not a preset color.
125
+
126
+ - **Primary themes (8):** `indigo` (default), `blue`, `lime`, `green`, `red`, `orange`, `yellow`, `cyan`
127
+ - **Neutral themes (5):** `gray` (default), `slate`, `zinc`, `base`, `stone`
128
+ - **Font variants:** `v1` (Geist + JetBrains Mono)
129
+
130
+ Pick a theme at init, interactively or via flags:
131
+
132
+ ```bash
133
+ npx @create-ui/cli init --theme blue --neutral slate --font-variant v1
134
+ ```
135
+
136
+ `init` applies the choice by adding the matching registry items (`theme-<primary>`, `neutral-<neutral>`, `font-variant-<v>`). There is **no `apply` command** and **no preset codes** — to change theme later, re-run `init` with new flags or edit the token variables in your global CSS.
137
+
138
+ ---
139
+
140
+ ## Dark Mode
141
+
142
+ Toggle the `.dark` class on the root element; tokens swap automatically. In Next.js, use `next-themes`:
143
+
144
+ ```tsx
145
+ import { ThemeProvider } from "next-themes"
146
+
147
+ <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
148
+ {children}
149
+ </ThemeProvider>
150
+ ```
151
+
152
+ Because every color is a token that already has a `.dark` override, **never write manual `dark:` color overrides** on components — let the tokens do the work.
153
+
154
+ ---
155
+
156
+ ## Adding a Custom Color / Changing Radius
157
+
158
+ Edit the project's global CSS file — the `tailwind.css` path reported by `createui info` (typically `app/globals.css`). **Never create a new CSS file** for this.
159
+
160
+ Define the HEX scale under `:root` (and `.dark`), then expose it to Tailwind in the same file:
161
+
162
+ ```css
163
+ /* app/globals.css */
164
+ :root {
165
+ --color-brand-50: #eef6ff;
166
+ --color-brand-500: #2f7bff;
167
+ --color-brand-900: #14315f;
168
+ --radius-lg: 0.75rem; /* override radius */
169
+ }
170
+
171
+ .dark {
172
+ --color-brand-500: #5a96ff;
173
+ }
174
+ ```
175
+
176
+ Tailwind v4 auto-generates the utilities (`bg-brand-500`, `text-brand-900`, …) from those `--color-*` variables:
177
+
178
+ ```tsx
179
+ <div className="bg-brand-50 text-brand-900">Brand surface</div>
180
+ ```
181
+
182
+ To restyle existing components, override the semantic tokens themselves (e.g. redefine the `primary` scale or a status family) rather than adding new ones. (There is no token build step to run — editing the CSS is the whole change.)
183
+
184
+ ---
185
+
186
+ ## Customizing Components
187
+
188
+ See also: [rules/styling.md](./rules/styling.md) for Incorrect/Correct examples.
189
+
190
+ Prefer these approaches, in order.
191
+
192
+ ### 1. Built-in props
193
+
194
+ Reach for the component's own API first. For example, `Button` exposes `variant`, `appearance`, `size`, `shape`, `loading`, `iconOnly`, `leadingIcon`, `trailingIcon`, and `asChild`:
195
+
196
+ ```tsx
197
+ import { Button } from "@/components/ui/button"
198
+
199
+ <Button appearance="outline" size="sm">Save</Button>
200
+ <Button variant="danger">Delete</Button>
201
+ <Button loading>Saving…</Button>
202
+ ```
203
+
204
+ ### 2. Tailwind classes via `className`
205
+
206
+ Use `className` for layout and spacing, not for re-coloring the variant:
207
+
208
+ ```tsx
209
+ import { cn } from "@/lib/utils"
210
+ import { Card } from "@/components/ui/card"
211
+
212
+ <Card className={cn("mx-auto max-w-md")}>...</Card>
213
+ ```
214
+
215
+ ### 3. Add a CVA variant in the source
216
+
217
+ If you need a new look, add it to the component's `cva` config in the source, using real Create UI tokens:
218
+
219
+ ```tsx
220
+ // components/ui/button.tsx — add to the buttonVariants config
221
+ warning: "bg-warning-base text-static-white hover:bg-warning-strong",
222
+ ```
223
+
224
+ ### 4. Wrapper components
225
+
226
+ Compose Create UI primitives into higher-level components. Verify each primitive's props (`Button` has `variant="danger"`, not `variant="destructive"`):
227
+
228
+ ```tsx
229
+ import { Button } from "@/components/ui/button"
230
+ import {
231
+ Dialog,
232
+ DialogClose,
233
+ DialogContent,
234
+ DialogDescription,
235
+ DialogFooter,
236
+ DialogHeader,
237
+ DialogTitle,
238
+ DialogTrigger,
239
+ } from "@/components/ui/dialog"
240
+
241
+ export function ConfirmDialog({ title, description, onConfirm, children }) {
242
+ return (
243
+ <Dialog>
244
+ <DialogTrigger asChild>{children}</DialogTrigger>
245
+ <DialogContent>
246
+ <DialogHeader>
247
+ <DialogTitle>{title}</DialogTitle>
248
+ <DialogDescription>{description}</DialogDescription>
249
+ </DialogHeader>
250
+ <DialogFooter>
251
+ <DialogClose asChild>
252
+ <Button appearance="outline">Cancel</Button>
253
+ </DialogClose>
254
+ <Button variant="danger" onClick={onConfirm}>
255
+ Confirm
256
+ </Button>
257
+ </DialogFooter>
258
+ </DialogContent>
259
+ </Dialog>
260
+ )
261
+ }
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Checking for Updates
267
+
268
+ To see which installed components differ from the registry, use the `diff` command:
269
+
270
+ ```bash
271
+ # List components that have updates available.
272
+ npx @create-ui/cli diff
273
+
274
+ # Show what changed upstream for one component.
275
+ npx @create-ui/cli diff button
276
+ ```
277
+
278
+ When you re-add a component, pass `--overwrite` to replace local files:
279
+
280
+ ```bash
281
+ npx @create-ui/cli add button --overwrite
282
+ ```
283
+
284
+ See [Updating Components in SKILL.md](./SKILL.md#updating-components) for the full workflow.
@@ -0,0 +1,47 @@
1
+ {
2
+ "skill_name": "createui",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "I'm building a Next.js app with Create UI (lucide icons). Create a settings form component with fields for: full name, email address, and notification preferences (email, SMS, push notifications as on/off toggles). Add validation states for required fields.",
7
+ "expected_output": "A React component using FieldGroup, Field, Switch, data-invalid/aria-invalid validation, gap-* spacing, and Create UI semantic tokens.",
8
+ "files": [],
9
+ "expectations": [
10
+ "Uses FieldGroup and Field components for form layout instead of a raw div with space-y",
11
+ "Uses Switch for independent on/off notification toggles (not looping Button with manual active state)",
12
+ "Uses data-invalid on Field and aria-invalid on the input control for validation states",
13
+ "Uses gap-* (e.g. gap-4, gap-6) instead of space-y-* or space-x-* for spacing",
14
+ "Uses Create UI semantic tokens (e.g. bg-static, text-body, text-placeholder, text-error-base) — never shadcn tokens like bg-background/text-muted-foreground or raw colors like bg-red-500",
15
+ "No manual dark: color overrides (tokens swap via the .dark class)"
16
+ ]
17
+ },
18
+ {
19
+ "id": 2,
20
+ "prompt": "Create a dialog component for editing a user profile. It should have the user's avatar at the top, input fields for name and bio, and Save/Cancel buttons with appropriate icons. Using Create UI with lucide icons.",
21
+ "expected_output": "A React component with DialogTitle, Avatar+AvatarFallback, Button with leadingIcon/trailingIcon props, no icon sizing classes, asChild for custom triggers.",
22
+ "files": [],
23
+ "expectations": [
24
+ "Includes DialogTitle for accessibility (visible or with an sr-only class)",
25
+ "Avatar component includes AvatarFallback",
26
+ "Icons on buttons are passed via the leadingIcon/trailingIcon props (never a data-icon attribute, which does not exist in Create UI)",
27
+ "No sizing classes on icons inside components (no size-4, w-4, h-4, etc.) — the component sizes icons via CVA",
28
+ "Uses the Button loading prop for the pending Save state instead of manually composing a Spinner",
29
+ "Uses asChild for custom triggers (Radix Slot)"
30
+ ]
31
+ },
32
+ {
33
+ "id": 3,
34
+ "prompt": "Create a dashboard component that shows 4 stat cards in a grid. Each card has a title, large number, a percentage-change badge, and a loading skeleton state. Using Create UI with lucide icons.",
35
+ "expected_output": "A React component with full Card composition, Skeleton for loading, a Badge/StatusBadge for the change, Create UI semantic tokens, and gap-* spacing.",
36
+ "files": [],
37
+ "expectations": [
38
+ "Uses full Card composition with CardHeader, CardTitle, CardContent (not dumping everything into CardContent)",
39
+ "Uses the Skeleton component for loading placeholders instead of custom animate-pulse divs",
40
+ "Uses a Badge or StatusBadge for the percentage change instead of custom styled spans",
41
+ "Uses Create UI semantic tokens (e.g. text-body, text-strongest, text-success-base) instead of shadcn tokens or raw colors like bg-green-500",
42
+ "Uses gap-* instead of space-y-* or space-x-* for spacing",
43
+ "Uses size-* when width and height are equal instead of separate w-* h-*"
44
+ ]
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,151 @@
1
+ # Create UI MCP Server
2
+
3
+ The Create UI MCP server lets AI assistants browse, search, and install components from registries through the Model Context Protocol.
4
+
5
+ ## Contents
6
+
7
+ - [Setup](#setup)
8
+ - [Available Tools](#available-tools)
9
+ - [Configuring Registries](#configuring-registries)
10
+ - [Usage Examples](#usage-examples)
11
+
12
+ ## Setup
13
+
14
+ Start the MCP stdio server with:
15
+
16
+ ```bash
17
+ npx @create-ui/cli mcp
18
+ ```
19
+
20
+ To write the configuration file for your MCP client, run:
21
+
22
+ ```bash
23
+ npx @create-ui/cli mcp init --client claude
24
+ ```
25
+
26
+ Supported clients and the config path each one writes:
27
+
28
+ | Client | Config path |
29
+ | --- | --- |
30
+ | `claude` | `.mcp.json` |
31
+ | `cursor` | `.cursor/mcp.json` |
32
+ | `vscode` | `.vscode/mcp.json` |
33
+ | `codex` | `.codex/config.toml` |
34
+ | `opencode` | `opencode.json` |
35
+
36
+ The generated config always runs `npx createui@latest mcp`. For example, the `claude` client writes:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "createui": {
42
+ "command": "npx",
43
+ "args": ["createui@latest", "mcp"]
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Available Tools
50
+
51
+ The MCP server exposes seven tools:
52
+
53
+ ### get_project_registries
54
+
55
+ Returns the registries configured in the current project's `components.json`.
56
+
57
+ **Inputs:** none
58
+
59
+ ### list_items_in_registries
60
+
61
+ Lists all items available in the specified registries.
62
+
63
+ **Inputs:**
64
+ - `registries` (string[]) — registry namespaces to query
65
+ - `limit` (number, optional)
66
+ - `offset` (number, optional)
67
+
68
+ ### search_items_in_registries
69
+
70
+ Searches for items across registries by query string.
71
+
72
+ **Inputs:**
73
+ - `registries` (string[])
74
+ - `query` (string)
75
+ - `limit` (number, optional)
76
+ - `offset` (number, optional)
77
+
78
+ ### view_items_in_registries
79
+
80
+ Returns detailed information about specific items.
81
+
82
+ **Inputs:**
83
+ - `items` (string[]) — e.g. `@createui/button`
84
+
85
+ ### get_item_examples_from_registries
86
+
87
+ Finds example and demo code for items.
88
+
89
+ **Inputs:**
90
+ - `registries` (string[])
91
+ - `query` (string)
92
+
93
+ ### get_add_command_for_items
94
+
95
+ Returns the `add` command for the specified items.
96
+
97
+ **Inputs:**
98
+ - `items` (string[])
99
+
100
+ ### get_audit_checklist
101
+
102
+ Returns a checklist to verify after adding components.
103
+
104
+ **Inputs:** none
105
+
106
+ > **Tip:** The MCP server has no equivalent for inspecting project configuration. To print the resolved aliases, framework, and Tailwind setup, run the `info` command directly: `npx @create-ui/cli info`.
107
+
108
+ ## Configuring Registries
109
+
110
+ Configure additional registries under the `registries` field in `components.json`:
111
+
112
+ ```json
113
+ {
114
+ "registries": {
115
+ "@acme": "https://acme.com/r/{name}.json",
116
+ "@private": {
117
+ "url": "https://api.company.com/r/{name}.json",
118
+ "headers": {
119
+ "Authorization": "Bearer ${MY_TOKEN}"
120
+ }
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ - Registry namespaces must start with `@`.
127
+ - A registry can be a plain URL string (`@acme`) or an object with `url`, `headers`, and `params` (`@private`).
128
+ - URL templates contain a `{name}` placeholder that is replaced with the item name.
129
+ - `${VAR}` expands from environment variables, which is useful for tokens and secrets.
130
+
131
+ The `@createui` registry is always built-in and available without any configuration.
132
+
133
+ ## Usage Examples
134
+
135
+ Browse the Create UI registry:
136
+
137
+ ```
138
+ Show me all available components in @createui
139
+ ```
140
+
141
+ Search for a component:
142
+
143
+ ```
144
+ Search for a date picker in @createui
145
+ ```
146
+
147
+ Install a component:
148
+
149
+ ```
150
+ Add the button and card components from @createui
151
+ ```