Appearance & Theming¶
Overview¶
JustIAM provides a per-user theming system with three modes: Light, Dark, and Custom. Each user can choose their preferred mode from the Appearance settings page in their profile. Language selection is also available there.
Custom mode allows overriding individual CSS design tokens on top of either the light or dark base theme, enabling personalized branding without affecting other users.
Language¶
Navigate to Profile → Appearance to select the interface language. The selection is applied immediately without a page reload.
Theme Modes¶
| Mode | Description |
|---|---|
| Light | Clean light interface with white surfaces and dark text |
| Dark | Dark interface with slate surfaces and light text |
| Custom | User-defined color overrides layered on a chosen base (light or dark) |
Selecting a Theme¶
Quick switch from the top bar¶
Click the theme icon (sun / moon / palette) in the top-right header to instantly cycle between Light, Dark, and Custom modes. The selection is saved to your profile automatically — it will persist across page reloads and other devices.
Appearance Settings¶
Navigate to Profile → Appearance to:
- Choose the interface language
- Choose the active theme mode
- Select a base theme for custom mode (light or dark)
- Override individual color tokens with a visual color picker
- Export or import custom themes as JSON files
Custom Theme¶
Base Theme¶
Custom mode always starts from a base — either light or dark. Tokens you don't override inherit from the base theme. This means you only need to customize the colors you want to change.
Auto-Derivation¶
Some tokens are automatically derived when you change a "root" token:
- Accent → auto-generates accent-hover, accent-soft, accent-text
- Danger → auto-generates danger-soft, danger-border
- Badge colors → auto-generates badge background (20% opacity) and badge text
You can still override derived tokens individually via JSON import.
Token Categories¶
| Group | Tokens |
|---|---|
| Backgrounds | Page, Surface, Elevated, Sunken, Input |
| Text | Primary, Secondary, Muted, Faint, On-brand |
| Borders | Default, Subtle, Strong |
| Brand | Color, Hover, Soft, Text |
| Interaction States | Hover, Active, Selected, Focus ring |
| Danger | Main, Soft |
| Badges | Green, Red, Blue, Yellow, Amber, Slate |
| Chrome | Scrollbar track/thumb, Chart lines/bar track |
Export / Import¶
Custom themes can be exported as JSON files for sharing or backup. The export format is versioned for future compatibility:
{
"version": 1,
"base": "dark",
"overrides": {
"--t-accent": "#8b5cf6",
"--t-bg-page": "#1a1a2e"
},
"exportedAt": "2026-04-30T12:00:00.000Z"
}
Import applies the base and all overrides from the file. Save to persist the imported theme.
API¶
Theme preferences are stored per-user via the preferences API:
| Key | Value | Description |
|---|---|---|
theme_mode |
light / dark / custom |
Active theme mode |
theme_base |
light / dark |
Base preset for custom mode |
theme_overrides |
JSON string | Map of CSS variable overrides |
Endpoints¶
GET /api/v1/me/preferences → all preferences
GET /api/v1/me/preferences/:key → single preference value
PUT /api/v1/me/preferences/:key → set preference { "value": "..." }
DELETE /api/v1/me/preferences/:key → remove preference
All endpoints require authentication. Preferences are scoped to the authenticated user.
Design Tokens¶
All UI colors are defined as CSS custom properties (e.g. --t-accent, --t-bg-surface). Components use Tailwind utility classes mapped to these variables. Switching themes changes the data-theme attribute on <html>, which activates the corresponding CSS ruleset.
In custom mode, the base theme's CSS is loaded via data-theme="light" or data-theme="dark", and user overrides are applied as inline styles on <html>.