Laurel

Use with shadcn

Install the package, import one CSS file, and every stock shadcn/ui component renders as Laurel.

Prerequisite: a React app with Tailwind CSS v4 (Next.js, Vite, …).

Install the package

The package is published to GitHub Packages, scoped @ralekocode. Add to your project's .npmrc:

.npmrc
@ralekocode:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

GITHUB_TOKEN is a PAT with read:packages (or authenticate with npm login --registry=https://npm.pkg.github.com --scope=@ralekocode). Then:

npm i @ralekocode/design-system
Initialise shadcn
npx shadcn@latest init

Choose the Mira style and keep CSS variables on (tailwind.cssVariables: true). Base colour does not matter — Laurel replaces every colour variable — but it cannot be changed later, so pick neutral. Point tailwind.css at your global stylesheet.

init writes its own :root, .dark, @theme inline and @layer base blocks into that stylesheet. Delete those generated blocks and replace them with the import in the next step. If you keep them, put the Laurel import after them so Laurel's values win.

Import the theme
app/globals.css
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@import "@ralekocode/design-system/theme.css";

theme.css is the standard shadcn theme: :root and .dark variable blocks (--primary, --border, --ring, …), Tailwind's @theme inline (bg-primary, rounded-md, font-sans, …), the dark variant and the base layer. It does not import Tailwind itself.

Add components
npx shadcn@latest add button card dialog select tabs

Every component is stock shadcn. Nothing to restyle: colours, radius, ring and font all come from the variables above.

Icons

Laurel's icon set is Phosphor. Set "iconLibrary": "phosphor" in components.json so shadcn add writes @phosphor-icons/react imports. The components on this site were added that way; see Iconography.

Optional: the namespaced registry

The site serves the theme as a shadcn registry. Register it in components.json:

components.json
{
  "registries": {
    "@ralekocode": "https://<site-host>/r/{name}.json"
  }
}
npx shadcn@latest add @ralekocode/laurel        # theme variables, no npm package needed
npx shadcn@latest add @ralekocode/laurel-font   # Fira Sans via @fontsource

This inlines the same variables into your CSS instead of importing them from the package. Use one path or the other, not both.

Updates

  • Look changes (colours, radius, fonts): bump @ralekocode/design-system. Components pick the change up through the variables; nothing to re-add.
  • Component changes (shadcn's own markup or behaviour): npx shadcn@latest add button --overwrite. Component files are yours; overwrite only if you have not customised them.
  • Registry install: re-run npx shadcn@latest add @ralekocode/laurel --overwrite.

Dark mode

Laurel ships a real dark theme. It is class-based like shadcn's: put class="dark" on <html> and every variable flips. theme.css also registers the dark: variant. Use next-themes (attribute="class", defaultTheme="system", enableSystem) in Next.js, or a tiny no-flash inline script elsewhere; both are in Dark mode. Prefer semantic utilities over dark: utilities.

Theme variables

The theme sets the standard shadcn variables and nothing else. Each has a light and a dark value in theme.css.

VariableRole
--background, --foregroundPage ground and body text
--card, --popover (+ -foreground)Raised surfaces; lighter than the ground in dark
--primary (+ -foreground)The accent: primary buttons, links, marks
--secondary, --muted, --accent (+ -foreground, and -hover on the first two)Fills, quiet text, hover and selected states
--primary-hover, --destructive-hoverExplicit hover fills (not opacity), a step darker in light / lighter in dark
--success, --warning, --info, --destructive (+ -foreground, -subtle, -border)Status colours — each on its own hue, distinct from the brand accent
--borderDividers: a faint hairline
--input, --input-backgroundForm-control boundary (a stronger step than --border, for WCAG 1.4.11) and fill
--ringFocus ring (the accent)
--chart-1…5A five-step run of the primary hue
--sidebar-*Sidebar equivalents
--radiusBase radius, 0.25rem; Mira derives rounded-sm…4xl from it
--font-sans, --font-headingFira Sans

Instructions for coding agents

Paste this into your AGENTS.md / CLAUDE.md:

## UI
- Build UI with shadcn/ui components (`npx shadcn@latest add <name>`); do not hand-roll buttons, inputs, dialogs, etc.
- The Laurel theme (`@ralekocode/design-system`) is applied through the standard shadcn CSS variables. Style only with Tailwind semantic utilities (`bg-primary`, `text-muted-foreground`, `border-border`, `rounded-md`).
- Never hard-code hex colors, px sizes, or font names. Never use pure black or white.
- Themes are class-based (`.dark` on `<html>`); use semantic utilities so light and dark both work, and add `dark:` variants only for genuinely mode-specific cases. Icons: Phosphor.
- Primary is a line or mark, never a flood. Headings stay weight 500.
- Do not edit files under `components/ui`; re-run `npx shadcn@latest add <name> --overwrite`.

On this page