Theming
Make your own theme in the builder, the tokens behind it, dark mode, and several themes on one site.
Every component reads its look from CSS variables: the standard shadcn/ui tokens plus a few kit tokens. A theme is a set of values for those variables. Change them and everything restyles at once, down to corner radius, fonts and heading weight.
There are no preset themes to install. Without any changes, you get a neutral default with a blue accent. To make it yours, use the theme builder.
The theme builder
Start from one of a few starting points (Default, Editorial, Swiss, Studio, Terminal), then pick an accent, neutrals, button style, heading and body fonts, radius, shadows and borders. The builder works out both palettes, light and dark, and keeps text readable (WCAG contrast) whatever you choose. While you work, this whole site and every live preview switch to your theme, so you can browse the kit in it. Previews show components or whole templates.
Shuffle picks a random combination to explore from. Undo and Redo (⌘Z / ⇧⌘Z) step through your changes; dragging a slider counts as one step. Reset goes back to the default.
When you like it, the builder gives you three ways to use it:
- CSS: replace the
:rootand.darkblocks in your global stylesheet with the generated ones. - shadcn CLI: download
theme.json, then runnpx shadcn@latest add ./theme.json. The CLI writes the variables into your CSS. - Prompt: paste the instructions into your coding agent.
The builder also lists the font packages to install (self-hosted with @fontsource) and the import lines to add. Copy link saves the theme in a URL, for example /themes?a=38&n=paper&h=instrument-serif. /themes.md lists every parameter.
Dark mode
Dark palettes use the .dark class, like shadcn/ui. ThemeToggle manages it (light, dark or system) and remembers the choice. To force a dark surface inside a light page (a terminal window, a footer), add className="dark" to that element.
Several themes on one site
Your main theme lives on :root. To let visitors switch between looks, scope the others with a data-theme attribute and use the ThemePicker component. A scoped theme only needs the variables it changes:
[data-theme="paper"] {
--background: oklch(0.975 0.01 80);
--foreground: oklch(0.2 0.02 60);
--highlight: oklch(0.55 0.13 38);
--highlight-ink: oklch(0.55 0.13 38);
--font-heading: "Instrument Serif", serif;
--heading-weight: 400;
}<ThemePicker themes={[{ value: "default", label: "Default" }, { value: "paper", label: "Paper" }]} storageKey="theme" />Tokens
The shadcn/ui tokens (background, foreground, card, muted, primary, border, ring…) plus:
In Tailwind they're available as bg-highlight, text-highlight-ink, border-border-hover (the border mixed toward the text color), shadow-card, font-heading and rounded-pill.
Editing by hand
If you tune the variables yourself:
- Keep
--highlight-inkat 4.5:1 or more against--background. If your highlight is a light fill (lime, yellow), make the ink a darker shade of it. - Keep
--muted-foregroundat 4.5:1 or more against--backgroundand--card. - Use one heading family and one body family. Set
--heading-weightto 400 for display serifs and 600–700 for grotesks.