The tokens
Colours
Five, each a 6-digit hex value like#6d28d9:
Only
#rrggbb is accepted: no rgb(), no hsl(), no three-digit shorthand, no eight-digit alpha, no colour names, no var(...). A colour picker that emits anything else gets a validation error naming the field. Values are normalized to lowercase before they are stored, so what ends up in the page is wondeya’s re-serialization of what matched, never the exact string that arrived.
Typefaces
Two picks, one for headings and one for body, from a curated set that wondeya self-hosts:
You choose a key; the server owns the family name, the fallback stack and the file. Fonts are served from wondeya rather than imported from a third-party font host, because a remote font import blocks the first render and adds a dependency to your visitors’ page that nobody chose.
Radius
One pick from a closed scale:
The scale is a set of keys rather than a number, because a number would be a CSS length: a string written by the client and interpolated into a stylesheet.
The defaults
A site that has never saved its theme uses the wondeya defaults:One theme per site
The theme belongs to a site’s (project’s) brand: every page of the site wears it, and there is no per-page override. What is in force resolves in two steps: the site’s saved tokens, else the wondeya defaults. Clearing the customization (tokens: null through the API) returns the site to the wondeya defaults; it does not save a copy of anything. That is what makes a later rebrand safe: there is no frozen snapshot that quietly stops following you.
Editing is a partial patch
You send only what changed (colors.primary on its own is normal and correct), and it is merged onto the theme in force and then validated as a whole.
Merging never repairs. A key wondeya does not recognise is a rejection with a field-level error, never a silently ignored field, at any depth of the object. A theme that “almost” validated is a theme somebody is probing.
What reaches the page
The server produces a map of custom properties from the parsed tokens, and injects it into the page’shead before the body renders, so a visitor never sees a flash of the default palette:
No key and no value in that map comes from the request. Colours are hex values wondeya re-serialized; fonts and radii are looked up in a table wondeya owns. That is what makes it safe to interpolate them into a style block on a page your visitors load.