Build the interface. Own every line.
Dowel is a source-first React UI system for SaaS and AI products — accessible components, whole-screen blocks and themes that install into your repository as TypeScript you own.
pnpm dlx @dowel-ui/cli initReact 19 · TypeScript · Tailwind CSS 4 · Radix UI
Why Dowel
Not a package to fight. A system you own.
Components, blocks, themes and tooling designed as one — and delivered as source, so nothing between you and the markup is a black box.
Source-first
Every component lands in your repository as a file. Read it, change it, keep it — and
updatecan tell your edits from ours.Accessible by construction
Keyboard, focus and announcements are part of each component, asserted with axe in CI and tested in real screen readers.
Built for AI products
45 components for streaming, reasoning, tool calls, citations and approvals — the parts every AI interface needs.
One token system
OKLCH design tokens and thirteen presets. Re-skin the whole system without opening a single component file.
Source-first
Install it. Then it is yours.
No runtime package sits between you and the markup. The CLI writes real files into your project — the same bytes this site documents.
- 01
Install
One command adds the component and anything it imports.
pnpm dlx @dowel-ui/cli add button - 02
Compose
Import it from your own path, like any file you wrote.
app/page.tsxTSX import { Button } from "@/components/ui/button"; <Button variant="primary">Continue</Button> - 03
Own
The source is in your repository. Change the variants, the markup, anything —
updatewill not overwrite your edits silently.components/ui/button.tsxTSX const buttonVariants = cva( cn( "inline-flex shrink-0 items-center justify-center font-medium whitespace-nowrap select-none", "transition-[background-color,border-color,color,box-shadow,scale,translate] duration-[var(--duration-fast)] ease-[var(--ease-out-quint)]", focusRing, disabledStyles, iconSlot, ), { variants: { variant: { primary: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active", secondary: "bg-secondary text-secondary-foreground hover:bg-accent active:bg-border", outline: "border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground active:bg-secondary", ghost: "text-foreground hover:bg-accent hover:text-accent-foreground active:bg-secondary", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 active:bg-destructive/80", link: "text-primary underline-offset-4 hover:underline", /**
Components · live on this page
Not screenshots. The real components.
Drag the toggle, sweep across the dock, turn the dial. Each one is the code the CLI installs, running the same story its tests run.
…and 272 more, each with its own page
- 3D Carousel
- Account Menu
- Alert
- Aurora Background
- Bottom Nav
- Action Node
- Alert Dialog
- Bar Loader
- Border Beam
- Breadcrumb
- Aspect Morph
- Context Menu
- Dots Loader
- Bubble Background
- Browser Tabs
- Code Block
- Agent Ledger
- Calendar
- Separator
- Avatar Group
- Drawer
- Empty State
- Cosmic Background
- Badge
- Dropdown Menu
- Grid Loader
- Cursor Follow
- Book
- Gooey Popover
- Like Button
- Cursor Spotlight
- Card
- Hover Card
- Meter
- Escape Button
- Card Spread
- Accordion
- Agent Approvals
- Animated Checklist
- Bento Grid
- Button
- Activity Feed
- Agent Data Table
- App Stack
- Collapsible
- Direction Provider
- Chart Sonifier
- Agent Form
- Assignee Picker
- Resizable
- Avatar
- Dialog
- Emoji Reaction
- Confetti Button
- Canvas Toolbar
- Code Tabs
- Agent Replay
- Checkbox
- Command
- Data Table
- Agent Surface
- Color Picker
- Create Menu
- Diff Viewer
- AI Action Ledger
- Combobox
- File Tree
- Dither Area
- AI Agent Plan
- Confirm Typed
- Focus Blur Links
- Dither Bar
AI interfaces
UI infrastructure for AI products.
Conversation, streaming, reasoning, tool calls, citations and approvals — built accessible, so a streamed answer is announced once instead of every token.
Blocks
Whole screens, assembled.
Dashboards, sign-in, pricing, analytics — built from the components, installed with the same command, and yours to edit.
- DashboardAn overview page with headline metrics and a recent activity feed.
- LoginA sign-in form with validation, social providers and a busy state.
- Pricing Three TierThree plans side by side, the middle one featured, under a monthly/annual switch with prices that roll.
- AnalyticsAn analytics page: headline metrics against the previous period, a series over time, and the breakdown that made it up.
Themes
One system. Every brand.
A preset reassigns a handful of semantic tokens; every component follows. Pick one, or build your own from a single colour with contrast checked as you go.
Ship acme-web v2.4
Production · main · 3 changes
data-theme="default"
Playground
Turn the knobs. Copy the code.
Every variant comes from the component's own definition, so the playground cannot offer something the component does not do.
import { Button } from "@/components/ui/button"; export function Continue() { return <Button>Continue</Button>;}Developer experience
Built like infrastructure.
Counted from the registry and measured by the audits; the outside figures refresh hourly. Nothing here is typed in.
A CLI that respects your edits
init, add, update and diff. Every file is hashed when written, so an update never overwrites your changes silently.
Your coding agent already knows it
One command writes the catalogue into AGENTS.md for Claude, Cursor and the rest; an MCP server answers live.
Whole screens, not just parts
59 blocks assemble the components into dashboards, sign-in, billing and AI surfaces.
Your own registry
Serve your organisation's components through the same CLI, extending ours.
Start building
Your next interface starts with one command.
Every component and every free block is MIT, and stays that way. Pro adds whole application surfaces on top.
pnpm dlx @dowel-ui/cli init