| name | visage-theme |
| description | Knowledge for designing and applying Visage theme tokens and JUCE LookAndFeel colors. Use when the user asks about colors, theming, palettes, styling, branding, dark mode, light mode, ARGB hex format, color schemes, or the theme-designer tool. Covers the JSON theme schema, C++ codegen, Palette API, OverrideId scoping, and the design workflow. |
| version | 1.0.0 |
Visage Theme System
Theme Designer Workflow
- Open
Tools/theme-designer.html in a browser (works via file://, no server needed)
- Edit colors visually or describe what you want to Claude
- Claude updates the
<script id="theme-data"> JSON block in the HTML
- Refresh browser to see changes instantly
- When happy, export C++:
python3 scripts/generate_theme.py Tools/themes/my-theme.json --mode both --output Source/Theme
- Include
Source/Theme.h and call initThemePalette(palette) at plugin startup
JSON Theme Schema
The theme JSON has these sections:
colors — Standard Visage widget tokens (Button, Toggle, TextEditor, PopupMenu, ScrollBar)
values — Visage value tokens (rounding, margins, sizes) as floats with min/max hints
custom — Project-specific tokens (knobs, meters, waveform, panels, cards, accents, etc.)
juce — JUCE LookAndFeel ColourId mappings keyed as "ClassName::colourIdName"
meta — Theme name, version, base (for inheritance)
overrides — Per-OverrideId Visage color overrides (advanced)
Color format: "value": "#RRGGBB" (web-standard hex) + "alpha": 0.0-1.0 (separate float).
The codegen converts to Visage 0xAARRGGBB format automatically.
ARGB Color Format
Visage uses 0xAARRGGBB — alpha in the most-significant byte. This differs from CSS rgba.
0xFFFF0000
0x800000FF
0x00000000
Conversion: alpha_byte = round(alpha_0_to_1 * 255), shifted left 24 bits.
C++ Codegen
python3 scripts/generate_theme.py theme.json --output Source/Theme.h
python3 scripts/generate_theme.py theme.json --mode juce --output Source/ThemeLookAndFeel.h
python3 scripts/generate_theme.py theme.json --mode both --output Source/Theme
python3 scripts/generate_theme.py theme.json --validate-only
Palette API
visage::Palette palette;
palette.initWithDefaults();
palette.setColor(theme::KnobArc, visage::Color(0xFF00FFD4));
palette.setValue(theme::TextEditorRounding, 6.0f);
rootFrame->setPalette(&palette);
OverrideId Scoping
For per-component theme regions (e.g., a dark header in a light app):
VISAGE_THEME_PALETTE_OVERRIDE(HeaderRegion);
palette.setColor(HeaderRegion, theme::PanelBackground, visage::Color(0xFF1A1A2E));
headerFrame->setPaletteOverride(HeaderRegion, true);
JUCE LookAndFeel Integration
The codegen produces a LookAndFeel_V4 subclass with all ColourIds set:
#include "ThemeLookAndFeel.h"
static DefaultDarkLookAndFeel themeLAF;
setLookAndFeel(&themeLAF);
Common Mistakes
- Using CSS
#RRGGBBAA order — Visage is 0xAARRGGBB (alpha FIRST)
- Forgetting
palette.initWithDefaults() before applying custom colors
- Not calling
setPalette() after modifying the palette
- Editing the generated C++ header directly — always regenerate from JSON
Reference Files
| File | Purpose |
|---|
Tools/theme-designer.html | Visual preview + editing tool |
Tools/themes/default.json | Default theme with all tokens |
scripts/generate_theme.py | JSON to C++ codegen |
See references/token-catalog.md for all known Visage tokens with defaults.