add-theme-property

Checklist for adding or changing a field on ThemeConfig (a new design token, per-mode setting, or export option) end to end — schema, defaults, store + history, CSS apply, export, editor UI, AI, and t

SKILL.md

GitHub

Add a theme property: $ARGUMENTS

ThemeConfig is persisted in users' cookies, stored in saved presets, exported as JSON, generated by AI, and synced into the preview iframe. A change must work for all of them, including old data that lacks the new field.

Work through every step. Say explicitly when a step doesn't apply.

  1. Shared constants: if the property has a fixed value set (palettes, shades, fonts, ranges), add it to shared/constants/theme.ts so app, server, and AI prompt share it.
  2. Types + schema (app/types/theme.ts): add the field to ThemeConfig. In rawThemeSchema, make it .optional() and fill it in ThemeConfigSchema.transform() (usually mirroring the light-mode value for dark* fields). Existing cookies and presets must still parse.
  3. Defaults (app/utils/defaults.ts): add the value to DEFAULT_THEME (and to the light/dark override defaults if it's a token override).
  4. Presets (app/utils/presets.ts): built-in presets are full configs, so either add the field to each preset or rely on the schema transform, and make sure loadPreset still validates.
  5. Store (app/stores/theme.ts): add a setXForMode(mode, value) setter that mutates config.value then calls _pushHistory(). Continuous inputs (sliders, drags) also get a visual setter without history, committed once at the end. Add it to the returned API.
  6. Apply (app/composables/useThemeApply.ts → app/utils/cssGenerator.ts): semantic palette names go to appConfig.ui.colors; everything else is a CSS variable in :root / .dark. Output must still pass isCleanCSS; sanitize free-form values with sanitizeCSSValue.
  7. Export (app/composables/useThemeExport.ts, generateExportCSS): include the property in the CSS and app-config output where relevant (JSON export is automatic).
  8. Editor UI (app/components/editor/): a leaf control taking modelValue and emitting updates, wired in EditorPanel via useThemeModeAccessors so it edits the current color mode.
  9. AI: if the model should choose it, extend aiThemeSchema in server/api/ai/generate.post.ts, buildThemeConfig in server/utils/aiResponseBuilder.ts, and describe it in server/utils/aiSystemPrompt.ts (value lists come from shared constants).
  10. Docs: update app/data/help.md and any learn article describing the editor's controls.
  11. Tests:
    • tests/unit/types/theme.test.ts: the schema accepts old configs without the field and fills the default.
    • tests/unit/stores/theme.test.ts: the setter updates the right mode, pushes history, and undo/redo work.
    • tests/unit/utils/cssGenerator.test.ts / useThemeExport.test.ts: the variable/export output.
  12. Verify: /dev-workflow full, then check the preview updates live and survives a reload (/run-app).