Adding Themes
Each theme in litmus consists of a theme definition file and one or more provider color files.
1. Create the Theme Definition
Theme definitions live in themes/. Standalone themes go directly in the directory; family members go in a subdirectory:
themes/dracula.toml # standalone
themes/catppuccin/mocha.toml # family member
A theme definition is minimal — just a name, variant, and provider mappings:
name = "Dracula"
variant = "dark"
[providers]
kitty = "Dracula"
wezterm = "Dracula (Gogh)"
- name — human-readable display name
- variant —
"dark"or"light" - providers — maps each supported provider to the theme name in that provider’s theme registry. Not every theme needs to support every provider.
2. Extract Provider Colors
Provider color files are auto-generated — don’t write them by hand. Run:
# Extract colors for all themes from all providers
mise run extract-colors
This reads each provider’s vendored theme data and writes .kitty.toml / .wezterm.toml files with the resolved RGB palette:
themes/catppuccin/mocha.kitty.toml # auto-generated
themes/catppuccin/mocha.wezterm.toml # auto-generated
If your theme’s provider name doesn’t match anything in the vendored data, the extraction will skip it — check that the [providers] mapping matches the provider’s actual theme registry names.
3. Register in themes.rs
Open crates/litmus-web/src/themes.rs and add entries to both arrays.
In DEFINITION_DATA:
#![allow(unused)]
fn main() {
("dracula", include_str!("../../../themes/dracula.toml")),
}
In PROVIDER_COLORS_DATA (one entry per provider color file):
#![allow(unused)]
fn main() {
("dracula", include_str!("../../../themes/dracula.kitty.toml")),
("dracula", include_str!("../../../themes/dracula.wezterm.toml")),
}
The first element is the theme slug (must match the slug used in the definition entry). Keep both arrays sorted alphabetically.
4. Register the Family (if new)
If your theme belongs to a family not yet registered, add the family prefix in crates/litmus-web/src/family.rs:
#![allow(unused)]
fn main() {
static FAMILIES: &[&str] = &[
"Ayu",
"Catppuccin",
// ... add your family name here ...
];
}
Family grouping uses prefix matching — “Catppuccin Mocha” matches the “Catppuccin” prefix.
5. Capture Screenshots
After adding the theme, capture screenshots for it:
mise run capture-kitty # if kitty provider is mapped
mise run capture-wezterm # if wezterm provider is mapped
6. Verify
- Check
.bacon-claude-diagnosticsfor compilation errors - Start the web app with
mise run dev - Confirm the theme appears in the theme list
- Check that all fixtures render on the detail page
- Verify family grouping if applicable