Getting started
Theming
AtroUI’s design system is dark-first: black canvas, brand blue from the hero shader (#0b7bff), Caveat sketch display, Outfit UI, quiet panels, and soft-rect CTAs. After npx shadcn add, tokens live in your host CSS (or a theme sheet you copy), not behind a required npm import.
CSS variables
Light and dark themes live under :root and .dark. Override brand or neutrals to restyle without rewriting components.
.dark {
--brand: oklch(0.62 0.2 255);
--background: oklch(0 0 0);
--primary: oklch(0.99 0 0);
--primary-foreground: oklch(0 0 0);
--font-sans: var(--font-outfit);
}The docs host and Host API consumers can still import atroui/globals.css from the npm package when they already depend on atroui. Pure registry apps should keep tokens in the host stylesheet the CLI/theme setup already owns. See npm → shadcn registry.
Fonts
Two voices on purpose:
- Caveat (sketch) — brand display, stamps, list titles, nav section rails (
.ds-display,.ds-sketch,.ms-stamp,.ds-nav-section). - Outfit (calm UI) — body and supporting copy at regular weight — not ultra-light — so it sits quietly under handwriting (
.ds-lede,.ds-body,.ds-meta,.ds-headline). - Geist Mono — code / technical precision.
On the docs host, load Caveat + Outfit in the root layout and expose --font-caveat / --font-outfit.
/* Token map (already in atroui globals) */
--font-sketch: var(--font-caveat);
--font-display: var(--font-sketch); /* page titles, brand marks */
--font-heading: var(--font-outfit); /* section h2 */
--font-sans: var(--font-outfit); /* body / UI */Radius
One knob. CTAs, stamps, and panels use --radius (and --radius-lg, --radius-md). Default is soft rectangle — not capsules. Circles stay for avatars, status dots, and true toggles.
:root {
/* Soft rect (AtroUI default) */
--radius: 0.875rem;
/* Sharp — set once, CTAs follow */
/* --radius: 0; */
/* Extra soft — still not a pill */
/* --radius: 1.25rem; */
}Want full pills? Edit the installed block — change rounded-lg to rounded-full on that button. We don’t ship a second variant of every block.
Site brand
Chrome strings (name, domain, email, site URL) come from getBrand() after you add @atroui/brand (typically lib/brand.ts). Defaults are AtroUI; override with env:
NEXT_PUBLIC_SITE_NAME=AtroUI
NEXT_PUBLIC_SITE_DOMAIN=atroui.com
NEXT_PUBLIC_SITE_EMAIL=hello@iamk.xyz
NEXT_PUBLIC_SITE_URL=https://www.atroui.comDemo modules may still show studio sample copy - swap CONTENT at the top of each installed block when shipping your own site.
Dark mode
Use next-themes with attribute="class". Add the toggle from the registry: npx shadcn add @atroui/theme-toggle. If flipping to dark hides muted copy or flattens a designed light palette, use Adaptive Theme Switch (@atroui/theme-adapt) instead. It still uses .dark, then lifts type tokens to WCAG AA.
import { ThemeProvider } from "next-themes"
import { ThemeToggle } from "@/components/ui/theme-toggle"
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<ThemeToggle />
{children}
</ThemeProvider>