A theme is the second kind of content a package can ship: a validated set of design tokens. Applying one swaps CSS custom properties live across the notch, the panel, and every widget — builtin and modded alike.
"themes": [
{
"id": "nord", "label": "Nord",
"tokens": {
"island": "#0e1116",
"text_primary": "#e6edf3",
"accent": "#88c0d0",
"rim": "rgba(255,255,255,.08)"
}
}
]
The themable set
Colors and shadows only — surfaces, text tiers, accents, rims, shadows. Geometry, radii, spacing, typography, and motion are permanently Perch: a theme can make the island navy, but it cannot make it square.
The token names mirror the product’s design tokens (island, the
text_* tiers, the accents, well, rim/rim-strong, the shadow set).
Any token you omit keeps its Perch value — a two-line theme that only
retints the accents is legitimate.
Rules
- Every value is validated at load (same validator as palettes — parseable, luminance-sane). A broken theme is rejected with its error in Settings and can never take the overlay down.
- Exactly one theme is active. Selection in
Settings → Appearanceis enablement; inactive themes are inert data. Perch black is the permanent fallback. - A theme may remap mods’ palette colors
wholesale — which is why widgets should use
@palettenames and role tokens instead of raw hex for anything identity-colored.
Widgets + themes
If your widget hardcodes #ffffff text on an assumed-black island, a light
theme will hurt it. The rule that keeps you theme-proof: roles for
meaning, palette for identity, hex only for incidentals (a shadow tint, a
one-off translucency). Test with a builtin alt theme active before
publishing.