Styling & Theming
No tailwind.config.*
The template uses Tailwind CSS v4, configured entirely in CSS — there is no
tailwind.config.js/.ts file. Everything starts from app/globals.css:
@import "tailwindcss";
@plugin "@tailwindcss/typography";Design tokens
Brand/semantic colors are defined as CSS custom properties under :root, then re-exposed
to Tailwind’s utility classes via an @theme inline block:
:root {
--background: var(--color-slate-50);
--foreground: oklch(0.1445 0.0148 121.37);
--primary: var(--color-neutral-900);
--primary-foreground: var(--color-white);
--secondary: var(--color-blue-800);
--secondary-foreground: var(--color-blue-50);
--status-success: oklch(0.93 0.07 180.27);
--status-success-foreground: var(--color-teal-600);
/* ...status-info, status-warning, status-destructive follow the same pattern */
--muted: var(--color-gray-200);
--muted-foreground: oklch(0.53 0.03 251.66);
--accent: var(--color-violet-100);
--accent-foreground: var(--color-violet-700);
--border: oklch(0.9097 0 0);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
/* ...and so on for every token above */
}That @theme inline block is what makes bg-primary, text-secondary-foreground,
bg-status-success, etc. available as ordinary Tailwind utility classes.
To reskin the template’s brand colors, edit the :root custom properties — not the
@theme inline block, and not individual component files. Changing --primary and
--secondary propagates everywhere those tokens are used. Prefer extending/reusing these
tokens over introducing raw color values (bg-[#123456]) in components.
There’s a separate @theme block (not inline) for typography:
@theme {
--font-sans: var(--font-instrument-sans), sans-serif;
}--font-instrument-sans is set by next/font/google’s Instrument_Sans loader in
app/layout.tsx — swap the font there if you need a different typeface, then update this
token to match.
cn() — merging conditional classNames
lib/cn.ts wraps clsx + tailwind-merge:
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}This is the standard way to combine static classes with conditional ones anywhere in the
codebase — clsx handles the conditional logic, twMerge resolves conflicting Tailwind
classes (e.g. a later bg-primary correctly overriding an earlier bg-white) so you
don’t get both applied. Use it instead of template-literal string concatenation whenever
a component’s className depends on props or state.
<div className={cn("rounded-full px-4 py-2", isActive && "bg-primary text-primary-foreground")} />Other CSS conventions worth knowing
@layer utilitiesinglobals.cssholds one-off utility classes used by specific components (striped backgrounds, marquee/ping keyframes) — check there before adding a new bespoke utility class of your own.@layer componentsholds small overrides for third-party CSS (Swiper pagination bullets) and a couple of structural fixes (GSAPSplitTextdescender clipping).- Swiper’s CSS is imported directly in
globals.css(swiper/css,swiper/css/pagination,swiper/css/mousewheel) sinceswiperis used for carousels/sliders.