Custom themes
One compatible theme CSS sheet — Studio export, agent-built, or base plus overrides.
A custom brand uses the same contract as a built-in preset: one theme CSS file that keeps the semantic variable names and swaps in your values. You do not need @viraui/foundation — load your sheet, then the fonts named in --font-family-*, then preflight. Keep light and dark in that same file with light-dark() on scheme-sensitive tokens; Light and dark covers the pairing pattern and how data-mode resolves it.
Ask an agent
Paste a prompt when you need a ViraUI-compatible brand sheet wired like any other custom theme — theme → fonts → preflight at the app root. Describe the product look in plain language; the agent should produce a complete theme CSS with light-dark() pairs on scheme-sensitive tokens, not a partial token dump.
Create a ViraUI-compatible custom theme for this project and wire it at the app root. I want: [describe brand — colors, mood, typography, density]. Produce a complete theme CSS file that defines every semantic token the ViraUI theme contract expects, with light-dark() on scheme-sensitive tokens (--global-*, --highlight-*, --base-*, and other values that change with color scheme). Save it in the app (e.g. src/vira-theme.css). Install @fontsource-variable/* for the families named in --font-family-* and import in order: theme CSS → Fontsource wght.css → @viraui/react/preflight.css. Do not install @viraui/foundation unless I asked for a built-in preset. Do not ship a partial override sheet without a full base theme already loaded. Report file paths, packages, and import order.A wired custom sheet looks like this once the agent (or Studio export) has produced it:
import './vira-theme.css';
import '@fontsource-variable/geist/wght.css'; // match families in your theme
import '@viraui/react/preflight.css';:root {
--global-background: light-dark(oklch(98% 0.01 250), oklch(18% 0.02 250));
--global-foreground: light-dark(oklch(22% 0.02 250), oklch(96% 0.01 250));
--global-primary: light-dark(oklch(55% 0.14 250), oklch(72% 0.12 250));
/* space, radius, type scale… can stay unpaired */
}Only after a complete theme is already loaded, you may layer a few semantic overrides:
import '@viraui/foundation/vira.css'; // or your full custom sheet
import './brand-overrides.css'; // only the tokens you change
import '@fontsource-variable/geist/wght.css';
import '@viraui/react/preflight.css';:root {
/* Prefer light-dark() so data-mode flips keep working */
--global-primary: light-dark(oklch(55% 0.14 250), oklch(72% 0.12 250));
--space-medium: 0.875rem;
}Scoped wrappers work the same way when only a subtree should rebrand. Full brand swaps replace the complete theme CSS import — not data-mode.
Load a complete theme
Components expect every semantic token from the theme contract — not a handful of overrides alone. Ship a full theme CSS (Studio export, agent-built sheet, or a built-in preset), or import a base theme first and only then layer partial :root overrides. A partial sheet with no base theme leaves missing variables and broken UI.
App Studio (ViraUI Pro)
Coming later this year
ViraUI Pro sits on top of Core. Join the waitlist on viraui.dev for launch pricing.
Hand-editing a full theme means forking a large CSS dump, keeping every semantic name stable, balancing light/dark pairs, and checking that components still look right. App Studio in ViraUI Pro is the preferred path for a new brand: tune colors, type, space, and effects on a live ViraUI canvas, share the theme with the team, export CSS that is already compatible, then drop it into the app.
Studio workflow: shape the brand on the canvas → export theme.css (ZIP or paste) into the app (e.g. src/vira-theme.css) → install @fontsource-variable/* for the families in --font-family-* and strip temporary Studio CDN @font-face blocks once npm fonts are wired → import theme → fonts → preflight. Do not also install @viraui/foundation.
For a new brand, prefer Studio. Reach for an agent-built sheet or a tiny :root override only when Studio is not an option.
Last updated on