Themes
How the Ternux theme system works and how to create custom themes.
Ternux uses a JSON-based theme engine. Each theme is a standalone JSON file that defines color tokens, applied at runtime via CSS custom properties. This makes themes portable, user-creatable, and easy to maintain.
How it works
- Built-in themes live in
src/themes/*.jsonand are bundled at build time. - Custom themes live in
~/.config/ternux/themes/*.jsonand are loaded on startup. - The active theme's tokens are written to
<html>viaelement.style.setProperty(). - All components consume colors via Tailwind utilities like
bg-(--color-bg),text-(--color-text), etc. — zero component changes needed for new themes.
Theme JSON structure
Each theme file carries its own mode (dark OR light) — there is no separate dark/light toggle.
{
"id": "my-theme",
"name": "My Theme",
"description": "A custom dark theme",
"mode": "dark",
"author": "Your Name",
"colors": {
"accent": "#EEEEEE",
"bg": "#121213",
"panel": "#09090a",
"card": "#191a1b",
"line": "#212224",
"text": "#EAEDF5"
}
}Required color keys
Only 6 keys are required:
| Key | Purpose |
|---|---|
accent | Primary brand color (buttons, active states, selection rings) |
bg | Main window background |
panel | Sidebar / tab-strip background |
card | Card and panel surfaces |
line | Borders and dividers |
text | Primary text color |
All other tokens (surfaces, borders, text variants, syntax, terminal ANSI palette) are derived automatically at apply-time from these 6 core values. Theme authors can override any derived token by including it explicitly in the colors object.
Optional token groups
- Syntax highlighting (13 tokens):
syntax-keyword,syntax-string,syntax-comment, etc. - Terminal ANSI palette (20+ tokens):
terminal-bg,terminal-fg,terminal-cursor,terminal-red,terminal-green, etc. - Status colors:
danger,warn,indigo - Overlay:
overlay
See src/core/theme/theme-schema.ts for the complete schema.
Adding a custom theme
- Create a JSON file matching the schema above.
- Drop it into
~/.config/ternux/themes/. - Restart Ternux (or the theme loads automatically on next startup).
- The theme appears in Settings → Appearance → Theme gallery.
No code changes or config file edits required.
Built-in themes
| ID | Name | Mode | Description |
|---|---|---|---|
ternux-dark | Ternux Dark | dark | Default monochrome dark |
ternux-light | Ternux Light | light | Default monochrome light |
one-dark-pro | One Dark Pro | dark | VS Code inspired |
atom-one-light | Atom One Light | light | VS Code inspired light |
Technical details
- Engine:
src/core/theme/apply-theme.ts— pureelement.style.setProperty()loop, no class toggles or<style>injection. - Registry:
src/core/theme/theme-registry.ts— merges built-in + custom themes. - Migration: Old
theme+colorSchemeconfig fields are automatically mapped to an equivalentthemeIdon first load. - Splash screen: Critical colors are cached to
localStorageso the splash renders with the correct theme before JS loads. - Terminal:
resolveTerminalTheme()inLocalTerminal.tsxreads from the active theme's resolved palette — one code path for all themes.
All component styles must use CSS variable references (--color-*), never hardcoded color values. This rule applies to both Tailwind utilities and inline styles.