Skip to content
FoundationsThemingMenu

Theming

Pick a preset or build your own theme, install it with one command or paste a few variables. OKLCH tokens, one accent, light and dark.

chatcn ships in ink, but every component reads the same set of --chatcn-* variables. Change them once and the whole kit follows: accent, solid buttons, the gray ramp, radii, font and density. Nothing in a component needs editing.

Pick a theme

Sage grays and a deep green for primary actions.

Terminal
pnpm dlx shadcn@latest add https://chatcn.dev/r/theme-forest.json
:root {
  --chatcn-accent: oklch(0.52 0.12 152);
  --chatcn-primary: var(--chatcn-accent);
  /* + a tinted gray ramp */
  /* + large radii */
}
Build your own theme
The runs page is slow. Limit it to the latest 20.
Thought for 4 seconds
Removed: const runs = await getRuns()Added: const runs = await getRuns({ limit: 20 })

Pass a limit of 20 to getRuns so the page stops loading every run.

getRuns() is called without a limit, so every run comes back. I will pass limit: 20 and keep the cursor pagination (opens in a new tab) for older runs.

Want something else? The theme builder tunes accent, gray tint, radius, font, density and contrast on a live agent run, checks the focus ring contrast in both modes and gives you a link to share.

Install a preset

Each preset is a registry item. It installs on top of the base chatcn-theme and writes light and dark values into your global CSS, so dark mode keeps working with the .dark class.

bash
pnpm dlx shadcn@latest add https://chatcn.dev/r/theme-forest.json
PresetItemCharacter
Slatetheme-slateCool blue grays with an ink accent. Quiet and technical.
Cobalttheme-cobaltA clear blue for buttons and focus on a neutral ramp.
Lagoontheme-lagoonTeal accents on cool grays, with softer corners.
Foresttheme-forestSage grays and a deep green for primary actions.
Olivetheme-oliveWarm green grays with an ink accent. Editorial.
Sandtheme-sandPaper warm grays and an amber accent on focus and progress.
Claytheme-clayTerracotta buttons on warm grays, round corners.
Plumtheme-plumMauve grays and a muted plum for the accent.
Contrasttheme-contrastDarker secondary text, stronger hairlines and square corners.

Or paste variables

A theme is plain CSS. Two lines give the kit a brand color: the accent for focus, selection, links, switches and progress, and --chatcn-primary for solid buttons and the send button.

globals.css
:root {
  --chatcn-accent: oklch(0.55 0.2 262);
  --chatcn-primary: var(--chatcn-accent);
}

.dark {
  --chatcn-accent: oklch(0.72 0.18 262);
}

The builder writes the full set for you, including a tinted gray ramp and dark values, and can also print shadcn variables so the rest of your shadcn components match.

What a theme changes

VariablesWhat follows them
--chatcn-accent, --chatcn-accent-fgFocus rings, selection, links, active switches, progress fills
--chatcn-primary, -fg, -hoverSolid buttons and the send button. Ink by default
--chatcn-gray-100 to -1000Text, borders, fills and surfaces. A small tint gives slate, sage or sand grays
--chatcn-bg, -surface, -card, -insetCanvas and raised surfaces
--chatcn-radius-xs to -2xlEvery corner, kept concentric
--font-sans, --font-monoComponents inherit your fonts
--spacing on a wrapperDensity: padding and control heights scale together

The neutral ramp

light
1000.970
2000.950
3000.930
4000.910
5000.860
6000.800
7000.700
8000.525
9000.440
10000.145
dark
1000.195
2000.225
3000.255
4000.285
5000.340
6000.410
7000.500
8000.620
9000.720
10000.970

Semantic tokens

TokenUse
--chatcn-fgPrimary text
--chatcn-fg-mutedSecondary text and icons
--chatcn-fg-subtleTertiary text, placeholders, idle icons
--chatcn-borderHairlines and dividers
--chatcn-cardRaised surfaces: white in light, a lighter gray in dark
--chatcn-insetCode and output wells inside a card
--chatcn-primarySolid buttons and the send button. Ink by default
--chatcn-accentFocus rings, selection, links, active toggles, progress. Ink by default

Status colors

Red marks failures. It appears as a small icon or a short label, never as a fill, and always next to a word that says the same thing. Every other state is told apart by shape and weight. Themes leave status colors alone.

Match your shadcn theme

Prefer your existing palette? Map the chatcn tokens onto shadcn variables after the theme import. To go the other way, copy the shadcn variables from the theme builder.

css
:root {
  --chatcn-fg: var(--foreground);
  --chatcn-fg-muted: var(--muted-foreground);
  --chatcn-border: var(--border);
  --chatcn-card: var(--card);
  --chatcn-primary: var(--primary);
  --chatcn-primary-fg: var(--primary-foreground);
  --chatcn-accent: var(--ring);
}

More on accents, dark mode, density and pairing with NeonKit in Theming in depth.