Color Scheme & Theme
Per-user UI theme that follows you across devices. Pick from nine presets (Midnight, Slate, Charcoal, Ocean, Ember, Maroon, Forest, Ivory, Cloud) or build a custom palette with per-element color pickers. The choice is saved on your User row server-side, so logging in from a different machine restores it within one network round-trip.
Steps
- Settings > Customize > Color Scheme.
- Click any preset tile to apply it instantly. The active preset shows an "Active" badge in its accent color.
- For a custom palette: click the "✨ Custom" tile, then either pick from the built-in palettes (Purple Night, Rose Gold, Sunset, Neon, Sage, Warm Sand) or tweak each color individually with the color picker / hex input.
- A live preview at the bottom of the custom editor shows roughly how the chrome, sidebar, cards, and accent button will look together before you commit.
- Light themes (Ivory, Cloud, or any custom palette with a light pageBg) automatically flip the data-scheme attribute and shadcn .dark class so text contrast stays correct.
Good to know
- Themes sync across devices via User.themePrefs (added 2026-04-28). On a brand-new device the dashboard paints with the default Midnight, then switches to your saved theme within ~one round-trip — a brief flicker only on first login from that device.
- localStorage still caches your last theme on every device for zero-flicker on returning visits.
- "Last write wins" — if you change theme on a laptop and then on a phone before the laptop has refetched, the phone's save wins. No version vectors.
- Custom palette colors only apply when the "Custom" tile is selected. Switching to a preset clears the custom CSS variables; switching back to Custom re-applies your saved palette without losing it.
- Brand colors (used in outbound emails, generated PDFs, the Client Hub portal, etc.) are separate from per-user theme — set those under Settings > Customize > Brand Colors at the org level.
Example: A consultant works on a 32" desktop in their office (loves the Cloud light theme to match the bright room) and on a laptop in cafés (switches to Midnight to reduce battery drain on OLED). Before the cross-device sync shipped, every laptop session opened in Cloud — too bright outdoors. Now the laptop just remembers its own picked theme; no per-device toggling.
Troubleshooting
Theme reset to Midnight after I logged in on a new device
First paint runs before the GET /users/me/theme-prefs round-trip completes, so the inline script defaults to Midnight until your saved preference loads.
Fix: Wait one second — the saved theme applies as soon as the request returns. Subsequent visits on that device are flicker-free because localStorage now caches it.
Custom colors I picked yesterday are gone
Either the theme picker was switched to a preset (which clears the CSS vars from the page but keeps the palette in storage), or the saved palette failed validation server-side.
Fix: Click the "✨ Custom" tile to re-apply your saved palette. If the colors really are gone, check the API response for /users/me/theme-prefs — invalid hex strings get rejected by the PATCH validator.
My phone shows a different theme than my laptop
You changed the theme on one device and the other hasn't reloaded since.
Fix: Reload (or just open the dashboard fresh) — useTheme reconciles with the server on every mount and overwrites the local cache when they differ.
Light theme makes some pages unreadable
A page is using shadcn tokens but doesn't respect the .dark class flip. Light themes set data-scheme="light" and remove .dark; dark themes do the opposite.
Fix: File a bug — the page needs to honor the .dark class. Workaround: switch to a dark preset (Midnight / Slate / Charcoal / etc).