fayzfayz sdk
PTEN

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 derived accent and (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.

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:

BrandBase hue (HSL)Becomes primary/ringDerived accent (hue −50°)Personality · when to use
blue221 83% 53%institutional blue171 → green-cyanTrust, corporate. B2B SaaS, fintech, legal.
violet262 83% 58%premium violet212 → blueNeutral-premium, creative, tech. The scaffold default.
green142 71% 45%vivid green92 → limeCare and growth. Health, finance, sustainability.
orange25 95% 53%warm orange335 → pinkAppetite and energy. Food, hospitality, retail.
red0 84% 60%strong red310 → magentaUrgency and passion. Sports, delivery, promotions (careful: it lives next to destructive).
pink330 81% 60%vibrant pink280 → violetLifestyle and expression. Beauty, fashion, young D2C.
teal172 66% 50%aqua green122 → greenCalm 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

KeyValueWhat changes at once
brandone of the 7 namesprimary, ring, accent (hue −50°) and, if you opt in, the colored sidebar — all from the same root.
radiusnoneSquare corners — a technical, dense read (tables, back office).
smSubtle rounding — sober, corporate.
mdThe balanced middle ground — the safe pick.
lgGenerous corners — friendly, tactile to the touch.
fullPills and circles — playful, consumer.
modesystemRespects the user's OS — the sensible default.
darkAlways dark — night apps, backstage, a floor plan at night.
lightAlways 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 tokenWhere it comes from
primarythe brand, with a white primaryForeground for contrast over the fill.
ring (focus)the same brand — the ring inherits the identity.
accentthe 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, typographyfrom 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 (nonesubtlemediumbold), 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 →