Theming
Dark mode, CSS variables, and styling with Tailwind CSS v4.
Overview
ZeroStarter uses Tailwind CSS v4 with CSS custom properties for theming, next-themes for dark/light mode switching, and the Fumadocs UI theme for documentation pages.
Dark Mode
Dark mode is handled by next-themes with system preference detection:
// web/next/src/app/providers.tsx
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
{children}
</ThemeProvider>The theme toggle component at web/next/src/components/mode-toggle.tsx cycles through: system → light → dark → system.
CSS Variables
Theme colors are defined in web/next/src/app/globals.css using OKLch color space:
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--border: oklch(0.922 0 0);
/* ... */
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
/* ... */
}These variables are consumed by Tailwind utility classes like bg-background, text-foreground, border-border, etc.
Tailwind Configuration
Tailwind v4 is configured via PostCSS in web/next/postcss.config.mjs:
export default { plugins: { "@tailwindcss/postcss": {} } }The global CSS imports Tailwind, animations, and fonts:
@import "tailwindcss";
@import "tw-animate-css";
@import "@fontsource-variable/dm-sans";
@import "@fontsource-variable/jetbrains-mono";Fonts
Two variable fonts are included:
- DM Sans — Primary UI font (body text, headings)
- JetBrains Mono — Monospace font (code blocks)
Component Styling
Components use the shadcn/ui base-nova preset with Base UI primitives. The configuration is in web/next/components.json:
{
"style": "base-nova",
"iconLibrary": "remixicon",
"tailwind": {
"baseColor": "neutral",
"cssVariables": true
}
}Utility Functions
import { cn } from "@/lib/utils"
// Merge Tailwind classes with conflict resolution
<div className={cn("text-sm", isActive && "font-bold")} />Customizing the Theme
- Edit CSS variables in
web/next/src/app/globals.cssfor global color changes - Use Tailwind utility classes that reference the CSS variables
- Update
components.jsonand runbun run shadcn:updateto regenerate components with a different preset