Zvessa docs

Styles

How everything looks is data: a style. Classic and Futuristic are built in and written the same way anyone's own style is, so they are the worked examples (convex/lib/styles.ts). Every setting, its options and ranges: docs/STYLES.md. This page is how to use them.

The three places a look lives #

"look":   { "style": "paper", "scheme": "system", "changes": { "colors": { "accent": "#15803d" } } },
"styles": [{ "id": "paper", "name": "Paper", "extends": "classic",
             "type": { "body": "serif" }, "shape": { "radius": 20 } }],
"pages":  [{ "id": "party", "title": "Party", "blocks": [], "look": { "backdrop": { "kind": "dots" } } }]
  1. look.style: which style the space uses (classic, futuristic or an id from styles).
  2. look.changes: small tweaks on top, without making a style ("make the accent green").
  3. page.look: one page looks different (a party page with dots).

The ground behind everything is the style's backdrop: plain, grid, dots or gradient, with size and moving beams. The lit scene adds lines (1 to 4 colours the grid sweeps through), glow (0 to 3 drifting lights), floor (a lit floor of lines moving toward you) and streaks (0 to 3 light streaks). It's drawn by src/components/Scene.tsx from convex/lib/scene.ts, and the moving parts follow the Performance rules.

Later, a person's own look on their device sits on top of all of these.

Layers #

Lowest first, each the same shape, so any layer can change anything: platform default → the style and what it extends → look.changes → page.look → (later) the person's device look. A setting not given falls through to the layer below, so a style lists only what it changes.

Colours #

"schemes": { "dark": { "bg": "#0b1410", "text": "#e8f3ec", "accent": "#34d399" } },
"colors":  { "surface": "mix(bg, text, 6%)", "line": "alpha(text, 12%)", "onAccent": "contrast(accent)" }

Recipes #

AskChange
"Make the accent orange"add /look/changes/colors/accent "#ea580c"
"Rounder corners everywhere"add /look/changes/shape/radius 22
"Dark mode always"replace /look/scheme "dark"
"Buttons outlined, not filled"add /look/changes/parts/button { "treatment": "outline" }
"A calm look with no animation"add /look/changes/motion { "speed": "off", "haptics": "off" }
"Warm paper with a serif font"new style in /styles extending classic, then replace /look/style "paper"

A path's parents must exist: if /look/changes or /look/changes/colors isn't there yet, add it first (add /look/changes { "colors": {} }), or add the whole object in one op.

Rules for anything you build #

Safe by design #

Styles are checked on the server (checkStyles, checkLayer): unknown settings, values out of range and anything that isn't a colour value are refused. A style can't run code, load a URL or fake a screen. A colour that can't resolve falls back to Classic's, so a mistake never breaks a screen.