Theme format¶
Theme packages are JSON files that override chatwire's CSS variable system. They control colors, spacing, typography, avatar style, and can inject arbitrary CSS.
File location¶
Drop .json files in ~/.chatwire/themes/. They appear in Settings → Themes → Theme Packages automatically (no restart needed).
Top-level schema¶
{
"name": "my-theme",
"author": "Your Name",
"version": "1.0.0",
"colors": { ... },
"structure": { ... },
"decorations":{ ... },
"custom_css": "..."
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Lowercase kebab-case slug. Used as CSS selector and data-theme-pack attribute. |
author |
string | no | Display name shown in the UI |
version |
string | no | Semver string, shown in the UI |
colors |
object | no | CSS color variable overrides |
structure |
object | no | Spacing, radius, font overrides |
decorations |
object | no | Avatar, bubble, shadow overrides |
custom_css |
string | no | Arbitrary CSS injected into the document |
Any combination of sections is valid — a colors-only package, a structure-only package, or all four together.
colors section¶
Maps semantic token names to CSS color values. Any valid CSS color syntax works: hex, rgb(), hsl(), oklch(), named colors.
Color tokens¶
| Token | Used for |
|---|---|
background |
App background |
foreground |
Default text color |
card |
Card / panel background |
card-foreground |
Text on cards |
popover |
Dropdown / popover background |
popover-foreground |
Text in popovers |
primary |
Primary action color (buttons, highlights) |
primary-foreground |
Text on primary-colored elements |
secondary |
Secondary UI elements |
secondary-foreground |
Text on secondary elements |
muted |
Muted background (subtle panels) |
muted-foreground |
Muted / de-emphasized text |
accent |
Accent highlights |
accent-foreground |
Text on accent elements |
destructive |
Destructive action color (delete, error) |
destructive-foreground |
Text on destructive elements |
border |
Border color |
input |
Input field background |
ring |
Focus ring color |
sidebar-bg |
Sidebar background (can differ from background) |
info |
Info state color |
warning |
Warning state color |
success |
Success state color |
msg-me |
Sent message bubble background |
msg-me-text |
Sent message text color |
msg-them |
Received message bubble background |
msg-them-text |
Received message text color |
msg-sms |
SMS/RCS message bubble background |
msg-sms-text |
SMS/RCS message text color |
Example¶
"colors": {
"background": "#0d1117",
"foreground": "#c9d1d9",
"primary": "#58a6ff",
"sidebar-bg": "#010409",
"msg-me": "#1f6feb",
"msg-me-text": "#ffffff",
"msg-them": "#21262d",
"msg-them-text": "#c9d1d9",
"border": "#30363d"
}
structure section¶
Controls spacing, sizing, and typography. Values must be valid CSS length strings (0.5rem, 8px, 1).
| Token | Used for |
|---|---|
radius |
Base border-radius |
radius-bubble |
Message bubble corner radius |
radius-input |
Input field corner radius |
spacing-message |
Vertical gap between messages |
spacing-sidebar |
Vertical gap between sidebar items |
font-size-message |
Message text font size |
font-size-sidebar |
Sidebar text font size |
shadow-card |
Box shadow for cards |
sidebar-width |
Sidebar panel width |
Example¶
"structure": {
"radius-bubble": "4px",
"radius-input": "4px",
"spacing-message": "2px",
"font-size-message": "0.9rem",
"sidebar-width": "260px"
}
decorations section¶
Fine-grained visual details: avatars, bubble styles, borders, and animations.
| Token | Used for |
|---|---|
avatar-shape |
Avatar border-radius (50% = circle, 0 = square, 8px = rounded) |
avatar-size |
Avatar width/height |
avatar-border |
CSS border for avatars |
bubble-shadow |
Box shadow on message bubbles |
bubble-tail |
Custom CSS for the message tail decoration |
header-shadow |
Box shadow on the chat header bar |
header-border |
Border on the chat header bar |
sidebar-divider |
Divider between sidebar items |
border-width |
Global border width |
transition-speed |
Animation/transition duration |
Example¶
"decorations": {
"avatar-shape": "8px",
"bubble-shadow": "0 2px 6px rgba(0,0,0,0.25)",
"header-border": "none",
"transition-speed": "100ms"
}
custom_css section¶
Arbitrary CSS injected verbatim into a <style> block in the document.
Security restrictions¶
Before injection, chatwire sanitizes custom_css:
@importrules are stripped — external stylesheets cannot be loadedurl(http://...)andurl(https://...)are replaced withurl(about:blank)— prevents tracking pixels and external requests
Everything else is preserved: selectors, animations, custom properties, var(), calc(), pseudo-elements. data: URIs and fragment references (url(#id)) are always preserved.
When sanitization occurs, the UI shows a notice: "This theme includes custom CSS (some external references were sanitized)."
How activation works¶
- Drop your
.jsonfile into~/.chatwire/themes/ - Open Settings → Themes → Theme Packages
- Select the package from the dropdown
- The package CSS is injected and
data-theme-pack="<name>"is set on<html> - All variable overrides become active immediately
Priority order¶
Later layers override earlier ones:
- Base CSS (chatwire defaults)
- Built-in scheme variables
- Theme package variables
- Individual accent color override (Settings → Accent color)
- Custom CSS (Settings → Custom CSS)
Your per-Settings overrides always win over the theme package. Import a package for its overall aesthetic and override specific colors in Settings without editing the file.
Example: complete GitHub Dark package¶
{
"name": "github-dark",
"author": "chatwire community",
"version": "1.0.0",
"colors": {
"background": "#0d1117",
"foreground": "#e6edf3",
"card": "#161b22",
"card-foreground": "#e6edf3",
"primary": "#58a6ff",
"primary-foreground": "#ffffff",
"secondary": "#21262d",
"secondary-foreground": "#c9d1d9",
"muted": "#161b22",
"muted-foreground": "#8b949e",
"accent": "#1f6feb",
"accent-foreground": "#ffffff",
"destructive": "#f85149",
"destructive-foreground": "#ffffff",
"border": "#30363d",
"input": "#21262d",
"ring": "#58a6ff",
"sidebar-bg": "#010409",
"msg-me": "#1f6feb",
"msg-me-text": "#ffffff",
"msg-them": "#21262d",
"msg-them-text": "#c9d1d9"
},
"structure": {
"radius-bubble": "6px",
"radius": "6px"
},
"decorations": {
"avatar-shape": "50%"
}
}
Sharing themes¶
Theme packages are self-contained JSON files. Share them directly — recipients drop the file in ~/.chatwire/themes/ and it appears in the picker immediately.