Tailwind v4 CSS variables and your theme preset
VeloCMS themes are built entirely on CSS custom properties injected via Tailwind v4's @theme engine. Understanding how presets map to CSS variables lets you extend themes precisely without fighting the system.
Every VeloCMS theme preset is a JSON file that defines semantic design tokens — colors, typography scales, border radii, spacing — as CSS custom properties. Tailwind v4's @theme engine reads these properties and generates utility classes automatically. When you switch themes, only the custom property values change; the Tailwind classes in your HTML stay the same. This is how the same blog template renders beautifully in all five presets.
How the preset JSON maps to CSS variables
A theme preset JSON object like { colors: { primary: 'oklch(0.55 0.22 250)' } } compiles to --color-primary: oklch(0.55 0.22 250) in the :root block. Tailwind v4's @theme engine then makes bg-primary, text-primary, border-primary, and ring-primary available as utility classes — all reading from the same CSS variable. Change the variable, every utility that references it updates automatically.
/* Generated from the theme preset JSON */
@theme inline {
--color-background: oklch(0.98 0 0);
--color-foreground: oklch(0.12 0 0);
--color-primary: oklch(0.55 0.22 250);
--color-muted: oklch(0.96 0.01 240);
--color-muted-foreground: oklch(0.45 0.02 240);
--font-sans: 'Inter', sans-serif;
--radius: 0.75rem;
}Extending the preset without modifying the source file
If you want to override a single token — say, change --radius from 0.75rem to 0.25rem for a sharper design — add a CSS override in Admin Themes Advanced CSS. The override goes in a :root block and takes precedence because it's injected after the preset in the stylesheet cascade. This is the right pattern for small tweaks. For a full custom palette, create a new theme preset JSON instead.
Semantic tokens vs. raw Tailwind classes
VeloCMS's templates always use semantic token classes — bg-background, text-foreground, bg-primary — rather than raw color classes like bg-indigo-600 or text-zinc-900. This is intentional: raw classes are hardcoded to a specific shade and don't respond to theme switching. If a template uses bg-indigo-600, switching from the Indigo preset to the Terminal preset doesn't change that element — it stays indigo. Semantic tokens switch automatically because they read from CSS variables.