Theming

indiegoon uses a CSS variable design system with oklch colors. Apply a pre-built theme in seconds or customize your own.

Apply a Theme

goon setup theme

Select from 10 pre-built themes. The CLI injects CSS variables directly into your globals.css.

Available Themes

Free Themes

ThemeDescription
DefaultClean black and white with subtle contrasts
ZincNeutral zinc grays, professional feel
SlateCool blue-gray tones, modern and calm
MidnightDeep navy, dark-first design

Pro Themes

ThemeDescription
OceanDeep teal and cyan, fresh and energetic
AuroraPurple-to-green gradient, creative and bold
EmberWarm amber and orange, cozy and confident
ForestEarthy greens, natural and grounded

Bundle Themes

ThemeDescription
CandyBubbly pinks and purples, playful and fun
BrutalNeo-brutalist high contrast, loud and unapologetic

How It Works

Your globals.css contains theme markers:

/* goon:theme:start */
:root {
  --background: oklch(0.15 0 0);
  --foreground: oklch(0.95 0 0);
  --primary: oklch(0.7 0.15 250);
  /* ... 25+ more tokens */
}

.dark {
  --background: oklch(0.1 0 0);
  /* ... dark mode overrides */
}
/* goon:theme:end */

When you run goon setup theme, the CLI replaces everything between these markers with your chosen theme's tokens.

Design Tokens

Each theme defines these CSS variables:

TokenUsage
--backgroundPage background
--foregroundPrimary text color
--cardCard/panel backgrounds
--card-foregroundText on cards
--primaryPrimary action color (buttons, links)
--primary-foregroundText on primary color
--secondarySecondary elements
--mutedMuted backgrounds (hover states, badges)
--muted-foregroundDe-emphasized text
--accentAccent highlights
--destructiveError/danger actions
--borderBorders and dividers
--inputForm input backgrounds
--ringFocus ring color
--radiusBorder radius scale

Customizing a Theme

Edit the CSS variables directly in globals.css:

/* goon:theme:start */
:root {
  --background: oklch(0.98 0 0);
  --foreground: oklch(0.1 0 0);
  --primary: oklch(0.6 0.2 280);  /* Your brand purple */
  --primary-foreground: oklch(1 0 0);
  --radius: 0.75rem;
  /* ... */
}
/* goon:theme:end */

The /* goon:theme:start */ and /* goon:theme:end */ markers tell the CLI where to inject themes. If you remove them, the CLI won't overwrite your custom theme.

Dark Mode

Dark mode is handled via the .dark class on the <html> element. The pre-built theme toggle component handles this:

import { ThemeToggle } from "@/components/ui/theme-toggle"

// In your header/navbar
<ThemeToggle />

The ThemeScript component (included in the root layout) prevents flash of incorrect theme on page load.

Tailwind Integration

CSS variables are bridged to Tailwind utilities via the @theme inline block:

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  /* ... */
}

Use them in your markup:

<div className="bg-background text-foreground">
  <button className="bg-primary text-primary-foreground">
    Click me
  </button>
</div>

Component Variants

The Button component uses class-variance-authority for variants:

// Available variants
<Button variant="default">Primary action</Button>
<Button variant="outline">Secondary</Button>
<Button variant="ghost">Subtle</Button>
<Button variant="destructive">Danger</Button>
<Button variant="link">Text link</Button>

// Sizes
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon">🎯</Button>

Next Steps