genui-mockup
by noah-vh
README.md
# Gen UI Mockup Tool (L1)
**Fast, low-token UI wireframing and design iteration with Claude.**
Normally, asking Claude to mock up a UI means one of two things: bad ASCII art, or an entire
HTML/JSX page hand-written from scratch — hundreds of lines, thousands of output tokens, tens of
seconds of streaming, every single time, even for a layout it's "drawn" a dozen times before.
This tool takes a different approach. Claude composes the mockup in a compact, line-oriented
language ([OpenUI Lang](https://www.openui.com/docs/openui-lang/overview)) that references a
fixed, pre-registered palette of 42 real shadcn/ui primitives — buttons, cards, tables, forms,
plus page-level layout primitives like `Container`/`PageHeader`/`AppShell`. It isn't *your* design
system or a general-purpose exporter — it's one specific, registered shadcn/ui palette this tool
ships with. A full page comes out to roughly 15–40 lines instead of hundreds, renders live in a
connected browser in well under a second, and — because the model can only reference primitives
that are actually registered — never contains invented markup.
## What it's like to use
Ask Claude (through the MCP tools below) to mock something up — "a pricing page," "a settings
screen," "a dashboard with a sidebar." It renders live in the browser tab you have open,
typically in tens of milliseconds. Ask for a tweak and only the changed lines get re-sent, not the
whole page, so iterating stays cheap and fast. Every version is auto-saved under a stable id, so
you can rename it, switch between saved designs instantly in the sidebar, come back to one later,
or delete the ones you don't want. Once you like something, ask Claude to write the actual
React/shadcn code for it — see [Getting code out](#getting-code-out-way-2) below.
## Key features
- **Live, in-browser rendering** — ask, watch it render in well under a second.
- **Low-token by design** — a full page is ~15–40 lines of a compact language, not hundreds of
lines of hand-written markup.
- **Always real components** — every element comes from the registered shadcn/ui palette; nothing
invented, nothing off-system.
- **Assemblies persist automatically** — rename, revisit, switch between, or delete saved designs
without a separate save step.
- **Code on demand** — ask for the code once you're happy with something; no export button, no
separate build step.
See the full design rationale and roadmap in
[`docs/superpowers/specs/2026-07-11-genui-mockup-tool-design.md`](docs/superpowers/specs/2026-07-11-genui-mockup-tool-design.md).
## Setup
### Prerequisites
- Node.js `>=24` (see root `package.json` `engines`)
### Install & build
```bash
npm install
npm run build
```
`npm run build` runs `build` in every workspace (`packages/*`, `apps/*`) via `npm run build
--workspaces --if-present` — this compiles `@genui/core` → `@genui/mcp` → `@genui/preview` in
turn.
### Running it
#### 1. Start the preview
```bash
npm run dev:preview
```
This root script first builds `@genui/core` (`npm run build -w @genui/core`) and then starts the
preview's Vite dev server (`npm run dev -w @genui/preview`). The core build is required up front
because the preview imports `@genui/core/browser` from its compiled `dist/` output, not from
source. Open the URL Vite prints (typically `http://localhost:5173`).
#### 2. Register the MCP server with Claude
The MCP server isn't started manually — it's launched by the MCP client (Claude). Local stdio
servers like this one are configured via JSON, not a URL — this is a project-scoped dev tool
(paired to this repo's live preview and its `data/assemblies` folder), not a hosted/remote
capability, so JSON config is the correct mechanism, not a legacy one.
**Claude Code** picks this up automatically from the root `.mcp.json` (relative paths are fine —
Claude Code runs from the repo root):
```json
{
"mcpServers": {
"genui-mockup": {
"command": "node",
"args": ["packages/mcp/dist/server.js"],
"env": { "WS_PORT": "7337", "DATA_DIR": "./data/assemblies" }
}
}
}
```
**Claude Desktop** requires an entry in `claude_desktop_config.json` — but Desktop does *not* run
from this repo's directory, so **paths must be absolute**, not the relative ones above:
```json
{
"mcpServers": {
"genui-mockup": {
"command": "/absolute/path/to/node",
"args": ["/absolute/path/to/this/repo/packages/mcp/dist/server.js"],
"env": {
"WS_PORT": "7337",
"DATA_DIR": "/absolute/path/to/this/repo/data/assemblies"
}
}
}
}
```
Find your `node` path with `which node`. The config file lives at
`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
`%APPDATA%\Claude\claude_desktop_config.json` (Windows). Fully quit and relaunch Claude Desktop
(not just close the window) after editing it.
Either way, a Claude session gets the five `genui-mockup` tools below once connected. The server
spawns a WebSocket bridge on `WS_PORT` (7337) that the preview connects to, and persists
assemblies as JSON files under `DATA_DIR`.
**Only run the server from one client at a time** — it's a single process binding port 7337, so
starting it from both Claude Code and Claude Desktop simultaneously will fail on the second one.
#### Operational note — reload the preview after (re)starting the server
The preview's WS client connects once on mount and does **not** auto-reconnect. Each new MCP
client session spawns a fresh `packages/mcp/dist/server.js` process — i.e. a fresh bridge on
port 7337 — so if the server restarts after the preview tab is already open, **reload the
preview tab once the server is back up** to pick up the new bridge connection. The preview must
be open and connected for `render_assembly` to succeed; otherwise it correctly reports "No
preview connected."
## The five MCP tools
- `list_primitives` — returns the shadcn primitive list, param signatures, and the OpenUI Lang
system prompt Claude must follow (including the lang→shadcn code mappings — see below).
- `render_assembly(lang, id?, name?)` — renders an OpenUI Lang assembly live in the connected web
preview. Every render is auto-persisted. **Omit `id`** to start a new assembly (its id is
returned — reuse it on later calls to keep editing the same design in place instead of creating
a duplicate). **Pass `id`** to update that existing assembly's tree (and optionally rename it) in
place. `name` is optional and can be set/changed on any call — that's how naming/"saving" works,
there's no separate save tool.
- `list_assemblies()` — lists saved assemblies (id, name, createdAt, updatedAt). If a user
references an existing design ambiguously by name, call this first and ask them to clarify
rather than guessing which one they mean.
- `get_assembly(id)` — fetches a saved assembly's OpenUI Lang source by id (used for Way 2 code
generation — see below).
- `delete_assembly(id)` — deletes a saved assembly by id. Deleting something already gone isn't an
error.
## Getting code out (Way 2)
There's no export button. To get real source for a saved assembly, ask Claude to
`get_assembly <id>` and write the corresponding React/shadcn code from the returned OpenUI Lang.
The non-obvious lang→shadcn translations (e.g. OpenUI's `Button` variant `"primary"` mapping to
shadcn's `variant="default"`, since shadcn has no `"primary"` variant; the `Table` row pipe
encoding; the `CardHeader` → `CardTitle`/`CardDescription` split) are documented directly in the
system prompt returned by `list_primitives`, so this works even for a Claude session with **only**
the MCP tools and no repo file access. When Claude *does* have repo access (e.g. Claude Code
running inside this repo), it can additionally cross-check against
`apps/preview/src/library/renderers.tsx` and `apps/preview/src/library/layout-renderers.tsx`
directly for full fidelity.
## Repo layout
- `packages/core` — library/palette definitions (42 primitives), OpenUI Lang parsing, the assembly store.
- `packages/mcp` — the MCP server (`server.ts`) exposing the five tools, plus the WS bridge to the preview.
- `apps/preview` — the Vite/React web preview that renders assemblies live via the shadcn library
(atom renderers in `library/renderers.tsx`, page-level layout renderers in
`library/layout-renderers.tsx`).
- `docs/` — the design spec and supporting verification notes.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues