# Theming with tweakcn / shadcn

Source: https://lumeo.nativ.sh/docs/tweakcn

# Theming with tweakcn / shadcn

[tweakcn](https://tweakcn.com) is a visual theme editor for the shadcn/ui ecosystem. Lumeo's color tokens are **natively compatible** with it: paste a shadcn / tweakcn `:root` / `.dark` export and the whole library re-skins — **no adapter, no import, no renaming**.

## TL;DR

-   Build a theme at tweakcn, export the Tailwind v4 / CSS-variables form (OKLCH).
-   Paste its `:root` / `.dark` blocks into your app, loaded _after_ `lumeo.css`.
-   Done. **Colors**, **`--radius`**, **spacing**, **tracking**, **fonts** and **shadows** all drive Lumeo 1:1 — Tailwind v4 reads them as variables. Only Lumeo's own status colors have no tweakcn source (see below).

## How it works

shadcn / tweakcn write **unprefixed** variables (`--primary`); Lumeo's components read the Tailwind v4 **`--color-*`** namespace. Lumeo maps the two natively at the source — every token is defined as the shadcn variable with Lumeo's own value as the fallback (no separate adapter or import file involved):

/\* lumeo.css — every color token maps to the shadcn name (built in, no import) \*/
:root {
    --color-primary:    var(--primary,    oklch(0.21 0.006 286));
    --color-background: var(--background, oklch(1 0 0));
    --color-border:     var(--border,     oklch(0.92 0.004 286));
    --color-ring:       var(--ring,       oklch(0.21 0.006 286));
    /\* …every color token, base + dark + all palettes… \*/
    --radius: 0.75rem;   /\* same name as shadcn — nothing to map \*/
}

So if you set `--primary`, it flows straight into `--color-primary` and every `bg-primary` / button / ring picks it up. If you don't, the fallback keeps Lumeo pixel-identical to its defaults — including dark mode and the eight built-in palettes. `--radius` needs no mapping at all: both projects already call it `--radius`.

## Setup

Tailwind v4

@import "./\_content/Lumeo/css/lumeo.css" layer(base);

/\* paste your tweakcn / shadcn export below — that's it \*/
:root { --primary: oklch(0.205 0 0); --radius: 0.625rem; /\* … \*/ }
.dark  { --primary: oklch(0.985 0 0); /\* … \*/ }

Without Tailwind

<link href="\_content/Lumeo/css/lumeo.css" rel="stylesheet" />
<style>
    :root { --primary: oklch(0.205 0 0); /\* tweakcn light vars \*/ }
    .dark { --primary: oklch(0.985 0 0); /\* tweakcn dark vars  \*/ }
</style>

**Load order matters:** your shadcn variables must come _after_ `lumeo.css` so they win the cascade. You can ignore the `@import "tailwindcss"`, `@theme inline` and `@layer base` lines in the tweakcn export — Lumeo already provides those.

## What carries over — and what doesn't

Token group

Carries over

Notes

All colors

Yes

background, foreground, card, popover, primary, secondary, muted, accent, destructive (+ foreground), border, input, ring, chart-1…5, and the full sidebar family — all map 1:1.

`--radius`

Yes

Same name in both. Lumeo derives its own `--radius-sm/md/lg/xl` from it, so set only the master `--radius` (don't paste tweakcn's derived scale).

Spacing & tracking

Yes

Tailwind v4 compiles Lumeo's spacing utilities to `calc(var(--spacing) * n)` and tracking to `letter-spacing: var(--tracking-*)`, so a pasted `--spacing` / `--tracking-*` rescales the whole library. (Verified: doubling `--spacing` doubles every padding/margin/gap.)

Fonts

Yes \*

Lumeo never hard-codes a font — components inherit, and the `font-sans` / `font-mono` utilities resolve `var(--font-sans)` / `var(--font-mono)`. _\* Apply the font on your `<body>` (every tweakcn export does) and it cascades into Lumeo._

Shadows

Yes

Lumeo maps the `shadow-*` utilities to `var(--shadow-*)` (overriding only `--tw-shadow`, so focus-ring composition stays intact), with defaults mirroring Tailwind's scale. A pasted `--shadow-2xs` … `--shadow-2xl` drives every Lumeo elevation 1:1.

Lumeo status colors

No

tweakcn never emits `info` / `success` / `warning` / `positive`, so they keep Lumeo's defaults. Override the `--color-*` directly if a recolored palette clashes.

## Demo: a shadcn palette driving Lumeo

This block sets the bare shadcn names (`--primary` / `--ring`) on one subtree — exactly what a pasted tweakcn export does globally — and Lumeo picks up the teal accent with no extra wiring.

### shadcn accent

Driven by a bare `--primary`, natively.

Primary Outline

## See also

-   [Theme Overrides](docs/theme-overrides) — the underlying CSS-variable system
-   [Theme Switcher](components/theme-switcher) — switching between built-in palettes
-   [tweakcn editor](https://tweakcn.com/editor/theme) — build and export a palette
