Guides

Building with AI agents

VUI ships an agent-ready usage guide so your AI coding assistant produces consistent, token-driven, accessible UI on the first pass instead of reinventing the design system. This page covers using the theme in your own app.

Which guide do I need?

Two scenarios, two homes. When you're using the theme in your own app (this page), your agent reads the package's AGENT.md. When you're contributing to the theme itself, see Contributing (humans) and its odin/engineering/AGENT-VUI.md (agents).

Where the guide lives

In your download, at the root, already at the paths each client reads. There is nothing to install and nothing to copy: unzip the project and your agent finds its rules the first time you open it. The four files below are one guide at four addresses, because Claude Code, Cursor and Copilot each look somewhere different.

already in your download
AGENTS.md            the rules a coding agent follows
CLAUDE.md            the same, at the path Claude Code reads
.cursor/rules/       the same, at the path Cursor reads
.github/copilot-instructions.md

Bringing the theme into a project you already have? Copy those four across with src/vui/. They are plain Markdown and they reference nothing outside the folder.

Two files that are not for you

odin/engineering/AGENT-VUI.md and CONTRIBUTING.md live in the repository this theme is built in, and they are the rules for working on VUI rather than with it. They are not in your download and you do not need them. The AGENTS.md at the root of your download is the one you want.

How do I connect the VUI MCP server?

It is already in your download, at agent/mcp/server.mjs, and .mcp.json at the project root registers it: an agent started in the project picks it up with nothing to install. The server lets an assistant ask direct questions, such as which component family answers a requirement, what a component takes, or which page pattern a screen should start from, instead of reading the source and guessing. It runs over stdio, needs no API key and no network, and answers for the exact version you downloaded.

register the server
# Claude Code
claude mcp add vui -- node ./agent/mcp/server.mjs

# Cursor, Windsurf, or any MCP client (.mcp.json / mcp.json)
{
  "mcpServers": {
    "vui": { "command": "node", "args": ["agent/mcp/server.mjs"] }
  }
}

Your download already has this file

.mcp.json ships at the project root carrying exactly the block above, so a client that reads it needs no setup at all. The commands are here for a client that does not, and for a project you are bringing the theme into.

Eighteen tools come with it, in three groups.

The documentation, offline.

  • list_guides and get_guide: every page of this site as markdown, shipped inside the download, so it works with no network and matches your exact version.
  • search_docs: all of it at once, including AGENTS.md and the README. Call it with no query to get the outline.

What to build with.

  • list_components and get_component: every export with its import specifier, then one component's source, or its props and exported types when the file is large.
  • get_component_props: what a component takes, in every edition, and nothing else. Attributes with their types, defaults and which are required, generated from the declarations rather than written by hand, so they cannot drift from the components. Call it instead of get_component when you need the contract rather than the code: composing a screen costs one small answer here and four hundred lines of source there. With no argument it indexes every component at once.
  • list_blocks and get_block: the marketing blocks, for a landing page rather than a screen.
  • list_pages, get_page and get_screen: whole working screens with their routes, so an agent copies one instead of inventing it.

How to decide. These are the ones that stop an agent guessing.

  • get_design_rules: the rules it must not break, in the form it can check itself against.
  • get_page_pattern and compose_page: which pattern a screen should start from, and the block order for one.
  • search_field_intents: the component that answers a field like “date of birth” or “owner”, so a form is built from the approved input rather than from a plain text box.
  • list_businesses: the workflows the theme already has screens for.
  • plan_app: the screens a whole application needs, before any one of them is built.
  • resolve_ui_spec: a requirement in, a validated page specification out, with each field already mapped to the approved component. This is the one that stops an agent designing the screen itself.

MCP is an addition, not a replacement

Keep the CLAUDE.md pointer above. It loads the rules every session; the MCP server answers the follow-up questions on demand. They read the same files, so the two never disagree.

What the guide enforces

  • Reuse first. Look for an existing component, layout, variant, or utility before creating anything new, and extend before you build.
  • Tokens only. Never hard-code colors, spacing, radius, shadows, or typography. Read the semantic tokens from theme.css (--background, --foreground, --button-primary, …).
  • Follow the page pattern. SetPageTitle → action header with <Breadcrumbs /> → a single scrolling content region (p-4, gap-4).
  • Datatables use RecordView with a fields array, never hand-rolled HTML tables. Charts use ChartContainer plus Recharts with chart tokens.
  • Accessibility and dark mode are mandatory: keyboard nav, visible focus, ARIA, WCAG AA, and both light and dark driven from tokens (no per-component color overrides).
  • Keep business logic out of the UI, prefer Server Components, and always surface loading, empty, success, and error states.

Package exports vs. reference-app patterns

The package ships the primitives: Button, Input, Select, Dialog, Menu, RecordView, ChartContainer, and theme.css. The app-shell pieces the guide references (SetPageTitle, Breadcrumbs, the sidebar and nav-config, and the AuthCard* auth screens) are reference-app patterns to copy from the backoffice demo rather than package exports. The shipped AGENT.mdmakes this distinction explicit so your agent won't invent imports.