wunderui-mcp 1.0.2 → 1.1.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.
package/README.md CHANGED
@@ -19,6 +19,10 @@ Works with Claude Code, Cursor, Windsurf, Cline, Codex, VS Code and any other cl
19
19
  | `list_templates` | The full-page templates and what each is built from |
20
20
  | `get_starter` | Copy-paste TSX: app shell, dashboard, data grid, AI chat, theming |
21
21
  | `get_library_info` | Package name, version, install commands, stack, counts, data source |
22
+ | `get_instructions` | The short, always-on rules (components, tokens, motion, copy) for CLAUDE.md / AGENTS.md |
23
+ | `list_skills` | The WunderUI agent skills, free and Pro |
24
+ | `get_skill` | One skill's instructions (SKILL.md), so the agent can follow it without installing — Pro skills need `WUNDERUI_LICENSE_KEY` |
25
+ | `get_block_source` | The React source of a UI block and its shared helpers — needs a Pro key in `WUNDERUI_LICENSE_KEY` |
22
26
 
23
27
  Every component carries its plan. On the Free plan, an agent should only use components marked `free`; the others need WunderUI Core or Pro.
24
28
 
@@ -56,6 +60,7 @@ The server starts with the bundled copy and answers immediately. In the backgrou
56
60
  | --- | --- |
57
61
  | `WUNDERUI_OFFLINE=1` | never touch the network, use the bundled copy |
58
62
  | `WUNDERUI_SITE=<url>` | fetch the live data from another origin |
63
+ | `WUNDERUI_LICENSE_KEY=<key>` | your WunderUI Pro key — unlocks Pro skills (`get_skill`) and block source (`get_block_source`); sent only to wunderui.com |
59
64
 
60
65
  ## Without MCP
61
66
 
package/data/DESIGN.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  > Design context for AI coding agents. Paste this into your prompt, or let your
4
4
  > agent pull it from https://wunderui.com/DESIGN.md.
5
- > Generated from the WunderUI source on 2026-10-08 · @wunderui/react@0.1.0
5
+ > Generated from the WunderUI source on 2026-10-09 · @wunderui/react@0.1.0
6
6
 
7
- WunderUI is a React component library and design system: 201
7
+ WunderUI is a React component library and design system: 204
8
8
  documented components in 6 groups, built on Base UI
9
9
  primitives and Tailwind CSS v4. It covers the parts most kits skip — data grid,
10
10
  kanban, charts, an application shell and a full AI chat set.
@@ -15,7 +15,7 @@ Core and Pro licence holders (the wunderui-core download from the purchase). Not
15
15
 
16
16
  Unzip the wunderui-core download, run `npm install && npm run build` in it once, then in your project: `npm pack <wunderui-core>/packages/react --pack-destination .wunderui` and `npm install ./.wunderui/<the .tgz>`. The wunderui-setup agent skill does all of it.
17
17
 
18
- Do not run `npm install @wunderui/react` — the package is not published, the command fails. Free plan: the 76 free components are MIT source at https://github.com/wunder-ui/wunderui — copy components/, lib/ and styles/wunderui.css into your project (each free component in design.json has a sourceRaw URL). Core and Pro components come with a plan (https://wunderui.com/#pricing).
18
+ Do not run `npm install @wunderui/react` — the package is not published, the command fails. Free plan: the 76 free components are MIT source at https://github.com/wunder-ui/wunderui — add them with `npx wunderui-cli add <name>` (files, dependencies and styles), or copy components/, lib/ and styles/wunderui.css (each free component in design.json has a sourceRaw URL). Core and Pro components come with a plan (https://wunderui.com/#pricing).
19
19
 
20
20
  Then wire up the styles and import:
21
21
 
@@ -314,10 +314,10 @@ Light is `:root`, dark is `.dark`. Same names in both themes.
314
314
  | `--success` | `#1AD598` | `#1AD598` |
315
315
  | `--success-foreground` | `#17181A` | `#17181A` |
316
316
  | `--chart-1` | `var(--brand-600)` | `var(--brand-600)` |
317
- | `--chart-2` | `#F3654A` | `#F3654A` |
318
- | `--chart-3` | `#A584F3` | `#A584F3` |
319
- | `--chart-4` | `#FACA4A` | `#FACA4A` |
320
- | `--chart-5` | `#1AD598` | `#1AD598` |
317
+ | `--chart-2` | `#12AFF0` | `#3CC2F5` |
318
+ | `--chart-3` | `#A584F3` | `#B79CF6` |
319
+ | `--chart-4` | `#1AD598` | `#3DDBA6` |
320
+ | `--chart-5` | `#A2A3A3` | `#6E7078` |
321
321
  | `--sidebar` | `#F9FBFC` | `#17181A` |
322
322
  | `--sidebar-foreground` | `#000000` | `#FFFFFF` |
323
323
  | `--sidebar-primary` | `var(--brand-600)` | `var(--brand-600)` |
@@ -589,10 +589,15 @@ on an `animate-in` the same way it works on a `transition`.
589
589
  4. **Never fade in the LCP element.** An element at `opacity: 0` is not an LCP candidate, so a 600ms hero fade adds 600ms to your LCP. Render headline copy at full opacity; animate `transform` only.
590
590
  5. **Restrain the travel.** Anything anchored to a trigger moves `--travel-xs` or `--travel-sm`. A menu that slides 20px looks like it fell in.
591
591
  6. **One overshoot per screen.** `ease-overshoot` is punctuation. Two of them on one view and the interface reads as a toy.
592
- 7. **Reduced motion is opt-in, not a kill switch.** Wrap the animation in `@media (prefers-reduced-motion: no-preference)` so the still state is the default and you cannot forget a selector.
592
+ 7. **Reduced motion is opt-in, not a kill switch.** Wrap the animation in `@media (prefers-reduced-motion: no-preference)` so the still state is the default and you cannot forget a selector. Reduced means calmer, not nothing: drop transforms and travel, keep opacity and colour changes (rule 15).
593
593
  8. **Never `transition-all`.** Name the properties — `transition-[opacity,transform]` — or use bare `transition`, which covers colour, shadow, transform and opacity but no layout property. `transition-all` animates things you did not mean to animate, including on first paint.
594
594
  9. **Loading keeps its height.** A skeleton occupies the same box as the content it stands in for, and crossfades — it never collapses and reflows.
595
595
  10. **A looping ambient animation is the one place `ease-in-out` belongs.** A shimmer that runs forever has no entrance and no exit, so symmetry is correct there and nowhere else.
596
+ 11. **Animate by frequency.** Keyboard-driven and 100+/day actions (command palette, shortcuts, moving between tooltips) get no motion; tens a day get a short fade; rare moments may delight. Tooltips skip their entrance when another one was just open (`data-open:data-instant:animate-none`).
597
+ 12. **Anchored surfaces grow from their trigger.** Popover, dropdown, tooltip, hover card and select use `origin-(--transform-origin)`. Never start from `scale(0)` — start at 0.92–0.97 with opacity. Centred dialogs are exempt.
598
+ 13. **Toggles stay interruptible.** Animate switches, checkboxes, tabs and other repeated state changes with transitions — they retarget from wherever they are — never with keyframes bound to the state, which restart from zero. An overshoot transition (`transition-transform duration-base ease-overshoot`) still swings past the end.
599
+ 14. **Hover only where hover exists.** Tailwind v4's `hover:` is already gated to `(hover: hover)`; hand-written `:hover` in CSS goes inside `@media (hover: hover) and (pointer: fine)`, so a tap on a phone does not leave a hover state stuck.
600
+ 15. **Reduced motion keeps the fade.** WunderUI's global rule zeroes the scale, slide, spin and blur of every `animate-in` / `animate-out` and every transform transition, and keeps opacity and colour — so do not add `motion-reduce:transition-none` or `motion-reduce:animate-none` to a fade.
596
601
 
597
602
  ### Motion recipes
598
603
 
@@ -651,9 +656,39 @@ on an `animate-in` the same way it works on a `transition`.
651
656
  }
652
657
  ```
653
658
 
659
+ ## Copy
660
+
661
+ Rules for the words inside the product — buttons, labels, errors and empty states.
662
+
663
+ 1. **Buttons say what happens.** A verb and, where it helps, the object: `Save changes`, `Invite member`, `Delete project` — never `OK`, `Submit` or `Yes`. The destructive button repeats the action, the other one is `Cancel`.
664
+ 2. **Sentence case everywhere in the product.** Buttons, menu items, headings, labels and tabs start with one capital: `Billing history`, not `Billing History`.
665
+ 3. **Errors say what happened and what to do.** `The card was declined. Try another card or contact your bank.` — no `Oops`, no `Something went wrong` on its own, no blame, no error codes without words.
666
+ 4. **Empty states explain and offer one action.** What will appear here, why it is empty, and the one button that fills it: `No invoices yet — your first one appears after the first payment.`
667
+ 5. **Labels are nouns, hints are sentences.** A field label names the thing (`Work email`); help text under it explains a rule in a full sentence.
668
+ 6. **Numbers carry their unit.** Money with the ISO currency or symbol and two decimals (`$299.00`, `EUR 41.80`), percentages with `%`, durations and sizes with units (`12 GB`, `3 min`). Use tabular numbers in tables.
669
+ 7. **No filler.** No `please`, `simply`, `just` or `easily`; no exclamation marks in the interface; no `Lorem ipsum`. Sample people are invented (`Alina Lorenz`, `Felix Brandt`).
670
+ 8. **Confirmations name the object.** `Delete “Q4 report”?` with what is lost, not `Are you sure?`.
671
+
672
+ ## Skills
673
+
674
+ Agent skills that build and check with these rules (https://wunderui.com/skills):
675
+
676
+ - **wunderui-screen** (Free) — Builds a complete React screen with WunderUI from a one-sentence request, within the user's plan (Free uses only the free components) — picks the components and a matching block layout, fills props from design.json, adds the empty, loading and error states that generated screens usually forget, uses motion tokens instead of raw milliseconds, and finishes with a typecheck and a build.
677
+ - **wunderui-setup** (Free) — Sets up WunderUI in a React project from scratch to the first rendered screen — detects the framework, Tailwind version and existing tokens, puts DESIGN.md and design.json into the project, registers the WunderUI MCP server, wires styles.css and the @source path, renders a probe component and writes a setup report.
678
+ - **wunderui-theme** (Free) — Generates a complete WunderUI brand theme from one brand colour (hex) — optionally an accent colour, a radius preference and a font — the eleven-step brand scale (--brand-50 … --brand-1000), the brand tokens derived from it (primary, primary-foreground, text-link, ring, tint and tint text, chart 1) for light and dark, a WCAG AA check of every key pair with shades moved automatically until they pass, and one CSS file to import after @wunderui/react/styles.css (globally or for one subtree), plus a report.
679
+ - **wunderui-token-check** (Free) — Finds hard-coded colours, spacing and radii that bypass the WunderUI design tokens, maps each literal to the nearest token with a measured distance (ΔE for colour, px for spacing and radius), separates safe swaps from values too far from any token, replaces the safe ones and reports how much the look changed.
680
+ - **wunderui-a11y** (Pro) — Accessibility check per component or screen in a WunderUI project — renders every variant, walks the focus order and checks that focus is visible, measures WCAG AA contrast of every text in light and dark, verifies the reduced-motion fallback, and delivers each finding with a patch instead of just a report.
681
+ - **wunderui-agent-ui** (Pro) — Builds the interface of an AI agent with WunderUI's agent components — describes the run (steps, tools, costs, approvals), picks RunTimeline, ApprovalCard, CostMeter, AgentStatus, RunError and their relatives, plays through every state including failure and abort, applies the agent motion tokens and checks the approval moment separately.
682
+ - **wunderui-compose** (Pro) — Composes WunderUI blocks into a complete page — clarifies the page's goal and audience, proposes a block order that follows the visitor's questions, inserts the blocks and fills them with real content, checks the rhythm (one notable effect per section) and protects the LCP element from entrance animation.
683
+ - **wunderui-figma-screen** (Pro) — Builds a screen in Figma from the WunderUI library — real component instances instead of drawn rectangles, every fill and text bound to the theme variables and text styles, auto layout throughout, a light frame first, then the dark frame as a clone with the Dark mode and a 390 px mobile frame — and checks the result with screenshots and an audit (unbound paints, unstyled text, absolute children).
684
+ - **wunderui-figma-sync** (Pro) — Keeps Figma variables and the project's CSS tokens (styles.css) identical in both directions — reads the Figma variable collections and text styles through the Figma MCP server, diffs them against the CSS custom properties (colour per light/dark mode, spacing, radius, type, motion), lists every conflict with the measured difference, asks which side wins and writes only in that direction, then reports what changed.
685
+ - **wunderui-motion-audit** (Pro) — Audits a codebase's animations and transitions against the WunderUI motion rules — transition-all, raw millisecond durations, ease-in-out and other generic curves, scroll-driven animations without an @supports fallback, missing prefers-reduced-motion handling, layout-property animation and fades on the LCP element — justifies every finding with the rule from DESIGN.md, proposes and applies a patch with motion tokens and verifies the build.
686
+ - **wunderui-refactor** (Pro) — Migrates an existing React app to WunderUI — scans the project and detects the UI stack per file (shadcn/ui, Radix primitives, MUI, Chakra, Headless UI, Mantine, hand-built components and hard-coded Tailwind colours), maps every component to its WunderUI equivalent with prop notes, writes a migration plan with effort and order, applies the safe codemods (shadcn imports → @wunderui/react, raw colours → token utilities) and measures before → after (raw colours, foreign UI imports, WunderUI coverage) with the project's typecheck.
687
+ - **wunderui-uiux-design-auditor** (Pro) — Evidence-based UI/UX and accessibility audit of any product — live websites, landing pages, component libraries / front-end code (React, Vue, Svelte, HTML/CSS, Tailwind) and Figma files — against a 497-rule catalog (WCAG 2.2 A/AA, platform guidance, design-system rules).
688
+
654
689
  ## Component inventory
655
690
 
656
- **Plans.** 76 components are **Free** (MIT, source at https://github.com/wunder-ui/wunderui); 125 are **Pro** and need WunderUI Core or Pro — charts, KPI cards, the data grid, the app layout and navigation, AI & agents. On the Free plan, build only with components marked Free and name the Pro component that would do the job better.
691
+ **Plans.** 76 components are **Free** (MIT, source at https://github.com/wunder-ui/wunderui); 128 are **Pro** and need WunderUI Core or Pro — charts, KPI cards, the data grid, the app layout and navigation, AI & agents. On the Free plan, build only with components marked Free and name the Pro component that would do the job better.
657
692
 
658
693
  ### Primitives
659
694
 
@@ -730,6 +765,9 @@ on an `animate-in` the same way it works on a `transition`.
730
765
  | `Sparkline` | Pro | A tiny trend line without axes — green when it rises, red when it falls — for table cells, price cards and metric tiles. | SparklineProps |
731
766
  | `FunnelChart` | Pro | Shows drop-off across sequential stages, each with a label and value. | — |
732
767
  | `ColumnChart` | Pro | Vertical bars for comparing categories side by side. | — |
768
+ | `Heatmap` | Pro | A grid of rounded cells whose shade shows how much happened — commits per day, tickets per hour, deploys per week. | HeatmapCell, HeatmapProps |
769
+ | `StatusStrip` | Pro | A row of day bars from a status page — green when all was well, amber when degraded, red for an outage. | StatusStripDay, StatusStripProps, StatusStripStatus |
770
+ | `Gauge` | Pro | One value against its limit on a half circle, with a needle that swings in and re-aims with a spring. | GaugeProps, GaugeSegment |
733
771
 
734
772
  ### Data Display
735
773
 
@@ -1481,7 +1519,9 @@ function Tabs({ className, orientation, ...props }: Tabs.Root.Props): React.JSX.
1481
1519
  A gradient-filled area chart for visualizing trends over time.
1482
1520
 
1483
1521
  ```tsx
1484
- <AreaChart data={data} index="month" categories={["revenue", "cost"]} />
1522
+ <ChartCard title="Revenue" value="$84,250" delta={{ value: "18.2%", caption: "vs last year" }} periods={["12M", "30D"]}>
1523
+ <AreaChart data={data} index="month" categories={["revenue"]} height={200} />
1524
+ </ChartCard>
1485
1525
  ```
1486
1526
 
1487
1527
  ```ts
@@ -1493,11 +1533,13 @@ function AreaChart({ data, index, categories, colors, height, stacked, curveType
1493
1533
  Compares categorical data with grouped or stacked bars.
1494
1534
 
1495
1535
  ```tsx
1496
- <BarChart data={data} index="month" categories={["revenue", "cost"]} stacked={false} />
1536
+ <ChartCard title="Active users" value="349k" delta={{ value: "6.4%", caption: "this week" }} periods={["Week", "Month"]}>
1537
+ <BarChart data={data} index="day" categories={["users"]} height={200} highlight={3} />
1538
+ </ChartCard>
1497
1539
  ```
1498
1540
 
1499
1541
  ```ts
1500
- function BarChart({ data, index, categories, colors, height, layout, stacked, stackGap, radius, barSize, maxBarSize, barGap, lollipop, segments, background, showGrid, showAxis, showTooltip, showLegend, yAxisFormatter, yDomain, yTicks, valueFormatter, animate, loading, className, }: BarChartProps): React.JSX.Element;
1542
+ function BarChart({ data, index, categories, colors, height, layout, stacked, stackGap, radius, barSize, maxBarSize, barGap, lollipop, segments, background, showGrid, showAxis, showTooltip, showLegend, yAxisFormatter, yDomain, yTicks, valueFormatter, animate, highlight, loading, className, }: BarChartProps): React.JSX.Element;
1501
1543
  ```
1502
1544
 
1503
1545
  #### LineChart
@@ -1505,7 +1547,9 @@ function BarChart({ data, index, categories, colors, height, layout, stacked, st
1505
1547
  Plots one or more series as smooth or linear lines.
1506
1548
 
1507
1549
  ```tsx
1508
- <LineChart data={data} index="month" categories={["revenue", "cost"]} curved />
1550
+ <ChartCard title="Monthly revenue" value="$94k" delta={{ value: "46.9%", caption: "vs 2025" }} legend={[{ label: "2026" }, { label: "2025", color: "var(--chart-5)" }]}>
1551
+ <LineChart data={data} index="month" categories={["y2026", "y2025"]} colors={["var(--chart-1)", "var(--chart-5)"]} dashed={["y2025"]} height={200} />
1552
+ </ChartCard>
1509
1553
  ```
1510
1554
 
1511
1555
  ```ts
@@ -1517,7 +1561,9 @@ function LineChart({ data, index, categories, colors, height, showGrid, showAxis
1517
1561
  Combines bars and a trend line in a single chart.
1518
1562
 
1519
1563
  ```tsx
1520
- <ComposedChart data={data} index="month" bars={["revenue"]} lines={["cost"]} />
1564
+ <ChartCard title="Revenue and cost" value="$365k" delta={{ value: "12.8%", caption: "margin up" }} legend={[{ label: "Revenue" }, { label: "Cost", color: "var(--chart-2)" }]}>
1565
+ <ComposedChart data={data} index="month" bars={["revenue"]} lines={["cost"]} height={200} />
1566
+ </ChartCard>
1521
1567
  ```
1522
1568
 
1523
1569
  ```ts
@@ -1529,7 +1575,9 @@ function ComposedChart({ data, index, bars, lines, colors, height, showGrid, sho
1529
1575
  Shows proportions of a whole, with an optional donut mode.
1530
1576
 
1531
1577
  ```tsx
1532
- <PieChart data={[{ name: "Direct", value: 42 }]} donut />
1578
+ <ChartCard title="Traffic sources" description="Last 30 days">
1579
+ <PieChart data={data} variant="donut" legend="right" height={180} centerLabel={{ label: "Visits", value: "48,230" }} cornerRadius={4} />
1580
+ </ChartCard>
1533
1581
  ```
1534
1582
 
1535
1583
  ```ts
@@ -1541,7 +1589,9 @@ function PieChart({ data, colors, height, donut, variant, innerRadius, paddingAn
1541
1589
  Compares multiple series across shared axes on a polar grid.
1542
1590
 
1543
1591
  ```tsx
1544
- <RadarChart data={data} index="metric" categories={["a", "b"]} />
1592
+ <ChartCard title="Team profile" description="Two teams compared" legend={[{ label: "Team A" }, { label: "Team B", color: "var(--chart-2)" }]}>
1593
+ <RadarChart data={data} index="metric" categories={["a", "b"]} height={240} />
1594
+ </ChartCard>
1545
1595
  ```
1546
1596
 
1547
1597
  ```ts
@@ -1553,7 +1603,9 @@ function RadarChart({ data, index, categories, colors, height, showTooltip, fill
1553
1603
  A circular progress-style chart for a single goal value.
1554
1604
 
1555
1605
  ```tsx
1556
- <RadialChart data={[{ name: "Goal", value: 72 }]} />
1606
+ <ChartCard title="Quarterly goal" value="72%" description="$360k of $500k · 23 days left">
1607
+ <RadialChart data={[{ name: "Goal", value: 72 }]} height={200} />
1608
+ </ChartCard>
1557
1609
  ```
1558
1610
 
1559
1611
  ```ts
@@ -1647,6 +1699,30 @@ import { ColumnChart } from "@wunderui/react"
1647
1699
  <ColumnChart data={data} index="month" categories={["revenue", "cost"]} />
1648
1700
  ```
1649
1701
 
1702
+ #### Heatmap
1703
+
1704
+ A grid of rounded cells whose shade shows how much happened — commits per day, tickets per hour, deploys per week.
1705
+
1706
+ ```ts
1707
+ function Heatmap({ data, rowLabels, columnLabels, max, levels, color, cellSize, gap, legend, valueFormatter, cellLabel, animate, tooltip, onCellHover, className, "aria-label": ariaLabel, }: HeatmapProps): React.JSX.Element;
1708
+ ```
1709
+
1710
+ #### StatusStrip
1711
+
1712
+ A row of day bars from a status page — green when all was well, amber when degraded, red for an outage.
1713
+
1714
+ ```ts
1715
+ function StatusStrip({ days, startLabel, endLabel, height, animate, tooltip, onDayHover, className, "aria-label": ariaLabel, }: StatusStripProps): React.JSX.Element;
1716
+ ```
1717
+
1718
+ #### Gauge
1719
+
1720
+ One value against its limit on a half circle, with a needle that swings in and re-aims with a spring.
1721
+
1722
+ ```ts
1723
+ function Gauge({ value, max, label, format, minLabel, maxLabel, color, dangerAt, ticks, size, animate, className, "aria-label": ariaLabel, }: GaugeProps): React.JSX.Element;
1724
+ ```
1725
+
1650
1726
  #### Agenda
1651
1727
 
1652
1728
  A time-ordered list of scheduled events.
@@ -0,0 +1,52 @@
1
+ # WunderUI — instructions for your coding agent
2
+
3
+ Paste this into CLAUDE.md, AGENTS.md or .cursor/rules. It is the short, always-on version;
4
+ the full context is https://wunderui.com/DESIGN.md and the MCP server answers everything else
5
+ (`claude mcp add wunderui -- npx -y wunderui-mcp`).
6
+
7
+ ## Always
8
+ - Never hardcode colours.
9
+ - Theme by overriding tokens, not by restyling components.
10
+ - Dark mode is a `.dark` class on `<html>`.
11
+ - The package is client code.
12
+ - Import from the package root, never from `dist/` or `src/` paths.
13
+ - `cn` is not re-exported — import it from the `cn` package directly.
14
+ - Prefer a composite over rebuilding one.
15
+ - Charts take a `loading` prop; do not build your own skeleton.
16
+ - A KPI chart ends on the trend line.
17
+ - Motion comes from tokens too.
18
+ - Agent UI has its own components.
19
+ - Before writing UI by hand, look up the component: the Task → component table in DESIGN.md, or the MCP tool `list_components`.
20
+
21
+ ## Motion
22
+ - Duration and easing are class names, not numbers.
23
+ - Only `transform` and `opacity`.
24
+ - Entrances decelerate, exits accelerate.
25
+ - Never fade in the LCP element.
26
+ - Restrain the travel.
27
+ - One overshoot per screen.
28
+ - Reduced motion is opt-in, not a kill switch.
29
+ - Never `transition-all`.
30
+ - Loading keeps its height.
31
+ - A looping ambient animation is the one place `ease-in-out` belongs.
32
+ - Animate by frequency.
33
+ - Anchored surfaces grow from their trigger.
34
+ - Toggles stay interruptible.
35
+ - Hover only where hover exists.
36
+ - Reduced motion keeps the fade.
37
+
38
+ ## Copy
39
+ - Buttons say what happens.
40
+ - Sentence case everywhere in the product.
41
+ - Errors say what happened and what to do.
42
+ - Empty states explain and offer one action.
43
+ - Labels are nouns, hints are sentences.
44
+ - Numbers carry their unit.
45
+ - No filler.
46
+ - Confirmations name the object.
47
+
48
+ ## Before you finish
49
+ - Run the free skills `wunderui-token-check` (no raw colours) and, with Pro, `wunderui-motion-audit` and `wunderui-a11y` on the files you changed.
50
+ - Check light, dark and 390 px.
51
+
52
+ https://wunderui.com/DESIGN.md · https://wunderui.com/skills · https://wunderui.com/llms-full.txt
package/data/design.json CHANGED
@@ -4,12 +4,12 @@
4
4
  "version": "0.1.0",
5
5
  "description": "WunderUI — a design system and component library for React.",
6
6
  "site": "https://wunderui.com",
7
- "generatedAt": "2026-10-08",
7
+ "generatedAt": "2026-10-09",
8
8
  "install": {
9
9
  "available": "Core and Pro licence holders (the wunderui-core download from the purchase). Not on the public npm registry.",
10
10
  "package": "Unzip the wunderui-core download, run `npm install && npm run build` in it once, then in your project: `npm pack <wunderui-core>/packages/react --pack-destination .wunderui` and `npm install ./.wunderui/<the .tgz>`. The wunderui-setup agent skill does all of it.",
11
11
  "doNot": "Do not run `npm install @wunderui/react` — the package is not published, the command fails.",
12
- "free": "Free plan: the 76 free components are MIT source at https://github.com/wunder-ui/wunderui — copy components/, lib/ and styles/wunderui.css into your project (each free component in design.json has a sourceRaw URL). Core and Pro components come with a plan (https://wunderui.com/#pricing).",
12
+ "free": "Free plan: the 76 free components are MIT source at https://github.com/wunder-ui/wunderui — add them with `npx wunderui-cli add <name>` (files, dependencies and styles), or copy components/, lib/ and styles/wunderui.css (each free component in design.json has a sourceRaw URL). Core and Pro components come with a plan (https://wunderui.com/#pricing).",
13
13
  "import": "import { Button, Card } from \"@wunderui/react\"",
14
14
  "styles": "@import \"@wunderui/react/styles.css\";"
15
15
  },
@@ -20,12 +20,12 @@
20
20
  "charts": "recharts"
21
21
  },
22
22
  "counts": {
23
- "components": 201,
23
+ "components": 204,
24
24
  "categories": 12,
25
- "exports": 594,
25
+ "exports": 603,
26
26
  "templates": 5,
27
27
  "free": 76,
28
- "pro": 125
28
+ "pro": 128
29
29
  },
30
30
  "plans": {
31
31
  "free": "WunderUI Free: the components with tier \"free\" are open source under the MIT License (https://github.com/wunder-ui/wunderui) — any project, commercial included. Every \"pro\" component needs WunderUI Core or Pro.",
@@ -69,10 +69,10 @@
69
69
  "--success": "#1AD598",
70
70
  "--success-foreground": "#17181A",
71
71
  "--chart-1": "var(--brand-600)",
72
- "--chart-2": "#F3654A",
72
+ "--chart-2": "#12AFF0",
73
73
  "--chart-3": "#A584F3",
74
- "--chart-4": "#FACA4A",
75
- "--chart-5": "#1AD598",
74
+ "--chart-4": "#1AD598",
75
+ "--chart-5": "#A2A3A3",
76
76
  "--radius": "0.75rem",
77
77
  "--sidebar": "#F9FBFC",
78
78
  "--sidebar-foreground": "#000000",
@@ -288,10 +288,10 @@
288
288
  "--success": "#1AD598",
289
289
  "--success-foreground": "#17181A",
290
290
  "--chart-1": "var(--brand-600)",
291
- "--chart-2": "#F3654A",
292
- "--chart-3": "#A584F3",
293
- "--chart-4": "#FACA4A",
294
- "--chart-5": "#1AD598",
291
+ "--chart-2": "#3CC2F5",
292
+ "--chart-3": "#B79CF6",
293
+ "--chart-4": "#3DDBA6",
294
+ "--chart-5": "#6E7078",
295
295
  "--sidebar": "#17181A",
296
296
  "--sidebar-foreground": "#FFFFFF",
297
297
  "--sidebar-primary": "var(--brand-600)",
@@ -422,10 +422,15 @@
422
422
  "**Never fade in the LCP element.** An element at `opacity: 0` is not an LCP candidate, so a 600ms hero fade adds 600ms to your LCP. Render headline copy at full opacity; animate `transform` only.",
423
423
  "**Restrain the travel.** Anything anchored to a trigger moves `--travel-xs` or `--travel-sm`. A menu that slides 20px looks like it fell in.",
424
424
  "**One overshoot per screen.** `ease-overshoot` is punctuation. Two of them on one view and the interface reads as a toy.",
425
- "**Reduced motion is opt-in, not a kill switch.** Wrap the animation in `@media (prefers-reduced-motion: no-preference)` so the still state is the default and you cannot forget a selector.",
425
+ "**Reduced motion is opt-in, not a kill switch.** Wrap the animation in `@media (prefers-reduced-motion: no-preference)` so the still state is the default and you cannot forget a selector. Reduced means calmer, not nothing: drop transforms and travel, keep opacity and colour changes (rule 15).",
426
426
  "**Never `transition-all`.** Name the properties — `transition-[opacity,transform]` — or use bare `transition`, which covers colour, shadow, transform and opacity but no layout property. `transition-all` animates things you did not mean to animate, including on first paint.",
427
427
  "**Loading keeps its height.** A skeleton occupies the same box as the content it stands in for, and crossfades — it never collapses and reflows.",
428
- "**A looping ambient animation is the one place `ease-in-out` belongs.** A shimmer that runs forever has no entrance and no exit, so symmetry is correct there and nowhere else."
428
+ "**A looping ambient animation is the one place `ease-in-out` belongs.** A shimmer that runs forever has no entrance and no exit, so symmetry is correct there and nowhere else.",
429
+ "**Animate by frequency.** Keyboard-driven and 100+/day actions (command palette, shortcuts, moving between tooltips) get no motion; tens a day get a short fade; rare moments may delight. Tooltips skip their entrance when another one was just open (`data-open:data-instant:animate-none`).",
430
+ "**Anchored surfaces grow from their trigger.** Popover, dropdown, tooltip, hover card and select use `origin-(--transform-origin)`. Never start from `scale(0)` — start at 0.92–0.97 with opacity. Centred dialogs are exempt.",
431
+ "**Toggles stay interruptible.** Animate switches, checkboxes, tabs and other repeated state changes with transitions — they retarget from wherever they are — never with keyframes bound to the state, which restart from zero. An overshoot transition (`transition-transform duration-base ease-overshoot`) still swings past the end.",
432
+ "**Hover only where hover exists.** Tailwind v4's `hover:` is already gated to `(hover: hover)`; hand-written `:hover` in CSS goes inside `@media (hover: hover) and (pointer: fine)`, so a tap on a phone does not leave a hover state stuck.",
433
+ "**Reduced motion keeps the fade.** WunderUI's global rule zeroes the scale, slide, spin and blur of every `animate-in` / `animate-out` and every transform transition, and keeps opacity and colour — so do not add `motion-reduce:transition-none` or `motion-reduce:animate-none` to a fade."
429
434
  ],
430
435
  "recipes": {
431
436
  "Overlay enter and exit": "/* Dialog, sheet, popover, dropdown, context menu — one pattern for all of them.\n Base UI exposes data-open / data-closed; tw-animate-css turns them into keyframes. */\n<Dialog.Popup className=\"\n data-open:animate-in data-open:fade-in-0 data-open:zoom-in-92\n data-open:slide-in-from-bottom-2\n data-open:duration-slow data-open:ease-overshoot\n data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-96\n data-closed:duration-fast data-closed:ease-exit\n\" />",
@@ -1118,7 +1123,7 @@
1118
1123
  "AreaChart"
1119
1124
  ],
1120
1125
  "props": "function AreaChart({ data, index, categories, colors, height, stacked, curveType, variant, fillOpacity, dashed, outline, fillOnly, strokeWidth, strokeWidths, showGrid, showAxis, showTooltip, showLegend, yDomain, baseline, yTicks, xTicks, xAxisFormatter, sparkline, yAxisFormatter, valueFormatter, animate, loading, className, }: AreaChartProps): React.JSX.Element;",
1121
- "example": "<AreaChart data={data} index=\"month\" categories={[\"revenue\", \"cost\"]} />",
1126
+ "example": "<ChartCard title=\"Revenue\" value=\"$84,250\" delta={{ value: \"18.2%\", caption: \"vs last year\" }} periods={[\"12M\", \"30D\"]}>\n <AreaChart data={data} index=\"month\" categories={[\"revenue\"]} height={200} />\n</ChartCard>",
1122
1127
  "docs": "https://wunderui.com/components/area-chart"
1123
1128
  },
1124
1129
  {
@@ -1131,8 +1136,8 @@
1131
1136
  "exports": [
1132
1137
  "BarChart"
1133
1138
  ],
1134
- "props": "function BarChart({ data, index, categories, colors, height, layout, stacked, stackGap, radius, barSize, maxBarSize, barGap, lollipop, segments, background, showGrid, showAxis, showTooltip, showLegend, yAxisFormatter, yDomain, yTicks, valueFormatter, animate, loading, className, }: BarChartProps): React.JSX.Element;",
1135
- "example": "<BarChart data={data} index=\"month\" categories={[\"revenue\", \"cost\"]} stacked={false} />",
1139
+ "props": "function BarChart({ data, index, categories, colors, height, layout, stacked, stackGap, radius, barSize, maxBarSize, barGap, lollipop, segments, background, showGrid, showAxis, showTooltip, showLegend, yAxisFormatter, yDomain, yTicks, valueFormatter, animate, highlight, loading, className, }: BarChartProps): React.JSX.Element;",
1140
+ "example": "<ChartCard title=\"Active users\" value=\"349k\" delta={{ value: \"6.4%\", caption: \"this week\" }} periods={[\"Week\", \"Month\"]}>\n <BarChart data={data} index=\"day\" categories={[\"users\"]} height={200} highlight={3} />\n</ChartCard>",
1136
1141
  "docs": "https://wunderui.com/components/bar-chart"
1137
1142
  },
1138
1143
  {
@@ -1147,7 +1152,7 @@
1147
1152
  "LineChartReferenceLine"
1148
1153
  ],
1149
1154
  "props": "function LineChart({ data, index, categories, colors, height, showGrid, showAxis, showXAxis, showTooltip, showLegend, showDots, endDot, curved, curveType, dashed, area, strokeWidth, strokeWidths, xTicks, xAxisFormatter, yDomain, yTicks, activeIndex, referenceLines, yAxisFormatter, valueFormatter, animate, loading, className, }: LineChartProps): React.JSX.Element;",
1150
- "example": "<LineChart data={data} index=\"month\" categories={[\"revenue\", \"cost\"]} curved />",
1155
+ "example": "<ChartCard title=\"Monthly revenue\" value=\"$94k\" delta={{ value: \"46.9%\", caption: \"vs 2025\" }} legend={[{ label: \"2026\" }, { label: \"2025\", color: \"var(--chart-5)\" }]}>\n <LineChart data={data} index=\"month\" categories={[\"y2026\", \"y2025\"]} colors={[\"var(--chart-1)\", \"var(--chart-5)\"]} dashed={[\"y2025\"]} height={200} />\n</ChartCard>",
1151
1156
  "docs": "https://wunderui.com/components/line-chart"
1152
1157
  },
1153
1158
  {
@@ -1161,7 +1166,7 @@
1161
1166
  "ComposedChart"
1162
1167
  ],
1163
1168
  "props": "function ComposedChart({ data, index, bars, lines, colors, height, showGrid, showAxis, showTooltip, valueFormatter, animate, loading, className, }: ComposedChartProps): React.JSX.Element;",
1164
- "example": "<ComposedChart data={data} index=\"month\" bars={[\"revenue\"]} lines={[\"cost\"]} />",
1169
+ "example": "<ChartCard title=\"Revenue and cost\" value=\"$365k\" delta={{ value: \"12.8%\", caption: \"margin up\" }} legend={[{ label: \"Revenue\" }, { label: \"Cost\", color: \"var(--chart-2)\" }]}>\n <ComposedChart data={data} index=\"month\" bars={[\"revenue\"]} lines={[\"cost\"]} height={200} />\n</ChartCard>",
1165
1170
  "docs": "https://wunderui.com/components/composed-chart"
1166
1171
  },
1167
1172
  {
@@ -1175,7 +1180,7 @@
1175
1180
  "PieChart"
1176
1181
  ],
1177
1182
  "props": "function PieChart({ data, colors, height, donut, variant, innerRadius, paddingAngle, cornerRadius, startAngle, endAngle, track, centerLabel, legend, showLabel, showTooltip, valueFormatter, animate, loading, className, }: PieChartProps): React.JSX.Element;",
1178
- "example": "<PieChart data={[{ name: \"Direct\", value: 42 }]} donut />",
1183
+ "example": "<ChartCard title=\"Traffic sources\" description=\"Last 30 days\">\n <PieChart data={data} variant=\"donut\" legend=\"right\" height={180} centerLabel={{ label: \"Visits\", value: \"48,230\" }} cornerRadius={4} />\n</ChartCard>",
1179
1184
  "docs": "https://wunderui.com/components/pie-chart"
1180
1185
  },
1181
1186
  {
@@ -1189,7 +1194,7 @@
1189
1194
  "RadarChart"
1190
1195
  ],
1191
1196
  "props": "function RadarChart({ data, index, categories, colors, height, showTooltip, fillOpacity, showDots, animate, loading, className, }: RadarChartProps): React.JSX.Element;",
1192
- "example": "<RadarChart data={data} index=\"metric\" categories={[\"a\", \"b\"]} />",
1197
+ "example": "<ChartCard title=\"Team profile\" description=\"Two teams compared\" legend={[{ label: \"Team A\" }, { label: \"Team B\", color: \"var(--chart-2)\" }]}>\n <RadarChart data={data} index=\"metric\" categories={[\"a\", \"b\"]} height={240} />\n</ChartCard>",
1193
1198
  "docs": "https://wunderui.com/components/radar-chart"
1194
1199
  },
1195
1200
  {
@@ -1203,7 +1208,7 @@
1203
1208
  "RadialChart"
1204
1209
  ],
1205
1210
  "props": "function RadialChart({ data, colors, height, showTooltip, innerRadius, centerLabel, animate, loading, className, }: RadialChartProps): React.JSX.Element;",
1206
- "example": "<RadialChart data={[{ name: \"Goal\", value: 72 }]} />",
1211
+ "example": "<ChartCard title=\"Quarterly goal\" value=\"72%\" description=\"$360k of $500k · 23 days left\">\n <RadialChart data={[{ name: \"Goal\", value: 72 }]} height={200} />\n</ChartCard>",
1207
1212
  "docs": "https://wunderui.com/components/radial-chart"
1208
1213
  },
1209
1214
  {
@@ -1291,6 +1296,55 @@
1291
1296
  "example": "import { ColumnChart } from \"@wunderui/react\"\n\n<ColumnChart data={data} index=\"month\" categories={[\"revenue\", \"cost\"]} />",
1292
1297
  "docs": "https://wunderui.com/components/column-chart"
1293
1298
  },
1299
+ {
1300
+ "slug": "heatmap",
1301
+ "title": "Heatmap",
1302
+ "category": "Charts",
1303
+ "description": "A grid of rounded cells whose shade shows how much happened — commits per day, tickets per hour, deploys per week.",
1304
+ "group": "Data & Charts",
1305
+ "tier": "pro",
1306
+ "exports": [
1307
+ "Heatmap",
1308
+ "HeatmapCell",
1309
+ "HeatmapProps"
1310
+ ],
1311
+ "props": "function Heatmap({ data, rowLabels, columnLabels, max, levels, color, cellSize, gap, legend, valueFormatter, cellLabel, animate, tooltip, onCellHover, className, \"aria-label\": ariaLabel, }: HeatmapProps): React.JSX.Element;",
1312
+ "example": null,
1313
+ "docs": "https://wunderui.com/components/heatmap"
1314
+ },
1315
+ {
1316
+ "slug": "status-strip",
1317
+ "title": "Status Strip",
1318
+ "category": "Charts",
1319
+ "description": "A row of day bars from a status page — green when all was well, amber when degraded, red for an outage.",
1320
+ "group": "Data & Charts",
1321
+ "tier": "pro",
1322
+ "exports": [
1323
+ "StatusStrip",
1324
+ "StatusStripDay",
1325
+ "StatusStripProps",
1326
+ "StatusStripStatus"
1327
+ ],
1328
+ "props": "function StatusStrip({ days, startLabel, endLabel, height, animate, tooltip, onDayHover, className, \"aria-label\": ariaLabel, }: StatusStripProps): React.JSX.Element;",
1329
+ "example": null,
1330
+ "docs": "https://wunderui.com/components/status-strip"
1331
+ },
1332
+ {
1333
+ "slug": "gauge",
1334
+ "title": "Gauge",
1335
+ "category": "Charts",
1336
+ "description": "One value against its limit on a half circle, with a needle that swings in and re-aims with a spring.",
1337
+ "group": "Data & Charts",
1338
+ "tier": "pro",
1339
+ "exports": [
1340
+ "Gauge",
1341
+ "GaugeProps",
1342
+ "GaugeSegment"
1343
+ ],
1344
+ "props": "function Gauge({ value, max, label, format, minLabel, maxLabel, color, dangerAt, ticks, size, animate, className, \"aria-label\": ariaLabel, }: GaugeProps): React.JSX.Element;",
1345
+ "example": null,
1346
+ "docs": "https://wunderui.com/components/gauge"
1347
+ },
1294
1348
  {
1295
1349
  "slug": "agenda",
1296
1350
  "title": "Agenda",
@@ -3773,5 +3827,79 @@
3773
3827
  ],
3774
3828
  "url": "https://wunderui.com/templates/sign-in"
3775
3829
  }
3830
+ ],
3831
+ "skills": [
3832
+ {
3833
+ "name": "wunderui-screen",
3834
+ "tier": "free",
3835
+ "group": "free",
3836
+ "description": "Builds a complete React screen with WunderUI from a one-sentence request, within the user's plan (Free uses only the free components) — picks the components and a matching block layout, fills props from design.json, adds the empty, loading and error states that generated screens usually forget, uses motion tokens instead of raw milliseconds, and finishes with a typecheck and a build. Use when the user asks for a page, screen, view, dashboard, settings page, table view, form or similar in a project that uses WunderUI (@wunderui/react)."
3837
+ },
3838
+ {
3839
+ "name": "wunderui-setup",
3840
+ "tier": "free",
3841
+ "group": "free",
3842
+ "description": "Sets up WunderUI in a React project from scratch to the first rendered screen — detects the framework, Tailwind version and existing tokens, puts DESIGN.md and design.json into the project, registers the WunderUI MCP server, wires styles.css and the @source path, renders a probe component and writes a setup report. Use when the user wants to install, add, set up or connect WunderUI (or \"@wunderui/react\") in a project, or asks why WunderUI components render unstyled."
3843
+ },
3844
+ {
3845
+ "name": "wunderui-theme",
3846
+ "tier": "free",
3847
+ "group": "free",
3848
+ "description": "Generates a complete WunderUI brand theme from one brand colour (hex) — optionally an accent colour, a radius preference and a font — the eleven-step brand scale (--brand-50 … --brand-1000), the brand tokens derived from it (primary, primary-foreground, text-link, ring, tint and tint text, chart 1) for light and dark, a WCAG AA check of every key pair with shades moved automatically until they pass, and one CSS file to import after @wunderui/react/styles.css (globally or for one subtree), plus a report. Use when the user wants to rebrand, theme or white-label WunderUI, use their own brand / primary / accent colour, change the radius or font of the library, asks for a \"design system from my colour\", or wants to check an existing WunderUI theme file for contrast."
3849
+ },
3850
+ {
3851
+ "name": "wunderui-token-check",
3852
+ "tier": "free",
3853
+ "group": "free",
3854
+ "description": "Finds hard-coded colours, spacing and radii that bypass the WunderUI design tokens, maps each literal to the nearest token with a measured distance (ΔE for colour, px for spacing and radius), separates safe swaps from values too far from any token, replaces the safe ones and reports how much the look changed. Use when the user asks to check or clean up tokens, remove hardcoded colours/hex values, make a codebase use the design system, or before a theming or dark-mode change in a WunderUI project."
3855
+ },
3856
+ {
3857
+ "name": "wunderui-a11y",
3858
+ "tier": "pro",
3859
+ "group": "coding",
3860
+ "description": "Accessibility check per component or screen in a WunderUI project — renders every variant, walks the focus order and checks that focus is visible, measures WCAG AA contrast of every text in light and dark, verifies the reduced-motion fallback, and delivers each finding with a patch instead of just a report. Use when the user asks for an accessibility or a11y check, WCAG contrast, keyboard or focus review, or a reduced-motion check of a component, page or pull request."
3861
+ },
3862
+ {
3863
+ "name": "wunderui-agent-ui",
3864
+ "tier": "pro",
3865
+ "group": "coding",
3866
+ "description": "Builds the interface of an AI agent with WunderUI's agent components — describes the run (steps, tools, costs, approvals), picks RunTimeline, ApprovalCard, CostMeter, AgentStatus, RunError and their relatives, plays through every state including failure and abort, applies the agent motion tokens and checks the approval moment separately. Use when the user asks for an agent run view, an agent dashboard, a tool-call transcript, a human-in-the-loop approval, a cost or usage view, or any UI that shows what an AI agent is doing, in a project that uses @wunderui/react."
3867
+ },
3868
+ {
3869
+ "name": "wunderui-compose",
3870
+ "tier": "pro",
3871
+ "group": "coding",
3872
+ "description": "Composes WunderUI blocks into a complete page — clarifies the page's goal and audience, proposes a block order that follows the visitor's questions, inserts the blocks and fills them with real content, checks the rhythm (one notable effect per section) and protects the LCP element from entrance animation. Use when the user asks for a landing page, marketing page, pricing page, product page, about page or any multi-section page assembled from WunderUI blocks or sections."
3873
+ },
3874
+ {
3875
+ "name": "wunderui-figma-screen",
3876
+ "tier": "pro",
3877
+ "group": "figma",
3878
+ "description": "Builds a screen in Figma from the WunderUI library — real component instances instead of drawn rectangles, every fill and text bound to the theme variables and text styles, auto layout throughout, a light frame first, then the dark frame as a clone with the Dark mode and a 390 px mobile frame — and checks the result with screenshots and an audit (unbound paints, unstyled text, absolute children). Use when the user asks to design, mock up or build a screen, page or dashboard in Figma with WunderUI, or to turn a React screen or a description into a Figma frame."
3879
+ },
3880
+ {
3881
+ "name": "wunderui-figma-sync",
3882
+ "tier": "pro",
3883
+ "group": "figma",
3884
+ "description": "Keeps Figma variables and the project's CSS tokens (styles.css) identical in both directions — reads the Figma variable collections and text styles through the Figma MCP server, diffs them against the CSS custom properties (colour per light/dark mode, spacing, radius, type, motion), lists every conflict with the measured difference, asks which side wins and writes only in that direction, then reports what changed. Use when the user asks to sync Figma and code, compare design tokens with Figma, update styles.css from Figma, push token changes into Figma, or check for design↔code drift in a WunderUI project."
3885
+ },
3886
+ {
3887
+ "name": "wunderui-motion-audit",
3888
+ "tier": "pro",
3889
+ "group": "coding",
3890
+ "description": "Audits a codebase's animations and transitions against the WunderUI motion rules — transition-all, raw millisecond durations, ease-in-out and other generic curves, scroll-driven animations without an @supports fallback, missing prefers-reduced-motion handling, layout-property animation and fades on the LCP element — justifies every finding with the rule from DESIGN.md, proposes and applies a patch with motion tokens and verifies the build. Use when the user asks for a motion or animation audit, wants transitions to feel less generic, asks about reduced motion, or before shipping UI built with WunderUI."
3891
+ },
3892
+ {
3893
+ "name": "wunderui-refactor",
3894
+ "tier": "pro",
3895
+ "group": "coding",
3896
+ "description": "Migrates an existing React app to WunderUI — scans the project and detects the UI stack per file (shadcn/ui, Radix primitives, MUI, Chakra, Headless UI, Mantine, hand-built components and hard-coded Tailwind colours), maps every component to its WunderUI equivalent with prop notes, writes a migration plan with effort and order, applies the safe codemods (shadcn imports → @wunderui/react, raw colours → token utilities) and measures before → after (raw colours, foreign UI imports, WunderUI coverage) with the project's typecheck. Use when the user wants to switch to WunderUI, migrate or refactor an app from shadcn, MUI, Chakra, Mantine or Headless UI, replace a component library, estimate how much work a switch is, or asks \"how do I move this project to WunderUI\"."
3897
+ },
3898
+ {
3899
+ "name": "wunderui-uiux-design-auditor",
3900
+ "tier": "pro",
3901
+ "group": null,
3902
+ "description": "Evidence-based UI/UX and accessibility audit of any product — live websites, landing pages, component libraries / front-end code (React, Vue, Svelte, HTML/CSS, Tailwind) and Figma files — against a 497-rule catalog (WCAG 2.2 A/AA, platform guidance, design-system rules). Produces findings with evidence, severity and acceptance criteria, a coverage matrix, a change plan and a client-ready HTML report. Read-only. Use when the user asks for a UI/UX audit, accessibility or WCAG check, design review, landing-page review, design-system or Figma audit, design↔code (token) comparison, or a re-check after fixes."
3903
+ }
3776
3904
  ]
3777
3905
  }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "wunderui-mcp",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
+ "mcpName": "io.github.Kl-webmedia/wunderui-mcp",
4
5
  "description": "MCP server that gives AI coding agents the WunderUI design system: tokens, component props, templates and starters. Works with Claude Code, Cursor, Windsurf, Cline and Codex.",
5
6
  "keywords": [
6
7
  "mcp",
package/src/index.mjs CHANGED
@@ -373,6 +373,88 @@ server.registerTool(
373
373
  })
374
374
  )
375
375
 
376
+ /* ---------------------------------------------- skills, instructions, Pro */
377
+
378
+ const siteUrl = () => (process.env.WUNDERUI_SITE ?? design.site ?? "https://wunderui.com").replace(/\/$/, "")
379
+ const licenseKey = () => process.env.WUNDERUI_LICENSE_KEY?.trim() || null
380
+ const authHeaders = () => (licenseKey() ? { authorization: `Bearer ${licenseKey()}` } : {})
381
+ let instructions = null
382
+ try {
383
+ instructions = readFileSync(resolve(dataDir, "INSTRUCTIONS.md"), "utf8")
384
+ } catch {}
385
+
386
+ server.registerTool(
387
+ "get_instructions",
388
+ {
389
+ title: "Get the short WunderUI rules",
390
+ description:
391
+ "The short, always-on rules for building with WunderUI (components, tokens, motion, copy) — the text to keep in CLAUDE.md / AGENTS.md. Read this first; use get_design_md for the full context.",
392
+ inputSchema: {},
393
+ },
394
+ async () => {
395
+ if (instructions) return text(instructions)
396
+ const r = await fetch(`${siteUrl()}/INSTRUCTIONS.md`, { signal: AbortSignal.timeout(8000) }).catch(() => null)
397
+ return text(r?.ok ? await r.text() : "INSTRUCTIONS.md is not available offline; use get_design_md.")
398
+ }
399
+ )
400
+
401
+ server.registerTool(
402
+ "list_skills",
403
+ {
404
+ title: "List WunderUI agent skills",
405
+ description:
406
+ "The agent skills that build and check with WunderUI (set up a project, build screens, theme from a brand colour, migrate from shadcn/MUI/Chakra, token check, motion and accessibility audits, Figma). Free skills work for everyone; Pro skills need WUNDERUI_LICENSE_KEY.",
407
+ inputSchema: {},
408
+ },
409
+ async () =>
410
+ text({
411
+ licenseKeySet: Boolean(licenseKey()),
412
+ skills: (design.skills ?? []).map((skill) => ({ name: skill.name, tier: skill.tier, description: skill.description })),
413
+ use: "get_skill({ name }) returns the skill's instructions so you can follow them without installing it.",
414
+ })
415
+ )
416
+
417
+ server.registerTool(
418
+ "get_skill",
419
+ {
420
+ title: "Get a WunderUI agent skill",
421
+ description:
422
+ "Returns one skill's instructions (its SKILL.md) from wunderui.com, so the agent can follow the workflow without installing the skill. Pro skills are sent only with a valid Pro key in WUNDERUI_LICENSE_KEY. Scripts the skill mentions come with the installed skill (wunderui.com/skills).",
423
+ inputSchema: { name: z.string().describe("Skill name, e.g. wunderui-theme or wunderui-screen") },
424
+ },
425
+ async ({ name }) => {
426
+ const r = await fetch(`${siteUrl()}/api/skills/${encodeURIComponent(name)}`, { headers: authHeaders(), signal: AbortSignal.timeout(10000) }).catch(() => null)
427
+ if (!r) return text("wunderui.com is not reachable — install the skill from https://wunderui.com/skills instead.")
428
+ const body = await r.json().catch(() => null)
429
+ if (r.status === 401) return text(`${name} is a Pro skill. Set WUNDERUI_LICENSE_KEY to your WunderUI Pro key (https://wunderui.com/#pricing).`)
430
+ if (!r.ok || !body?.skill) return text(`No skill called "${name}". Available: ${(design.skills ?? []).map((s) => s.name).join(", ")}`)
431
+ return text(body.skill)
432
+ }
433
+ )
434
+
435
+ server.registerTool(
436
+ "get_block_source",
437
+ {
438
+ title: "Get a WunderUI block's source (Pro)",
439
+ description:
440
+ "The React source of a UI block (e.g. category 'app', block 'billing'), optionally one screen, plus the shared helpers it imports. Needs a WunderUI Pro key in WUNDERUI_LICENSE_KEY. Use https://wunderui.com/api/registry/index to see every block.",
441
+ inputSchema: {
442
+ category: z.string(),
443
+ block: z.string(),
444
+ screen: z.string().optional(),
445
+ },
446
+ },
447
+ async ({ category, block, screen }) => {
448
+ if (!licenseKey()) return text("Blocks come with WunderUI Pro. Set WUNDERUI_LICENSE_KEY to your Pro key (https://wunderui.com/#pricing), or browse the free previews at https://wunderui.com/blocks.")
449
+ const url = `${siteUrl()}/api/registry/block/${encodeURIComponent(category)}/${encodeURIComponent(block)}${screen ? `?screen=${encodeURIComponent(screen)}` : ""}`
450
+ const r = await fetch(url, { headers: authHeaders(), signal: AbortSignal.timeout(15000) }).catch(() => null)
451
+ if (!r) return text("wunderui.com is not reachable.")
452
+ if (r.status === 401) return text("The key was not accepted for blocks (blocks need a Pro key).")
453
+ if (!r.ok) return text(`No block ${category}/${block}${screen ? ` screen ${screen}` : ""}.`)
454
+ return text(await r.json())
455
+ }
456
+ )
457
+
376
458
  /* --------------------------------------------------------------------- run */
377
459
 
378
460
  async function main() {