Skip to main content
Sabo uses Tailwind CSS v4 for styling. This guide covers how to customize the core elements of your project’s visual theme: the color palette and typography. All global style variables are defined in src/app/globals.css.

Color Palette

The project uses a CSS variable-based color system, inspired by shadcn/ui. This makes it easy to apply your own brand colors across all components.
Easily Generate a New ThemeInstead of manually editing CSS variables, you can use a visual tool like tweakcn to generate a complete theme for your shadcn/ui components.Simply use the color pickers on the site to create your theme, then copy the generated CSS code and paste it into your src/app/globals.css file, replacing the existing :root and .dark blocks.
1

Understand the Color Variables

Open src/app/globals.css. You’ll find two main color blocks: :root for the light theme and .dark for the dark theme.Key variables to change are:
  • --background: The main page background color.
  • --foreground: The main text color.
  • --primary: The primary color for interactive elements like buttons.
  • --primary-foreground: The text color used on top of primary elements.
  • --secondary: A secondary color for less prominent elements.
  • --accent: A color for highlighted or active elements.
  • --destructive: A color for dangerous actions, like delete buttons.
  • --border: The color for borders and dividers.
src/app/globals.css
:root {
  --background: oklch(1 0 0);       /* White */
  --foreground: oklch(0.145 0 0);  /* Almost Black */
  --primary: oklch(0.205 0 0);     /* Dark Gray */
  --primary-foreground: oklch(0.985 0 0); /* Light Gray */
  /* ... and more */
}

.dark {
  --background: oklch(0.145 0 0);  /* Almost Black */
  --foreground: oklch(0.985 0 0);  /* Light Gray */
  --primary: oklch(0.922 0 0);     /* Light Gray */
  --primary-foreground: oklch(0.205 0 0); /* Dark Gray */
  /* ... and more */
}
The colors are defined using oklch(), a modern CSS color function that allows for intuitive adjustments. You can use online tools like Oklch Color Converter to find the oklch values for your brand’s hex codes.Alternatively, you can use standard hex codes directly. The following examples will use hex codes for simplicity.
2

Change the Primary Color

While the boilerplate uses oklch() for its benefits in theme modification, you can simply use standard hex codes.Let’s say your brand’s primary color is a blue, like #3b82f6. You can update the --primary variable directly with this value. Remember to also choose a readable foreground color (like #ffffff for white).
src/app/globals.css
:root {
  --primary: #3b82f6; /* Your new blue */
  --primary-foreground: #ffffff; /* White text */
  /* ... */
}

/* You might want a different primary color for dark mode */
.dark {
  --primary: #60a5fa; /* A lighter blue for dark backgrounds */
  --primary-foreground: #020817; /* Dark text */
  /* ... */
}
3

See Your Changes Apply Globally

The true power of this system is its global reach. A single change to a color variable in globals.css cascades throughout your entire application, ensuring brand consistency.This works because components are built using Tailwind’s utility classes (like bg-primary), which are linked to your color variables.Let’s look at the <Button> component as a specific example. Inside src/components/ui/button.tsx, you can see its default style is defined using bg-primary:
src/components/ui/button.tsx
const buttonVariants = cva(
  // ...
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        // ... other variants
      },
    },
  }
);
This means when you use the <Button>, it automatically reflects your changes.
Your new brand colors will be reflected not just on buttons, but consistently across many other components like toggles, badges, and input fields.

Typography

Fonts are managed using next/font for optimal performance. The default fonts are Geist Sans and Geist Mono.
1

Find the Font Configuration

Font settings are located in src/app/layout.tsx.
src/app/layout.tsx
import { Geist, Geist_Mono } from "next/font/google";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});
// ...
2

Update the Font

To change the font, simply import a new one from next/font/google and assign it to the --font-geist-sans variable.
src/app/layout.tsx
import { Inter, Geist_Mono } from "next/font/google"; // 1. Change import

// 2. Configure the new font and assign to the same variable
const inter = Inter({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

// 3. Apply the new font's variable to the body className
<body className={`${inter.variable} ${geistMono.variable} antialiased`}>
The system is built on a three-step connection. By reassigning the --font-geist-sans variable, you only change the “source” font, and the rest updates automatically.
  1. Tailwind Class (font-sans): Applied in your .tsx components.
  2. CSS Variable (--font-geist-sans): Acts as a bridge, linked to font-sans in globals.css.
  3. Font File (e.g., Inter): The actual font assigned to the variable in layout.tsx. This is the only part you change.