Using auri with shadcn
auri is not a shadcn alternative — it is the other lane. shadcn/ui is the chrome humans write: navigation, settings, dialogs. auri is the surfaces agents emit over the wire at runtime. A real product has both, and they should read as one system. This page is the bridge that makes that mechanical.
Why this is easy
auri's Foundation adopts shadcn/ui v4's values on purpose: the same chroma-zero oklch neutrals,
the same hairline-in-light / white-alpha-in-dark border treatment, a radius scale built around
shadcn's own 0.625rem base. On a stock shadcn theme the bridge below is a near no-op
— it starts mattering the moment you customize your theme, because from then on auri follows your
values instead of merely resembling them.
It also works without ceremony because auri's tokens ship at :where() zero specificity
by design — any declaration in your own stylesheet outranks them. Overriding is the supported customization
path, not a fight with the cascade.
The one-variable path
If all you want is auri in your brand color, skip the bridge: set --auri-seed (light) and --auri-seed-dark (dark) and every primary tone
— buttons, focus rings, tinted containers — reseeds from those two values. The full bridge is
for apps that want auri to inherit the whole shadcn theme: ground, cards, borders, radius,
charts.
The bridge, two steps
1 — mirror the dark class. shadcn toggles .dark; auri's renderer
keys off .a2ui-dark. Set both in your theme toggle:
const toggle = () => {
document.documentElement.classList.toggle('dark', isDark);
document.documentElement.classList.toggle('a2ui-dark', isDark); // one added line
}; This flips everything the token bridge doesn't carry — the five intents, skeleton shimmer,
hover/press state layers. Without it, a dark shadcn app would get light-mode intent colors on a
dark ground. (If you use the media-query strategy instead of a class, skip this step — auri's
own prefers-color-scheme block already tracks it.)
2 — paste the token bridge after your shadcn theme. Colors flip with your theme
automatically, because every bridged value points at a shadcn variable that itself changes under .dark:
/* auri ← shadcn bridge — paste after your shadcn theme (e.g. globals.css). */
:root {
--auri-surface: var(--background);
--auri-surface-container: var(--card);
--auri-surface-container-high: var(--muted);
--auri-on-surface: var(--foreground);
--auri-on-surface-variant: var(--muted-foreground);
--auri-outline-variant: var(--border);
--auri-primary: var(--primary);
--auri-on-primary: var(--primary-foreground);
--auri-primary-container: color-mix(in oklab, var(--primary) 10%, var(--background));
--auri-on-primary-container: var(--primary);
--auri-shape-sm: calc(var(--radius) - 4px);
--auri-shape-md: var(--radius);
--auri-shape-lg: calc(var(--radius) + 4px);
/* optional — adopt your chart palette (auri keeps its sixth) */
--auri-chart-1: var(--chart-1);
--auri-chart-2: var(--chart-2);
--auri-chart-3: var(--chart-3);
--auri-chart-4: var(--chart-4);
--auri-chart-5: var(--chart-5);
}
/* Dark tunes the two derived primary tones; scope to your dark selector. */
.dark {
--auri-primary-container: color-mix(in oklab, var(--primary) 16%, var(--background));
--auri-on-primary-container: color-mix(in oklab, var(--primary) 55%, white);
} The mapping
| auri role | shadcn variable | note |
|---|---|---|
--auri-surface | --background | the page ground |
--auri-surface-container | --card | cards: Stat, Chart, ApprovalCard… |
--auri-surface-container-high | --muted | muted fills, code insets |
--auri-on-surface | --foreground | primary text |
--auri-on-surface-variant | --muted-foreground | labels, captions |
--auri-outline-variant | --border | hairlines |
--auri-primary family | --primary family | containers derived via color-mix |
--auri-shape-sm/md/lg | --radius ±4px | shadcn's own calc pattern |
--auri-chart-1…5 | --chart-1…5 | optional; auri keeps its sixth |
What deliberately stays auri
- The five intents.
good / bad / warning / info / neutralis the design signature agents rely on, and shadcn has no counterpart scale —--destructivemaps to roughly one fifth of it. The intent trios stay auri's and flip with.a2ui-dark(step 1). - Input fill. Not bridged because the defaults already agree: transparent hairline inputs in light, translucent white-alpha fills in dark — auri adopted shadcn's treatment outright.
- Motion, skeletons, type roles. No shadcn counterpart exists; they are part of what a catalog promises an agent (in-between states are contract concerns), so they ship with auri.
- Fonts need no bridge. auri components inherit the host font stack — a shadcn
app that sets Geist (or anything else) on
bodyis already done.