YYayaw
Docs

Design Tokens

Runtime semantic token overrides for non-dashboard pages.

Overview

Yayaw supports runtime design token overrides without rebuilding the app.

Scope for this feature:

  • targets pages outside /dashboard/* and /auth/*
  • supports global overrides and organization-scoped overrides for public organization hosts
  • supports an optional immutable per-page layer for one global public page
  • supports semantic colors (including chart colors), public layout tokens (page-section-padding-y, page-section-margin-y, radius, spacing, tracking-normal), typography tokens (font-sans, font-serif, font-mono), and shadow tokens (shadow-*)

CMS Role

Design tokens are the public presentation layer for CMS-rendered pages and previews. They let operators adjust semantic color, radius, spacing, typography, tracking, and shadow values without editing page documents, section definitions, or component source.

Use tokens for theme-level visual decisions. Use page documents and sections for content structure, and keep dashboard/auth styling on their dedicated app-shell scope.

Data Model

The payload is versioned and stored as semantic token maps:

interface DesignTokensV1 {
  version: 1;
  light: Partial<Record<DesignToken, string>>;
  dark: Partial<Record<DesignToken, string>>;
}

Storage:

  • global scope: system_settings using key design-tokens.non-dashboard.v1
  • organization scope: organization_settings.designTokens
  • global page scope: ui_page_revisions.definition.data.root.props.designTokens

Runtime Resolution

Resolution pipeline:

  1. load the global token payload
  2. load the active organization token payload when the request resolves to an organization public host or organization-scoped preview
  3. merge organization values over global values for each light/dark token
  4. when a global page revision declares a page layer, apply its semantic color and approved sans/serif overrides inside that page only
  5. generate scoped CSS variables:
    • .scope-nondashboard:not(.dark) { ... }
    • .scope-nondashboard.dark { ... }

The scope class is applied only on pages outside dashboard/auth routes. Verified custom public hosts apply the owning organization's effective token payload after the global baseline, so one organization can theme its public pages without changing the canonical Yayaw site or another organization's host.

The page layer uses a revision-derived scope class and the same wrapper for published pages and immutable draft previews. Its selectors also cover body-level portals while that page is mounted. A page with no layer receives no extra class or style element and inherits the effective global theme unchanged. The first release intentionally limits contextual page layers to global_public; organization pages continue to use their organization token layer so draft and custom-domain rendering share one inherited baseline. The dashboard Puck authoring canvas preserves this field but does not inject the page layer in version 1. The immutable preview is the visual authority for this layer and must be used for design evidence and publication review.

The public page renderer applies page-section-padding-y and page-section-margin-y to reusable sections and generated body sections. Header and footer chrome stay outside that rhythm frame. The page editor uses the same frame, so changing either token updates authoring previews and public output without adding spacing nodes or route-specific styles to page documents. The repository baseline for page-section-padding-y is 1.5rem; operators can override it globally or for an organization public host.

Dashboard routes intentionally keep their app-shell styling independent from public-site token overrides. If a future dashboard theming feature is needed, add a separate scope and storage key instead of reusing design-tokens.non-dashboard.v1.

Token Families

Token families include:

  • semantic colors such as background, foreground, primary, secondary, accent, muted, destructive, border, input, ring, card, popover, and chart colors
  • public layout tokens such as page section padding, page section margin, radius, and spacing
  • typography tokens such as sans, serif, and mono font stacks
  • tracking tokens such as tracking-normal
  • shadow tokens such as shadow-sm, shadow-md, and related depth values

Only declared Yayaw tokens are accepted. Unknown CSS variables from imported themes are ignored.

Revision-owned page layers are narrower than theme-level payloads. They accept semantic color tokens and these loaded font families only:

  • system, Geist, or Alegreya Sans for font-sans
  • system, Georgia, or Alegreya for font-serif

font-mono, custom stacks, remote font URLs, layout tokens, and shadow tokens are not accepted in a page layer. Alegreya and Alegreya Sans are registered as root CSS variables through next/font; they do not affect another page unless that page explicitly selects the corresponding semantic font role.

Editing Flow

Admin UI route:

  • /dashboard/content/design-tokens

Behavior:

  • immediate save (no draft/publish split)
  • token fields are initialized from repository baseline values in theme-vars.css
  • color tokens use a picker with HEX input
  • the brush icon on each color input copies the current HEX value with inline success feedback
  • layout tokens use a numeric input with selectable unit
  • typography tokens use a preset select with optional custom font stack input and are shared across light/dark
  • shadow tokens use direct text inputs
  • font tokens currently store CSS font-family stacks (for example Inter, sans-serif); font file upload and font catalog selection are not part of this UI yet
  • dark values can be left unset to inherit light first, then baseline dark (or baseline light when no dark baseline exists)
  • color values are canonicalized and stored in OKLCH format
  • import by URL is available directly in the editor (current provider support: TweakCN URLs like https://tweakcn.com/editor/theme?theme=neo-brutalism)
  • import by shadcn CLI command is available directly in the editor (for example bunx --bun shadcn@latest add @ss-themes/ghibli-studio or pnpm dlx shadcn@latest add https://shadcnthemer.com/r/themes/<id>.json; package-manager agnostic)
  • import by pasted CSS is available directly in the editor (:root { ... } and optional .dark { ... })
  • theme import uses a single "Import Theme" dropdown that opens a method-specific modal (URL, command, or CSS) with contextual guidance
  • importing fills the current scope editor state; you still explicitly save to publish

Contextual MCP page plans can set page.designTokens to a non-empty version-1 payload for a global page. Create plans omit or use null to inherit. Rework plans omit the field to preserve the target revision's layer, use null to clear it explicitly, or provide a payload to replace it. This operation does not mutate the global or organization token records. Publication accepts a revision-owned layer only when strict contextual persistence issued its design proof and visual review approved that exact runtime; low-level page writes cannot publish an unreviewed page theme.

Theme Import Parsing

The parser is provider-based and currently includes one implementation:

  • tweakcn: accepts editor/theme URLs, resolves the slug, then fetches https://tweakcn.com/r/themes/{slug}.json
    • if the registry JSON endpoint fails for a valid theme page URL (for example https://tweakcn.com/themes/{id}), Yayaw falls back to parsing the server-rendered theme payload from the theme page
  • shadcn-registry: accepts a shadcn CLI add command (or direct @scope/item reference), resolves the registry alias, then fetches the registry JSON item endpoint
  • css: parses pasted CSS with :root and optional .dark variable blocks

Normalization rules:

  • only known Yayaw tokens are imported
  • color tokens are converted to canonical OKLCH
  • text/layout/typography/shadow tokens are validated with the same token value constraints as manual editing
  • unsupported or invalid token values are ignored

Runtime Consumers

Effective tokens are consumed by:

  • public generated pages
  • docs/public layout wrappers outside dashboard/auth
  • component catalog previews when validating token-aware recipes
  • generated section runtime previews

The component catalog applies effective runtime tokens to preview surfaces so authors can validate imported or local components against the current public theme.

Permissions

Editing requires:

  • global-variables:manage

Organization-scoped token saves also require the caller to operate inside the active organization context that owns the override.

Read access still allows opening the page in read-only mode.

Validation

Useful checks after design token changes:

bun test src/lib/server/services/design-tokens/design-tokens.test.ts
bun run check
bunx tsc --noEmit