Templates

Whole pages built only from UISet items: what each one takes, and how to connect your data.

Step 5 of the owner's plan. A template is a whole page built only from UISet items, so a developer starts from a working screen instead of a blank one, and every piece of it stays the same component they'd use by hand. Install one, render it, replace the sample data with yours.

The set (complete-set rule)

What a product team ships before anything domain-specific:

TemplateScreensBuilt from
authSign in, sign up, forgot password, reset password, verify code, and a layoutField, Input, PasswordInput, OtpInput, Checkbox, Button, Card, Alert
dashboardKPI row with trends, filter row (date range, segment), charts, recent activityAppShell, Stat, LineChart, BarChart, SegmentedBar, DataGrid, Select, SegmentedControl
settingsProfile, account and security, notifications, billing with usage, team, danger zoneAppShell, Tabs, Field, Switch, Meter, DataGrid, Dialog, AlertDialog, Toast
adminA records list with create, edit in a drawer, bulk actions and confirmed deleteDataGrid, Drawer, Field, Select, AlertDialog, Toast, EmptyState
inboxFolders, a message list, a reading pane, composeAppShell, Listbox, Badge, Dialog, Textarea, TokenInput, Toast
chat-appThe chat kit as a full page: chats, thread, composerChat kit
pricingA landing section: plans with a monthly/yearly switch, comparison, FAQSegmentedControl, Card, Accordion, Badge
project-boardA project's issues as a board or a list: sprint progress, filters, details, new issueAppShell, PageHeader, Meter, Board kit, DataGrid, SegmentedControl, Dialog, Toast
calendar-appDay, week and month views, a small month to jump, calendars to show or hide, what's nextAppShell, Scheduler kit, Calendar, Checkbox, Tooltip, Toast

The project board and the calendar came with the Board and Scheduler kits (step 6).

Rules for every template

  • Only UISet items. No new behavior lives in a template; if a page needs one, it becomes an item first.
  • Sample data in one place at the top of the file, typed, so replacing it is one edit. Handlers are props (onSignIn, onSave, onDelete) with sample defaults.
  • Responsive down to 360px, with the shell's drawer below 48rem.
  • Agent-operable: every control has a specific name (no two "Save" buttons on one page), destructive actions carry data-agent-confirm, secrets carry data-agent-secret.
  • Forms validate on submit with UI SDK's Field errors, keep what was typed, and focus the first problem. Auth fields carry the right autocomplete (inputHints).
  • Every skin and theme passes axe; each template has a keyboard-only e2e path.
  • Templates are client components whose data arrives as props, so a Server Component (or a loader) can fetch it and pass it in.

Delivery

Each template is a registry block whose files install under components/ui/templates/, importing UISet items relatively, like every other item. The site shows each one live at /templates, in the chosen skin, with its install command.

Use

pnpm dlx shadcn@latest add superzero11/uiset/dashboard

Each template installs to components/ui/templates/<name>.tsx with every item it uses. Render it, then replace its sample data:

TemplateRenderPlug in
auth<SignInForm onSignIn={…} /> and the other four formsEach handler returns nothing on success or a message to show
dashboard<DashboardTemplate orders={…} now={new Date()} />Every figure, chart and row comes from orders; ranges end at now
settings<SettingsTemplate onSave={(section, data) => …} onAction={…} />Each form's FormData by section; onAction for change plan, add seats, update card, change photo
admin<AdminTemplate defaultCustomers={…} onSave={…} onDelete={…} />Reject to keep the drawer open with a message
inbox<InboxTemplate defaultMessages={…} now={new Date()} onSend={…} onMove={…} />Sending and folder moves go to your mail API
chat-app<ChatAppTemplate assistant={…} commands={…} mentions={…} />An async generator of text, reasoning, tool and sources events
pricing<PricingTemplate plans={…} lede={…} />Plans, comparison rows and questions are props; "save n%" comes from the plans
project-board<ProjectBoardTemplate defaultCards={…} defaultLanes={…} columns={…} people={…} labels={…} onMove={…} onSave={…} />Both views share the cards and lanes; the last column counts as done; onCreate and onDelete too
calendar-app<CalendarAppTemplate defaultEvents={…} calendars={…} today={…} now={new Date()} onSave={…} onDelete={…} />Each event names its calendar, and the calendar's chart slot is its color; times are minutes in timeZone
  • Mount <Toaster /> (from toast) once in your app; templates call toast().
  • Inside a page that already has a <main>, pass contentElement="div".
  • Cascade layers: UISet's styles live in layers, so any unlayered CSS in your app wins over them. A global a { color: … } would recolor a button rendered as a link; scope such rules to plain links, like a:not([data-slot]).

Connecting a model to chat-app

tsx
async function* assistant({ text, history, signal }: AssistantInput) {
  const response = await fetch("/api/chat", {
    method: "POST",
    body: JSON.stringify({ text, history }),
    signal,
  })
  const reader = response.body!.pipeThrough(new TextDecoderStream()).getReader()
  for (;;) {
    const { value, done } = await reader.read()
    if (done) return
    yield { type: "text", delta: value } as const
  }
}

With the AI SDK's UI stream, map its parts the same way: text deltas to text, reasoning to reasoning, tool calls and results to tool (same id updates the card), and source parts to sources.

Checked

Every template passes axe in Base (light and dark), Blueprint and Studio, fits a 375px phone without sideways scrolling, and has a keyboard path in the e2e suite. Agents drive them by the names people see: the dashboard's date range, the customers grid, the inbox list, the issue board, the calendar.

  • Project board: the board stays mounted while the list shows, so the card dialog moves cards through it from either view and column limits hold. Each move offers Undo for that card alone.
  • Calendar: EventDialog has no calendar field, so a new event goes on the first calendar that's shown. While the sidebar shows, its New event is the page's one; the toolbar's takes over once the sidebar moves into the drawer, so no two buttons share a name.