@geomak/ui 7.18.5 → 7.20.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.
Files changed (42) hide show
  1. package/.claude/commands/ui-auth-shell.md +48 -0
  2. package/.claude/commands/ui-bootstrap.md +36 -0
  3. package/.claude/commands/ui-find.md +12 -0
  4. package/.claude/commands/ui-form.md +38 -0
  5. package/.claude/commands/ui-lookup.md +13 -0
  6. package/.claude/commands/ui-modal.md +50 -0
  7. package/.claude/commands/ui-page.md +36 -0
  8. package/.claude/commands/ui-scaffold.md +73 -0
  9. package/.claude/commands/ui-story.md +30 -0
  10. package/.claude/commands/ui-table.md +38 -0
  11. package/.claude/skills/oxygen-ui/SKILL.md +402 -0
  12. package/README.md +74 -34
  13. package/dist/{chunk-4V4U2W7K.cjs → chunk-4WD27VQX.cjs} +2 -2
  14. package/dist/chunk-4WD27VQX.cjs.map +1 -0
  15. package/dist/{chunk-KAFJJO5O.js → chunk-ILDMP2Q2.js} +2 -2
  16. package/dist/chunk-ILDMP2Q2.js.map +1 -0
  17. package/dist/{chunk-CNUDNGJM.cjs → chunk-LY3MZYWU.cjs} +3 -3
  18. package/dist/chunk-LY3MZYWU.cjs.map +1 -0
  19. package/dist/{chunk-DXOWXLKK.js → chunk-VM2725HH.js} +3 -3
  20. package/dist/chunk-VM2725HH.js.map +1 -0
  21. package/dist/icons/index.cjs +105 -105
  22. package/dist/icons/index.d.cts +2 -2
  23. package/dist/icons/index.d.ts +2 -2
  24. package/dist/icons/index.js +1 -1
  25. package/dist/{index-BktppxXp.d.ts → index-B8P5qbWt.d.cts} +5 -5
  26. package/dist/{index-BktppxXp.d.cts → index-B8P5qbWt.d.ts} +5 -5
  27. package/dist/index.cjs +29 -29
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +237 -237
  30. package/dist/index.d.ts +237 -237
  31. package/dist/index.js +18 -18
  32. package/dist/index.js.map +1 -1
  33. package/dist/tokens/index.cjs +4 -4
  34. package/dist/tokens/index.d.cts +1 -1
  35. package/dist/tokens/index.d.ts +1 -1
  36. package/dist/tokens/index.js +1 -1
  37. package/package.json +10 -3
  38. package/scripts/setup-claude.mjs +136 -0
  39. package/dist/chunk-4V4U2W7K.cjs.map +0 -1
  40. package/dist/chunk-CNUDNGJM.cjs.map +0 -1
  41. package/dist/chunk-DXOWXLKK.js.map +0 -1
  42. package/dist/chunk-KAFJJO5O.js.map +0 -1
@@ -0,0 +1,402 @@
1
+ ---
2
+ name: oxygen-ui
3
+ description: >
4
+ Context skill for working with the OxygenUI (@geomak/ui) design system.
5
+ Equips Claude Code with knowledge about available components, tokens, import
6
+ patterns, and how to use the MCP server for real-time docs lookup.
7
+ ---
8
+
9
+ # OxygenUI Design System
10
+
11
+ You are working inside the `@geomak/ui` repository, a React component library
12
+ built with Radix UI primitives, Tailwind CSS utilities, and a three-layer token
13
+ system. Everything ships as tree-shakeable ESM.
14
+
15
+ ---
16
+
17
+ ## MCP server
18
+
19
+ An `oxygen-ui` MCP server is configured in `.mcp.json`. Use its tools whenever
20
+ you need to look up component APIs, prop tables, or design tokens.
21
+
22
+ | Tool | When to call |
23
+ |---|---|
24
+ | `find_component` | Before writing any UI, check what the design system already has |
25
+ | `get_component` | Get full props + examples for a specific component (use the slug) |
26
+ | `list_components` | Browse all 100+ entries when unsure what exists |
27
+ | `get_token` | Look up CSS custom properties by name or category prefix |
28
+ | `get_pattern` | Get a full wired recipe for a page-level pattern (crud-list, dashboard, etc.) |
29
+ | `get_form_binding` | Look up the correct `useForm` binder for any input component |
30
+ | `compare_components` | Get a decision guide when choosing between similar components |
31
+ | `get_app_bootstrap` | Get the full provider stack + app shell bootstrap code |
32
+
33
+ **Always call `find_component` first.** OxygenUI ships 100+ components. Writing
34
+ from scratch without checking is almost always redundant.
35
+
36
+ ---
37
+
38
+ ## Import pattern
39
+
40
+ ```tsx
41
+ // Named imports from the main entry (tree-shakeable)
42
+ import { Button, Modal, DataGrid, useExcel } from '@geomak/ui'
43
+
44
+ // Styles: include once at app root
45
+ import '@geomak/ui/styles'
46
+
47
+ // Token values for JS/TS code
48
+ import { vars, semanticTokens, palette } from '@geomak/ui/tokens'
49
+
50
+ // Icons
51
+ import { Icon } from '@geomak/ui'
52
+ <Icon.Search size={20} />
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Token system
58
+
59
+ Three layers:
60
+
61
+ | Layer | Use case |
62
+ |---|---|
63
+ | `palette` | Raw brand hex values |
64
+ | `semanticTokens` | Resolved hex/px values in `{ light, dark, shared }` objects |
65
+ | `vars` | CSS custom-property strings: `vars.color.accent`, `vars.radius.md` |
66
+
67
+ ### CSS custom properties (use in inline styles or SCSS)
68
+
69
+ ```tsx
70
+ <div style={{
71
+ background: 'var(--color-surface)',
72
+ border: '1px solid var(--color-border)',
73
+ borderRadius: 'var(--radius-md)',
74
+ color: 'var(--color-foreground)',
75
+ }}>
76
+ ```
77
+
78
+ ### Tailwind utilities
79
+
80
+ | Utility | Token |
81
+ |---|---|
82
+ | `bg-surface` | `--color-surface` |
83
+ | `bg-surface-raised` | `--color-surface-raised` |
84
+ | `border-border` | `--color-border` |
85
+ | `text-foreground` | `--color-foreground` |
86
+ | `text-foreground-muted` | `--color-foreground-muted` |
87
+ | `bg-accent` | `--color-accent` |
88
+ | `text-accent-fg` | `--color-accent-foreground` |
89
+
90
+ ---
91
+
92
+ ## Form binder cheat sheet
93
+
94
+ **This is the most common source of silent bugs.** Every `useForm` field must use
95
+ the correct binder for its input type or values will not update.
96
+
97
+ | Input component | Binder method | Value type stored |
98
+ |---|---|---|
99
+ | `TextInput`, `TextArea`, `Password`, `SearchInput` | `fieldNative` | `string` |
100
+ | `NumberInput` | `fieldNative` | `number` |
101
+ | `Switch`, `Checkbox` | `fieldChecked` | `boolean` |
102
+ | `Dropdown`, `TreeSelect`, `AutoComplete` | `fieldTarget` | `key` or `key[]` |
103
+ | `RadioGroup` | `field` | option value |
104
+ | `Slider` | `field` | `number` or `[number, number]` |
105
+ | `DatePicker`, `TimePicker` | `field` | `Date \| null` |
106
+ | `DateRangePicker` | `field` | `{ from: Date; to: Date } \| null` |
107
+ | `TagsInput` | `field` | `string[]` |
108
+ | `ColorPicker` | `field` | `string` (hex) |
109
+ | `Rating` | `field` | `number` |
110
+
111
+ ```tsx
112
+ // Example: mixed form with correct binders
113
+ const form = useForm({ defaultValues: { name: '', role: '', active: false, joined: null } })
114
+
115
+ <Form form={form} onFinish={handleSubmit}>
116
+ <FormField name="name"><TextInput label="Name" {...form.fieldNative('name')} /></FormField>
117
+ <FormField name="role"><Dropdown label="Role" items={roles} {...form.fieldTarget('role')} /></FormField>
118
+ <FormField name="active"><Switch label="Active" {...form.fieldChecked('active')} /></FormField>
119
+ <FormField name="joined"><DatePicker label="Joined" {...form.field('joined')} /></FormField>
120
+ </Form>
121
+ ```
122
+
123
+ Call `get_form_binding` MCP tool when unsure which binder to use for a specific input.
124
+
125
+ ---
126
+
127
+ ## Component decision guide
128
+
129
+ ### Modal vs Drawer vs PopConfirm
130
+
131
+ | Component | Use when |
132
+ |---|---|
133
+ | `Modal` | The action needs full attention; no background context helps (confirm, form submit) |
134
+ | `Drawer` | User benefits from seeing the page behind (filter panel, row inspector, quick edit) |
135
+ | `PopConfirm` | Inline destructive confirmation on a specific row/button; no overlay needed |
136
+
137
+ Both Modal and Drawer share the same controlled API: `open` + `onClose` + `hasFooter` + `onOk` + `onCancel`.
138
+
139
+ ### Table vs DataGrid vs VirtualList vs List
140
+
141
+ | Component | Use when |
142
+ |---|---|
143
+ | `Table` | Standard paginated, sortable, searchable data; editable cells optional |
144
+ | `DataGrid` | Excel-like: column reorder/resize, bulk edits, copy-paste cell behaviour |
145
+ | `VirtualList` | 10k+ rows where DOM count is the bottleneck; no built-in sort/filter |
146
+ | List (custom) | Single-column items, icon + label, no comparison between columns |
147
+
148
+ ### Tabs vs SegmentedControl
149
+
150
+ | Component | Use when |
151
+ |---|---|
152
+ | `Tabs` | Three or more sibling content panes; content is substantial |
153
+ | `SegmentedControl` | Two to four compact mutually exclusive filter-style options |
154
+
155
+ ---
156
+
157
+ ## App bootstrap (provider nesting order)
158
+
159
+ This order is required. Getting it wrong causes token overrides, notification
160
+ portals, or dark mode to break silently.
161
+
162
+ ```tsx
163
+ // main.tsx or Bootstrap.tsx
164
+ import { ThemeProvider, NotificationProvider } from '@geomak/ui'
165
+ import { QueryClientProvider, QueryClient } from '@tanstack/react-query'
166
+ import { BrowserRouter } from 'react-router-dom'
167
+
168
+ const queryClient = new QueryClient()
169
+
170
+ export function Bootstrap() {
171
+ return (
172
+ <ThemeProvider colorScheme={colorScheme}> {/* always outermost */}
173
+ <BrowserRouter>
174
+ <QueryClientProvider client={queryClient}>
175
+ <NotificationProvider> {/* must be inside ThemeProvider */}
176
+ <AppRoutes />
177
+ </NotificationProvider>
178
+ </QueryClientProvider>
179
+ </BrowserRouter>
180
+ </ThemeProvider>
181
+ )
182
+ }
183
+ ```
184
+
185
+ Dark mode toggle: maintain `colorScheme` state in Bootstrap, pass it to `ThemeProvider`,
186
+ and also toggle `document.documentElement.classList.toggle('dark', isDark)` so that
187
+ Tailwind dark utilities work inside portals that render outside the ThemeProvider div.
188
+
189
+ Custom brand tokens (optional):
190
+
191
+ ```tsx
192
+ const BRAND_TOKENS = {
193
+ '--color-accent': '#1A56DB',
194
+ '--color-accent-hover': '#1e429f',
195
+ }
196
+
197
+ <ThemeProvider colorScheme={colorScheme} theme={BRAND_TOKENS} darkTheme={BRAND_TOKENS}>
198
+ ```
199
+
200
+ ---
201
+
202
+ ## useNotification
203
+
204
+ Must be used inside a component that is a descendant of `NotificationProvider`.
205
+
206
+ ```tsx
207
+ import { useNotification } from '@geomak/ui'
208
+
209
+ function MyPage() {
210
+ const notification = useNotification()
211
+
212
+ const onSave = async () => {
213
+ try {
214
+ await api.save(data)
215
+ notification.success({ title: 'Saved', description: 'Changes applied.', duration: 3000 })
216
+ } catch (err) {
217
+ notification.error({ title: 'Save failed', description: err.message, duration: 5000 })
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ Methods: `notification.success`, `notification.info`, `notification.warning`, `notification.error`.
224
+ All accept `{ title, description?, duration? }`.
225
+
226
+ ---
227
+
228
+ ## React Query integration
229
+
230
+ Map React Query state to OxygenUI component props:
231
+
232
+ ```tsx
233
+ const { data, isPending, isFetching, isError, refetch } = useQuery({ queryKey, queryFn })
234
+
235
+ // First load: full skeleton
236
+ if (isPending) return <SkeletonBox className="h-96 w-full" />
237
+
238
+ // Error state
239
+ if (isError) return <ErrorState onRetry={refetch} />
240
+
241
+ // Background refetch: show spinner overlay on existing content (not a full skeleton)
242
+ // isPending=false, isFetching=true means data is already on screen
243
+ return (
244
+ <Table
245
+ data={data}
246
+ loading={isFetching && !isPending} // subtle refetch indicator
247
+ columns={columns}
248
+ />
249
+ )
250
+ ```
251
+
252
+ For mutations:
253
+
254
+ ```tsx
255
+ const mutation = useMutation({
256
+ mutationFn: api.create,
257
+ onSuccess: () => {
258
+ notification.success({ title: 'Created' })
259
+ queryClient.invalidateQueries({ queryKey })
260
+ },
261
+ onError: (err) => notification.error({ title: 'Failed', description: err.message }),
262
+ })
263
+
264
+ <Button loading={mutation.isPending} onClick={() => mutation.mutate(formData)}>
265
+ Save
266
+ </Button>
267
+ ```
268
+
269
+ ---
270
+
271
+ ## SecureLayout + route guard pattern
272
+
273
+ ```tsx
274
+ // AppRoutes.tsx
275
+ import { AppShell, SecureLayout } from '@geomak/ui'
276
+ import { Routes, Route, Navigate } from 'react-router-dom'
277
+
278
+ function AppRoutes() {
279
+ return (
280
+ <AppShell topBar={<TopBar />} sidebarSections={sidebarSections}>
281
+ <Routes>
282
+ {/* Auth-gated routes: wrap parent Route with SecureLayout */}
283
+ <Route
284
+ element={
285
+ <SecureLayout
286
+ isAuthenticated={isAuthenticated}
287
+ fallback={<Navigate to="/login" replace />}
288
+ loadingFallback={null}
289
+ />
290
+ }
291
+ >
292
+ <Route path="/dashboard" element={<DashboardPage />} />
293
+ <Route path="/settings" element={<SettingsPage />} />
294
+ </Route>
295
+
296
+ <Route path="/login" element={<LoginPage />} />
297
+ <Route path="/" element={<Navigate to="/dashboard" replace />} />
298
+ </Routes>
299
+ </AppShell>
300
+ )
301
+ }
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Wizard + AppShell onboarding tour
307
+
308
+ Wizard must WRAP AppShell (not be inside it) so it can overlay the full viewport.
309
+ Refs for Wizard steps go on wrapper `<span>` elements inside the `icon` prop of each
310
+ `SidebarItem`, because `SidebarItem` has no `ref` prop.
311
+
312
+ ```tsx
313
+ const dashboardRef = useRef<HTMLSpanElement>(null)
314
+ const settingsRef = useRef<HTMLSpanElement>(null)
315
+
316
+ const sidebarSections = [{
317
+ items: [
318
+ {
319
+ label: 'Dashboard',
320
+ href: '/dashboard',
321
+ icon: <span ref={dashboardRef}><Icon.Home size={18} /></span>,
322
+ },
323
+ {
324
+ label: 'Settings',
325
+ href: '/settings',
326
+ icon: <span ref={settingsRef}><Icon.Settings size={18} /></span>,
327
+ },
328
+ ],
329
+ }]
330
+
331
+ const wizardSteps = [
332
+ { target: dashboardRef, title: 'Dashboard', description: 'Your overview at a glance.' },
333
+ { target: settingsRef, title: 'Settings', description: 'Configure your preferences.' },
334
+ ]
335
+
336
+ <Wizard steps={wizardSteps} storageKey="my-app-tour">
337
+ <AppShell topBar={...} sidebarSections={sidebarSections}>
338
+ <Routes>...</Routes>
339
+ </AppShell>
340
+ </Wizard>
341
+ ```
342
+
343
+ ---
344
+
345
+ ## Page patterns reference
346
+
347
+ | Pattern | Key components |
348
+ |---|---|
349
+ | **CRUD list** | Table + Modal (create/edit) + Form + useForm + PopConfirm + useNotification |
350
+ | **Dashboard overview** | Statistic cards + Skeleton + Dropdown (filter) + optional chart cards |
351
+ | **Settings / admin tabs** | Tabs + Form per panel + Switch/Dropdown + useNotification on save |
352
+ | **Multi-step wizard form** | Stepper + Form (per step or sectioned) + validation before advancing |
353
+ | **Detail / inspection page** | Tabs + Statistic + Timeline + Drawer (row inspector) + Badge |
354
+ | **Authenticated app shell** | ThemeProvider + NotificationProvider + AppShell + SecureLayout + Wizard tour |
355
+
356
+ Use `get_pattern` MCP tool for the full wired recipe (components + state + wiring steps + code example) for any of these.
357
+
358
+ ---
359
+
360
+ ## Key component patterns
361
+
362
+ ### ThemeProvider (required at app root)
363
+
364
+ ```tsx
365
+ import { ThemeProvider } from '@geomak/ui'
366
+
367
+ <ThemeProvider defaultTheme="system">
368
+ <App />
369
+ </ThemeProvider>
370
+ ```
371
+
372
+ ### Modal
373
+
374
+ ```tsx
375
+ import { Modal } from '@geomak/ui'
376
+
377
+ const [open, setOpen] = useState(false)
378
+
379
+ <Modal open={open} onClose={() => setOpen(false)} title="Confirm" onOk={handleOk}>
380
+ <p>Are you sure?</p>
381
+ </Modal>
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Storybook
387
+
388
+ Stories live in `src/**/*.stories.tsx` (CSF3 format). The Storybook dev server
389
+ is in `.claude/launch.json` as `"storybook"` (port 6006).
390
+
391
+ Guide MDX files live in `src/docs/` (one per component).
392
+
393
+ ---
394
+
395
+ ## Repository conventions
396
+
397
+ - Component source: `src/components/{core,inputs,forms,layout,marketing}/`
398
+ - Hooks: `src/hooks/`
399
+ - Story title format: `"Category/ComponentName"` or `"Category/ComponentName/Guide"`
400
+ - All MDX guides use HTML tables (not GFM) with exported `th/td/td0/tbl` style constants
401
+ - Commit convention: `fix:` (patch), `feat:` (minor), `docs:` (no bump); semantic-release runs in CI
402
+ - Never bump `version` in `package.json` manually
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # @geomak/ui · Oxygen Design System
6
6
 
7
- **100+ production-grade React components for enterprise apps** dashboards, CRMs, internal tools, and landing pages. Token-driven, accessible, light/dark first-class, and properly tree-shakeable.
7
+ **100+ production-grade React components for enterprise apps**, dashboards, CRMs, internal tools, and landing pages. Token-driven, accessible, light/dark first-class, and properly tree-shakeable.
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/@geomak/ui?color=0466c8&label=npm)](https://www.npmjs.com/package/@geomak/ui)
10
10
  [![types](https://img.shields.io/npm/types/@geomak/ui?color=0466c8)](https://www.npmjs.com/package/@geomak/ui)
@@ -14,7 +14,7 @@
14
14
 
15
15
  ### ▶ [Browse the live, interactive demo →](https://oxygenui.com)
16
16
 
17
- <!-- Tip: drop a Storybook screen-recording here for the launch docs/assets/preview.gif -->
17
+ <!-- Tip: drop a Storybook screen-recording here for the launch, docs/assets/preview.gif -->
18
18
 
19
19
  </div>
20
20
 
@@ -24,11 +24,11 @@ Built on **React 19**, **Radix UI** (accessibility + behaviour), **Tailwind CSS*
24
24
 
25
25
  ## Why oxygen-ui
26
26
 
27
- - **Token-driven, dark mode first-class.** Every colour, radius, shadow, and motion value is a CSS variable. Light and dark aren't an afterthought both are designed. Re-theme the whole system with one override.
27
+ - **Token-driven, dark mode first-class.** Every colour, radius, shadow, and motion value is a CSS variable. Light and dark aren't an afterthought, both are designed. Re-theme the whole system with one override.
28
28
  - **Accessible by default.** Behaviour comes from Radix (focus traps, keyboard nav, ARIA); icons are `aria-hidden`, controls are labelled.
29
- - **Genuinely tree-shakeable.** Import one icon and ship **0.45 KB** (not the whole set). The entire library is **~76 KB gzipped** with deps external and a CI guard keeps it from regressing.
29
+ - **Genuinely tree-shakeable.** Import one icon and ship **0.45 KB** (not the whole set). The entire library is **~76 KB gzipped** with deps external, and a CI guard keeps it from regressing.
30
30
  - **Strict and tested.** `strict` TypeScript, ESLint at zero warnings, 360+ unit tests, per-export bundle budgets in CI.
31
- - **Batteries included.** Not just buttons a `Scheduler`, a real-time `Chat` (WebSocket-ready), `Table` with pagination, a `Form` engine, an e-commerce `Cart`, and a full **Marketing** kit (hero, pricing, testimonials, lead capture) to build the landing page too.
31
+ - **Batteries included.** Not just buttons, a `Scheduler`, a real-time `Chat` (WebSocket-ready), `Table` with pagination, a `Form` engine, an e-commerce `Cart`, and a full **Marketing** kit (hero, pricing, testimonials, lead capture) to build the landing page too.
32
32
 
33
33
  ---
34
34
 
@@ -64,7 +64,7 @@ import { ChevronDown, Search, createIcon } from '@geomak/ui/icons'
64
64
 
65
65
  ## Components
66
66
 
67
- 100+ components across these groups all with **live controls and a written guide** in [Storybook](https://oxygenui.com).
67
+ 100+ components across these groups, all with **live controls and a written guide** in [Storybook](https://oxygenui.com).
68
68
 
69
69
  | Group | Components |
70
70
  |---|---|
@@ -137,53 +137,93 @@ The standard **gray / slate / zinc** ramps and **black** stay available alongsid
137
137
 
138
138
  ## AI toolchain (Claude Code)
139
139
 
140
- OxygenUI ships a built-in MCP server and a set of Claude Code skills and commands that let AI assistants look up component APIs, search by use-case, and scaffold new components all grounded in the real MDX documentation.
140
+ OxygenUI ships a built-in MCP server and a set of Claude Code skills and commands that let AI assistants look up component APIs, search by use-case, generate complete page components, and bootstrap entire apps, all grounded in the real MDX documentation.
141
+
142
+ ### Setup
143
+
144
+ The toolchain has two parts: the **MCP server** (does the work) and the **commands + skill** (how you call it from Claude Code). Both can be installed at user scope (available in every project on your machine) or project scope (committed to the repo, shared with the whole team).
145
+
146
+ #### Option A — User scope (recommended for individuals)
147
+
148
+ Installs everything into `~/.claude/`. Available in every Claude Code session from that point on.
149
+
150
+ ```bash
151
+ # 1. Install commands + skill + MCP server config in one shot
152
+ npx --package=@geomak/ui@latest setup-claude
153
+
154
+ # If you already have @geomak/ui installed locally:
155
+ node node_modules/@geomak/ui/scripts/setup-claude.mjs
156
+ ```
157
+
158
+ #### Option B — Project scope (recommended for teams)
159
+
160
+ Commits the toolchain into the repo so every developer who clones it gets it automatically.
161
+
162
+ ```bash
163
+ # 1. Install commands + skill + .mcp.json into the project directory
164
+ npx --package=@geomak/ui@latest setup-claude --scope project
165
+
166
+ # If you already have @geomak/ui installed locally:
167
+ node node_modules/@geomak/ui/scripts/setup-claude.mjs --scope project
168
+
169
+ # 2. Commit the generated files so your team gets them on clone
170
+ git add .claude/ .mcp.json
171
+ git commit -m "chore: add OxygenUI Claude Code toolchain"
172
+ ```
173
+
174
+ Both options write a `.mcp.json` / `~/.claude/mcp.json` entry pointing to `https://oxygenui.com/mcp` alongside the commands and skill, so no manual config is needed. Restart Claude Code (or reload the MCP server list) after running.
175
+
176
+ ---
141
177
 
142
178
  ### MCP server
143
179
 
144
- The server is deployed alongside Storybook on Netlify as a Netlify Function at `/mcp`. It exposes four tools:
180
+ The server is deployed alongside Storybook at `https://oxygenui.com/mcp` (Netlify Function). It exposes eight tools in two tiers.
181
+
182
+ **Lookup tier** (docs + tokens):
145
183
 
146
184
  | Tool | What it does |
147
185
  |---|---|
148
186
  | `list_components` | Browse all 100+ components with slug, category, and description |
149
- | `get_component` | Fetch the full props API and usage examples for one component by slug |
187
+ | `get_component` | Full props API and usage examples for one component by slug |
150
188
  | `find_component` | Keyword search across names, categories, and descriptions |
151
189
  | `get_token` | Look up CSS custom properties by name or category prefix |
152
190
 
153
- **Connect it:**
154
-
155
- ```jsonc
156
- // .mcp.json (already in the repo — update the URL after first deploy)
157
- {
158
- "mcpServers": {
159
- "oxygen-ui": {
160
- "type": "http",
161
- "url": "https://your-site.netlify.app/mcp"
162
- },
163
- "oxygen-ui-local": {
164
- "type": "http",
165
- "url": "http://localhost:8888/mcp"
166
- }
167
- }
168
- }
169
- ```
191
+ **Generation tier** (patterns + code):
170
192
 
171
- Or add it from the CLI: `claude mcp add oxygen-ui --transport http https://your-site.netlify.app/mcp`
193
+ | Tool | What it does |
194
+ |---|---|
195
+ | `get_pattern` | Full wired recipe for a page type: components, state, wiring steps, and a complete code example. Patterns: `crud-list`, `dashboard`, `settings-tabs`, `multi-step-form`, `detail-page`, `app-bootstrap` |
196
+ | `get_form_binding` | Correct `useForm` binder for any input (`fieldNative` / `fieldChecked` / `fieldTarget` / `field`), with paste-ready snippet |
197
+ | `compare_components` | Decision guide for similar components: Modal vs Drawer, Table vs DataGrid, Tabs vs SegmentedControl |
198
+ | `get_app_bootstrap` | Full Bootstrap.tsx + AppRoutes.tsx + brandTokens.ts template for a new project |
172
199
 
173
200
  ### Claude Code commands
174
201
 
175
- Four slash commands are registered in `.claude/commands/`:
202
+ Eight slash commands are available after setup:
203
+
204
+ **Lookup commands:**
176
205
 
177
206
  | Command | Usage |
178
207
  |---|---|
179
- | `/ui-lookup <name>` | Fetch the full docs for a component — e.g. `/ui-lookup wizard` |
180
- | `/ui-find <query>` | Search by use-case e.g. `/ui-find virtualized table` |
181
- | `/ui-scaffold <name>` | Scaffold a new component with source + story + MDX guide |
182
- | `/ui-story <name>` | Add story coverage for an existing component |
208
+ | `/ui-find <query>` | Search by use-case, e.g. `/ui-find virtualized table` |
209
+ | `/ui-lookup <name>` | Full docs for a component, e.g. `/ui-lookup wizard` |
210
+
211
+ **Generation commands** (write real files into your project):
212
+
213
+ | Command | Usage |
214
+ |---|---|
215
+ | `/ui-page <type> [entity]` | Scaffold a complete page file. Types: `crud`, `dashboard`, `settings`, `detail`, `multi-step-form`. Example: `/ui-page crud Vessel` |
216
+ | `/ui-bootstrap [name]` | Generate the four-file app bootstrap (Bootstrap.tsx, AppRoutes.tsx, brandTokens.ts, main.tsx) |
217
+ | `/ui-form <field:type ...>` | Generate a fully-wired Form from a field spec, e.g. `/ui-form name:text role:dropdown active:switch` |
218
+ | `/ui-table <entity> [col:type]` | Typed Table with column renderers + actions, e.g. `/ui-table Vessel name:string flag:string status:badge actions:menu` |
219
+ | `/ui-modal <type>` | Complete state + Modal JSX. Types: `confirm-delete`, `form-in-modal`, `detail-view`, `alert` |
220
+ | `/ui-auth-shell [name] [routes]` | Full SecureLayout + AppShell + Wizard tour shell, e.g. `/ui-auth-shell VesOPS dashboard,vessels,settings` |
221
+
222
+ Two additional library commands (`/ui-scaffold`, `/ui-story`) are available inside the `oxygen-ui` repository itself for contributors.
183
223
 
184
224
  ### Context skill
185
225
 
186
- The `/oxygen-ui` skill loads the full design system context into any Claude Code session import patterns, token usage, Tailwind utilities, form API, and repository conventions. Invoke it at the start of any session where you plan to build against `@geomak/ui`.
226
+ The `/oxygen-ui` skill (installed by the setup script) loads the full design system context into any Claude Code session: import patterns, form binder cheat sheet, component decision guide, provider nesting order, React Query integration, and page pattern reference. Invoke it at the start of any session where you plan to build against `@geomak/ui`.
187
227
 
188
228
  ### Local development with the MCP server
189
229
 
@@ -196,7 +236,7 @@ The function is then available at `http://localhost:8888/mcp`. Claude Code picks
196
236
 
197
237
  ### How the manifest is built
198
238
 
199
- At build time, `scripts/generate-ai-manifest.mjs` scans all 101 MDX guide files in `src/docs/` and the co-located MDX files in `src/components/`, strips Storybook boilerplate, and emits `netlify/functions/ai-manifest.json`. The Netlify Function bundles this JSON via esbuild no database, no runtime file I/O, no cold-start penalty.
239
+ At build time, `scripts/generate-ai-manifest.mjs` scans all MDX guide files in `src/docs/` and co-located MDX files in `src/components/`, strips Storybook boilerplate, and emits `netlify/_data/ai-manifest.js`. The Netlify Function bundles this via esbuild at deploy time. No database, no runtime file I/O, no cold-start penalty.
200
240
 
201
241
  ---
202
242
 
@@ -385,5 +385,5 @@ exports.X = X;
385
385
  exports.XCircle = XCircle;
386
386
  exports.createIcon = createIcon;
387
387
  exports.icons_default = icons_default;
388
- //# sourceMappingURL=chunk-4V4U2W7K.cjs.map
389
- //# sourceMappingURL=chunk-4V4U2W7K.cjs.map
388
+ //# sourceMappingURL=chunk-4WD27VQX.cjs.map
389
+ //# sourceMappingURL=chunk-4WD27VQX.cjs.map