Skip to content

Build a theme

A theme restyles every widget through the design tokens of umbra.css. It is data only, so it’s a single file:

themes/ember/
theme.json required
preview.png optional
{
"$schema": "https://raw.githubusercontent.com/AmineChr54/umbra/main/schemas/theme.schema.json",
"id": "ember",
"name": "Ember",
"description": "Warm orange accent on deep brown-black surfaces.",
"author": "your-github-name",
"version": "1.0.0",
"tokens": {
"--accent": "#ff8a3d",
"--accent-soft": "rgba(255, 138, 61, 0.15)",
"--radius-m": "8px"
}
}
  • id equals the folder name: 2 to 40 lowercase letters, digits and dashes. default is taken. Bump version on every change.
  • tokens may only use the names in the token reference. Anything else (CSS, url(), scripts, other tokens, subfolders) fails validation.
  • Leave out what you don’t change. Left-out tokens keep the default “Umbra Black” look.
  • Keep --bg at the default #000 unless the theme is about the background, and keep text readable: check the contrast of --text and --text-2 on your surfaces.
Terminal window
umbractl install-theme ember # install a catalog theme
umbractl themes # installed and community themes
umbractl theme ember # switch live (every widget and Settings)
umbractl capture settings:themes themes.png

To test a local file, copy the folder to %APPDATA%\Umbra\themes\<id>\ and run umbractl themes, then umbractl theme <id>. Then check a few widgets with umbractl capture <widget> shot.png.

  1. Run node scripts/catalog.mjs: it validates your theme and regenerates themes/index.json. Never edit the index by hand.
  2. Open a pull request with your themes/<id>/ folder and the regenerated index.
  3. CI runs node scripts/catalog.mjs --check and fails if the index is out of date.

The host turns the active theme into one :root { ... } rule, and shared/umbra.js applies it after umbra.css, so widgets need no code to support themes. A widget with "themeable": false is left alone. The user’s own appearance settings (accent, corner radius, font, light text, reduced transparency) are applied on top of the theme. See Appearance and themes and the theme.json schema.

Catalog tokens are re-validated before Settings draws them, so a theme can never smuggle in anything but colors and radii.