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
| Theme | Description |
|---|---|
| Default | Clean black and white with subtle contrasts |
| Zinc | Neutral zinc grays, professional feel |
| Slate | Cool blue-gray tones, modern and calm |
| Midnight | Deep navy, dark-first design |
Pro Themes
| Theme | Description |
|---|---|
| Ocean | Deep teal and cyan, fresh and energetic |
| Aurora | Purple-to-green gradient, creative and bold |
| Ember | Warm amber and orange, cozy and confident |
| Forest | Earthy greens, natural and grounded |
Bundle Themes
| Theme | Description |
|---|---|
| Candy | Bubbly pinks and purples, playful and fun |
| Brutal | Neo-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:
| Token | Usage |
|---|---|
--background | Page background |
--foreground | Primary text color |
--card | Card/panel backgrounds |
--card-foreground | Text on cards |
--primary | Primary action color (buttons, links) |
--primary-foreground | Text on primary color |
--secondary | Secondary elements |
--muted | Muted backgrounds (hover states, badges) |
--muted-foreground | De-emphasized text |
--accent | Accent highlights |
--destructive | Error/danger actions |
--border | Borders and dividers |
--input | Form input backgrounds |
--ring | Focus ring color |
--radius | Border 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
- •API Routes — All available API endpoints
- •CLI Reference — Apply themes and more