Theme Engine
Zync themes are portable JSON files that restyle both the UI shell and the XTerm terminal canvas using a semantic color token system. No CSS knowledge required.
How themes work
A theme is a .zip containing two files:
manifest.json— Declares the theme identity, mode, and preview colors shown in the marketplace.theme.json— The color token map applied to the UI and terminal.
Themes are installed and applied through Settings → Appearance. Zync ships with 11 built-in themes (Dracula, Monokai, Catppuccin, Solarized, etc.) and can load any installed theme from the marketplace.
manifest.json
The manifest.json for a theme uses the same format as a plugin but references a style file instead of main:
{ "id": "com.yourname.theme.mytheme", "name": "My Theme", "version": "1.0.0", "description": "A short description shown in the marketplace.", "author": "Your Name", "style": "theme.json", "mode": "dark", "preview_bg": "#1f1f2e", "preview_accent": "#f92aad"}mode—"dark"or"light". This controls which OS/browser mode preference the theme matches.preview_bg— Background color shown as a swatch in the marketplace and settings grid.preview_accent— Accent color shown alongside the background in the swatch.
theme.json — color tokens
The theme.json defines two sections: UI colors (the app shell) and terminal colors (the XTerm canvas). All values are hex strings.
UI color tokens
| Token | What it controls |
|---|---|
| background | Primary root background of the entire app |
| surface | Secondary panels — sidebar, settings modal, cards |
| primary | Brand accent — active tabs, focus rings, buttons |
| border | Subtle dividers and component borders |
| text | Default foreground text color |
Terminal color tokens
The terminal object maps the 16 standard ANSI colors directly to XTerm, plus background, foreground, and cursor:
| Token | Description |
|---|---|
| background | Terminal canvas background |
| foreground | Default text color in terminal |
| cursor | Cursor color |
| black / red / green / yellow | Standard ANSI colors 0–3 |
| blue / magenta / cyan / white | Standard ANSI colors 4–7 |
Full example
{ "name": "Synthwave", "type": "dark", "colors": { "background": "#262335", "surface": "#1f1f2e", "primary": "#f92aad", "border": "#363655", "text": "#ffffff", "terminal": { "background": "#262335", "foreground": "#ffffff", "cursor": "#f92aad", "black": "#000000", "red": "#fe4450", "green": "#72f1b8", "yellow": "#fede5d", "blue": "#03edf9", "magenta": "#f92aad", "cyan": "#03edf9", "white": "#ffffff" } }}Light vs dark themes
Set "mode": "light" in your manifest for light themes. Light themes should use high-contrast text on a light background. Key differences from dark themes:
- background — Use a near-white or warm-white color (e.g.
#fafafa,#fdf6e3). - surface — Slightly darker than background for contrast (e.g.
#f0f0f0). - text — Dark color for readability (e.g.
#111111). - border — Light grey (e.g.
#e2e2e2). - terminal colors — Use darker variants of each ANSI color so they're readable on the light background.
Best practices
- Contrast — Ensure sufficient contrast between
textandbackground(WCAG AA minimum is 4.5:1). Use a tool like Coolors Contrast Checker. - Consistent primary — The
primarycolor should work well on bothbackgroundandsurfacesince it appears on both. - Terminal legibility — Test all 8 ANSI colors on your terminal background. Each color should be distinct and readable. Avoid very similar hues for
green/cyanorred/magenta. - Cursor visibility — Make the cursor color stand out from both common foreground text and the terminal background.
- Use existing themes as reference — Look at the built-in Dracula, Monokai, or Catppuccin themes in the zync-extensions repo for well-tested color mappings.
Packaging and publishing
Package your theme the same way as a plugin — zip both files with manifest.json at the root:
$zip -r my-theme.zip manifest.json theme.jsonTo publish to the official marketplace, open a Pull Request to the zync-extensions repository. Add your theme files under themes/your-theme-id/, host the .zip at a permanent URL, and add an entry to marketplace.json. See the Plugins guide for the full PR workflow.