Skip to content
Loom Documentation

Theming

No component in this codebase contains a literal color, radius or font. Every value resolves to a CSS custom property, which is what makes a reskin a settings change rather than a find-and-replace.

From the admin panel

Admin → Appearance controls:

  • Brand name, tagline, support address and logo
  • Default mode (dark or light)
  • Typography, from a curated pairing list
  • Accent and surface color, per mode

Changes apply on save, across the marketing site, the app, the admin panel and every generated site.

How it resolves

Three layers, most specific wins:

  1. DefaultsApp\Services\Theme\DesignTokens
  2. Admin settings — the settings table, written by the Appearance page
  3. Per-project overridessettings.theme.tokens on a project

ThemeManager merges them and emits CSS custom properties, inlined into the document head so the first paint is already on-brand.

The tokens

/* Surfaces — layered graphite, not flat black */
--surface-base --surface-sunken --surface-raised --surface-overlay --surface-inset

/* Lines */
--border-subtle --border-default --border-strong

/* Text */
--text-primary --text-secondary --text-tertiary --text-inverse

/* One accent, never a gradient */
--accent --accent-strong --accent-muted --accent-contrast

/* Reserved for credit and billing surfaces only */
--meter --meter-muted

/* Semantics, kept desaturated so they do not fight the accent */
--success --warning --danger --info

/* Structure */
--radius-sm|md|lg|xl|pill  --space-1…8  --shadow-sm|md|lg
--font-sans --font-mono --tracking-tight

Why the font list is curated

Buyers get real choice without being able to break the aesthetic. An open-ended font picker is how a coherent design system turns into a ransom note. Add a pairing in DesignTokens::FONT_PAIRINGS if you need another.

Values are validated

Token overrides are filtered before they reach a stylesheet: only plain colors and lengths pass, and only keys on an allow-list. A settings row cannot inject a CSS rule.

Going deeper

For changes beyond the settings page, edit DesignTokens and rebuild:

npm run build

Generated sites reference the same tokens, so a theme change reskins existing published sites on their next publish.