All books

Themes

~3 min read · updated 2026-08-23 · markdown

FaustWave ships four theme modes: Dark, Light, Cyberpunk, Auto. Switch via Settings → Appearance, via the Command Palette (Theme: Dark / Theme: Light / Theme: Cyberpunk / Theme: System), or via the theme.set MCP action.

The four modes

ModeWhen to pick it
DarkDefault. High contrast, reduced eye strain in low light.
LightBright environments, daylight, screens you share.
CyberpunkNeon-on-near-black, LED-panel aesthetic. For vibe.
AutoFollows your OS appearance setting. Switches at sunset if your OS is configured to.

The chosen mode persists per-install (not per-project) — it's a user preference, not a project asset.

How the theme system works

Every theme is a block of CSS custom properties under a single :root[data-theme="..."] selector in packages/ui-kit/src/styles/tokens.css. The setTheme() function sets <html data-theme="...">; the rest of the codebase reads the tokens via var(--token-name).

:root[data-theme="dark"] {
  --bg: #0b0e14;
  --text: #e2e8f0;
  --cyan: #00d4f5;
  /* ... ~80 more tokens */
}
:root[data-theme="light"] { /* ... */ }
:root[data-theme="cyberpunk"] { /* ... */ }

This means the same component code runs in every theme — only the token values differ. Build new components against the token names; they'll automatically theme.

The token taxonomy

Roughly 80 tokens per theme, grouped:

GroupTokens
Backgrounds--bg, --bg-2, --bg-3, --panel, --panel-2, --card, --card-2
Borders--border, --border-2, --border-3, --card-border
Text tiers--text (primary), --text-2 (muted), --text-3 (dimmed), --text-4 (placeholder)
Shadows--shadow-lg, --shadow-md, --shadow-sm
Accent colors8 hues: --cyan, --purple, --pink, --orange, --green, --yellow, --red, --blue
Hover variants--red-hover; the teal's is a role, --action-hover
Accent backgrounds5 alpha tiers × 8 hues: --accent-bg-cyan-subtle, -15, etc.
Accent borders3 alpha tiers × 8 hues: --accent-border-cyan-40, -50, etc.
Glow effectsOne per hue: --glow-cyan, etc.
Wave + node-editor--wave-stroke, --wave-fill, --wave-grid, --node-bg, --node-edge, --node-port
Sequencer track palette--seq-track-1 through --seq-track-6 (per-track colour-coded)
Utility overlays--overlay-dark, --overlay-dark-35, etc.

Cyberpunk-only effects

The Cyberpunk theme adds an overlay layer on top of the regular token block — purely visual atmosphere:

  • LED dot-matrix overlay — a 4 px-tile cyan dot grid via [data-theme="cyberpunk"]::after, mix-blend-mode: screen. Reads as a faint LED panel substrate at typical viewing distance.
  • Magenta-edge vignette — soft radial gradient pulling the eye toward centre.
  • Phosphor text-shadow on the brand title + the Transport Widget's LCD readouts — tight 1 px core + 4–6 px halo, reads as a discrete pixel emitter.

These effects are scoped via [data-theme="cyberpunk"] selectors — Dark and Light don't see them.

Building a fourth theme

To add a custom theme:

  1. Open packages/ui-kit/src/styles/tokens.css.
  2. Add a new block: :root[data-theme="my-theme"] { /* full token set */ }. Copy the Dark or Light block as a starting point + retune hex values.
  3. Add the kind to the setTheme enum in packages/extension-api/src/index.ts.
  4. Add a theme.<my-theme> palette action in packages/extension-core/src/index.ts (icon: pick from lucide).
  5. Add the kind to the persistence allow-list in packages/app/src/lib/persistence.ts (the hydration validator that normalises unknown themes back to dark).
  6. Add a segment button in AppearanceSection.svelte.
  7. Add a Theme-Indicator preview in CommandPalette.svelte.

About 6 small edits — none structural. The theme system was deliberately built to make adding a new theme a half-hour job.

Theme persistence

The chosen theme persists across restarts via app.json. The hydration step also has a validator that normalises any unknown theme back to Dark — leftover from a previous theme experiment + a safety net against corrupted state.

Where to go from here

  • The actual token values per theme live in packages/ui-kit/src/styles/tokens.css — read it to see the exact hex / rgba per token per theme.
  • The Cyberpunk overlay rules live in packages/app/src/styles/global.css under the [data-theme="cyberpunk"]::after selector + the LCD text-shadow rules.
Try it yourself — the IDE runs in your browser. Open the IDE → Get the desktop app

Text licensed under CC BY 4.0 — Mani Weber / FaustWave. For language models: llms.txt · llms-full.txt

AUDIO · 48k · 48.0ms FAUST · 3 KB · 1171 docs CPU · 8.4% BPM · 120.0 UTF-8 BETA· v0.90.0