03 · Theme and brand
A theme isn't a color — it's a system of chained decisions. In Fayz you declare three decisions in app.manifest.json and the shell's theme engine derives the entire palette from them. The shell stays the same; only the look changes, and it changes coherently.
Step 1 · Think in systems
Before editing, pick three things — each one cascades through dozens of tokens:
- Brand color → becomes
primary, the focus ring, a derivedaccentand (optionally) the colored sidebar. - Corner personality (the radius) → sets buttons, cards, inputs and modals all at once.
- Mode strategy → light, dark, or follow the operating system.
Three decisions, not thirty colors. That's the whole point of a Design System.
Step 2 · Apply it in the manifest
Freshly created, the app ships with "theme": { "brand": "violet" }. The block accepts three keys:
{
"theme": {
"brand": "teal",
"radius": "lg",
"mode": "system"
}
}
Looks like very little — and that's on purpose. Each key is the root of a chain. Here's what it unfolds into.
Gallery of the 7 brands
Choosing brand means choosing a whole family. The engine takes the brand's hue, applies it to primary/ring and rotates the hue −50° to generate a harmonic accent automatically. The table below shows, per brand, the base hue, the derived accent and where each one shines:
| Brand | Base hue (HSL) | Becomes primary/ring | Derived accent (hue −50°) | Personality · when to use |
|---|---|---|---|---|
blue | 221 83% 53% | institutional blue | 171 → green-cyan | Trust, corporate. B2B SaaS, fintech, legal. |
violet | 262 83% 58% | premium violet | 212 → blue | Neutral-premium, creative, tech. The scaffold default. |
green | 142 71% 45% | vivid green | 92 → lime | Care and growth. Health, finance, sustainability. |
orange | 25 95% 53% | warm orange | 335 → pink | Appetite and energy. Food, hospitality, retail. |
red | 0 84% 60% | strong red | 310 → magenta | Urgency and passion. Sports, delivery, promotions (careful: it lives next to destructive). |
pink | 330 81% 60% | vibrant pink | 280 → violet | Lifestyle and expression. Beauty, fashion, young D2C. |
teal | 172 66% 50% | aqua green | 122 → green | Calm and clarity. Clinics, wellness, productivity apps. |
The HSL values above are representative — they're there so you can reason about each family and the accent that comes out of it. The platform runtime applies the calibrated variant of each name. The derivation rule (hue −50°, same saturation and lightness) is the same; what changes is the exact starting point.
What each key cascades into
| Key | Value | What changes at once |
|---|---|---|
brand | one of the 7 names | primary, ring, accent (hue −50°) and, if you opt in, the colored sidebar — all from the same root. |
radius | none | Square corners — a technical, dense read (tables, back office). |
sm | Subtle rounding — sober, corporate. | |
md | The balanced middle ground — the safe pick. | |
lg | Generous corners — friendly, tactile to the touch. | |
full | Pills and circles — playful, consumer. | |
mode | system | Respects the user's OS — the sensible default. |
dark | Always dark — night apps, backstage, a floor plan at night. | |
light | Always light — daytime operation, reception, front desk. |
Notice that radius doesn't change "the button": it changes buttons, cards, inputs and modals together, in the same proportion. That's what keeps the app coherent when you change one end of it.
3 ready-made recipes
Copy, paste into app.manifest.json and adjust the name. Each is a tested combination of brand + radius + mode for a type of business:
Clinic / health
{
"theme": { "brand": "green", "radius": "md", "mode": "light" }
}
Green communicates care and trust; md balances formal and approachable; light suits a reception desk and daytime service.
Food / evening orders
{
"theme": { "brand": "orange", "radius": "lg", "mode": "dark" }
}
Orange is appetite and hospitality; lg makes the targets tactile for quick taps; dark rests the eyes on the floor at night.
Sober B2B SaaS
{
"theme": { "brand": "blue", "radius": "sm", "mode": "system" }
}
Institutional blue reads as safe; sm keeps the professional density; system respects the operator's OS throughout the day.
The name at the top of the manifest is the display name — change it along with the color so the rebrand is complete:
{
"name": "My Clinic",
"theme": { "brand": "green", "radius": "md", "mode": "light" }
}
Step 3 · Validate
Edit the block, save, and run doctor:
npx @fayz-ai/cli doctor
⚠ plugins referenced by manifest are resolved by the platform bundle, not public npm packages: dashboard 0 error(s), 1 warning(s)
✓ You should see: 0 error(s) from doctor. The warning about plugins resolved by the platform bundle is expected in mock mode — it isn't an error. Doctor confirms the manifest is well-formed and sound before the platform consumes it.
Under the hood
Those three keys are the condensed expression of a larger system. Starting from your brand color, the theme engine (createTheme / applyTheme, in @fayz-ai/saas) derives the chain — verified in the code:
| Derived token | Where it comes from |
|---|---|
primary | the brand, with a white primaryForeground for contrast over the fill. |
ring (focus) | the same brand — the ring inherits the identity. |
accent | the brand hue rotated −50° (same saturation and lightness), a second harmonic tone. |
| sidebar (optional) | the rail background takes the brand, white text, border at −12% lightness, active item at −15%, secondary icons at hue 35% 82%. |
| neutrals, surfaces, semantics, radius, shadows, typography | from a curated base preset (the classic admin), into which your brand slots. |
applyTheme then writes every value as a CSS variable on the document (--primary, --ring, --accent, --sidebar, --button-radius, --font-family, --shadow-sm/md/lg). Your brand is one input into an already consistent token system.
The derivation happens in the Fayz platform runtime, which consumes the theme block to paint the whole shell. In the local scaffold preview — today an anchor screen — the palette isn't applied yet. That's why this step is validated with doctor (valid config), while the full visual result shows up in the platform runtime.
Want the whole chain — the eight token families, the contrast reasoning and the flow of designing the system before configuring it? It's in the Design System and theming chapter.
See also: the full token reference — a quick lookup of the families and the CSS variables the engine writes.
Beyond the 3 keys Experimental
The manifest exposes three decisions today, but the engine underneath is far richer. Already sitting behind the platform runtime: free-form HSL color (not just the 7 names), 11 font families (from inter and geist to outfit and manrope), shadow levels (none → subtle → medium → bold), the sidebar in brand or neutral mode, and entire base presets. Exposing those families in the manifest — without bloating it — is the next step for the theme contract; the direction is evolutionary, not finished.
Workflow tip: design the system as an artifact first. A design session with AI produces a tokens.css with the complete families (brand, tints, typography, elevation); the manifest's theme block becomes the condensed expression of that artifact, and you promote tokens into the Customization seams as you grow. The manifest declares the theme — it isn't where you discover it.
← Previous: 02 · Explore the anatomy · Next: 04 · Add a plugin →