Themes
Magia is fully themeable. It ships 24 built-in themes and supports loading custom themes from a directory on disk. Changes to theme files are picked up automatically without restarting.
Built-in themes
Section titled “Built-in themes”The following themes are bundled with Magia and available in Settings → Appearance:
Magia, Stone Rose, Midnight, Brutalist, Dracula, Solarized, Nord, Monokai, Catppuccin, Gruvbox, Tokyo Night, One Dark, Rose Pine, Ayu, GitHub, Kanagawa, Everforest, Palenight, Vesper, Synthwave, Cyberpunk, Poimandres, Flexoki, Modus Vivendi.
Stone Rose is the default theme. Its values are baked into the CSS file, so selecting it clears any inline overrides rather than re-applying colors.
Dark, light, and system modes
Section titled “Dark, light, and system modes”Every theme defines both a dark and a light color map. The active map is chosen based on your Appearance setting:
- Dark — always use the dark map.
- Light — always use the light map.
- System — follow the OS dark/light preference.
If a theme only defines modes.dark, Magia falls back to the dark map for light mode as well.
Custom themes
Section titled “Custom themes”Place .json theme files in ~/.magia/themes/. Magia loads all .json files from that directory at startup and adds them to the theme picker alongside the built-ins.
The directory is created automatically on first launch.
File format
Section titled “File format”{ "name": "My Theme", "author": "your-name", "version": 1, "modes": { "dark": { "background": "20 14.3% 4.1%", "foreground": "0 0% 95%", "primary": "346.8 77.2% 49.8%", "..." }, "light": { "background": "0 0% 100%", "foreground": "20 14.3% 4.1%", "..." } }, "shape": { "radius": "0.5rem", "shadows": { "shadow-sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)" } }, "fonts": { "ui": "Inter", "mono": "JetBrains Mono" }}The file name (without .json) becomes the theme’s ID. For example, my-theme.json has ID my-theme.
Color values
Section titled “Color values”All color values use the HSL channel format without the hsl() wrapper: "<hue> <saturation>% <lightness>%". This matches the shadcn/ui convention and allows the CSS variable system to apply opacity modifiers.
The full set of color tokens:
| Token | Role |
|---|---|
background / foreground | Main app surface and text |
card / card-foreground | Card surfaces |
popover / popover-foreground | Dropdowns and tooltips |
primary / primary-foreground | Primary action color |
secondary / secondary-foreground | Secondary surfaces |
muted / muted-foreground | Subtle backgrounds and de-emphasized text |
accent / accent-foreground | Hover states and highlights |
destructive / destructive-foreground | Errors and destructive actions |
border | Default border color |
input | Input field border |
ring | Focus ring |
chart-1 through chart-5 | Data visualization colors |
sidebar / sidebar-foreground | Sidebar surface and text |
sidebar-primary / sidebar-primary-foreground | Active sidebar items |
sidebar-accent / sidebar-accent-foreground | Sidebar hover states |
sidebar-border / sidebar-ring | Sidebar borders and focus |
shape.radius sets the CSS --radius variable used for border radii throughout the UI. Use any valid CSS length, for example "0.5rem" or "0px" for a flat look.
shape.shadows is optional. It overrides the four shadow levels shadow-sm, shadow-md, shadow-lg, and shadow-xl.
fonts.ui and fonts.mono override the UI and monospace fonts respectively. Values are CSS font-family strings. Both fields are optional — omitting them leaves the defaults in place (Noto Sans and Noto Sans Mono).
Hot-reload
Section titled “Hot-reload”The Rust backend (ThemeWatcher) watches ~/.magia/themes/ using the notify crate. Any create, modify, or delete event triggers a debounced themes:changed Tauri event (500 ms debounce). The frontend listens for this event and reloads all external themes automatically. There is no need to restart Magia after editing or adding a theme file.
Applying themes programmatically
Section titled “Applying themes programmatically”Themes are applied by writing CSS custom properties to :root via applyTheme(theme, mode). This sets all color, shape, and font variables as inline styles. Selecting Stone Rose calls clearTheme() instead, which removes all inline overrides and lets the CSS defaults take over.