One interface, many skins — yours to pick
Every Sierra Hub module reads its colours, fonts, corners, and shadows from a single shared token set — the whole platform can wear any of these skins by swapping one block of values. The board now includes four practice palettes (Sierra, Springbank Hill, Midpark, Chinook) built from each clinic’s real brand colours, plus a range of general themes. And the choice is personal: each staff member will pick their preferred skin in the new Profile & settings module (me.sierrahub.ca → Appearance tab), and their pick follows them to every module on every device. Votes here decide two things: (a) which theme is the default for anyone who never picks, and (b) which themes make the personal picker. Below, the exact same sample screen (a mini Lead 360 cockpit) is rendered once per theme.
Each theme below shows the same mini cockpit: top bar, three KPI tiles, an outstanding-treatment worklist, hygiene coaching bars, an AI synthesis card, a Workspace banner, and the two button styles. Under each sample: the core colour tokens, the non-colour changes (typography, corner radius, shadow, blob character), and your voting row.
Vote 👍/👎 for gut reaction, pick Ship it / Maybe / No for the verdict, and leave a note if you want a hybrid (mixing is cheap — e.g. Porcelain's restraint with Editorial's serif). Use Compare side-by-side in the sticky bar to pit any two head-to-head.
The selected theme colours only the chrome: the wordmark accent, eyebrows, the active nav/tab, the module chip, buttons, tracks and section accents. The data itself never changes colour with the theme — a good number is green, an in-between number is amber, and a bad / overdue number is red, identically in every skin — because colour on a number means the number, not the brand. Watch the row of three KPI tiles and the worklist chips as you scroll: the top-bar and buttons re-skin per theme, but the tiles stay green / amber / red throughout.
Practice palettes also carry a secondary brand accent (Midpark’s burgundy, Sierra’s slate) on the “Lead 360” module chip — so the brand shows in more than one place without ever touching the data colours.
Every card's blob is dictated by its meaning, and the mapping is identical in every theme — only the saturation and tone adapt to each palette (the dark themes glow brighter so the tints still read). This same semantic system runs across all the module pages (Lead 360, Dentist 360, Workspace, …): a gold corner always means money, a rose corner always means risk — whichever skin you're in.
Design the final theme here — set the accent, the page background, or jump to a practice palette. Everything updates the “Your look” preview on the left instantly. The data tiles stay green/amber/red no matter what — only the chrome recolours.
Each theme rendered once with its tokens, spec chips and voting row. Toggle Show backups above to also reveal the retained backup palettes. Use the pinned compare view up top to pit any two head-to-head.
Every module page carries the same token block — colours, fonts,
radii, shadows, semantic blob tints. Pages never hardcode a hex; they only ever say "primary", "risk",
"money", "AI". Each theme on this board is a complete, drop-in token set. What changed: the winner is no
longer forced on everyone. The vote crowns the platform default and picks the shortlist;
each staff member then chooses their own skin in Profile & settings (me.sierrahub.ca →
Appearance). Their pick is stored once (app.user_prefs.theme_key)
and applied as a class on the app shell at sign-in — one row, every module, every device. Per-practice
theming (Midpark blue, Springbank green) still layers on top of whichever base skin the person chose.
◆ For Elijah — per-user theming, end to end
Data
New table app.user_prefs: user_id uuid PK REFERENCES auth.users(id),
theme_key text NOT NULL DEFAULT 'vz1' (allowed values = the shortlist this board
produces, VZ1–VZ19), updated_at timestamptz. RLS: own-row read/write; exec read-all.
Any view over it: security_invoker = true.
Resolver order (app shell, at login)
1. User pick — user_prefs.theme_key → class theme-<key> on
the app shell. 2. Per-practice theme — the existing §0t classes
(.theme-midpark etc.) layer on top for practice-branded chrome, untouched.
3. Platform default — this board's winning theme, for anyone with no row.
Picker surface
me.sierrahub.ca — Profile & settings, Appearance tab: renders this page's
mini-cockpit once per shortlisted theme; one tap calls server action setThemePref(themeKey)
which upserts user_prefs and re-applies the shell class without reload.
Votes + deploy surface
Verdicts here persist to app.future_votes (item_ids VZ1–VZ19; VZ1–VZ10 are
the earlier set and VZ11–VZ14 are the four practice palettes, so earlier votes stay valid). Until the
modules fold into the Next.js app, the 12
subdomain mockups (leads, hyg, ast, adm, hr, ortho, tc, cdgadmin, schedules, dentists, execs, visuals)
keep their static token blocks — the default-winning set is a copy-paste swap into each page's
<style> head.
Ship order
1. Migration: user_prefs + RLS. 2. Shell resolver in app/(app)/layout.tsx.
3. Appearance tab on me.sierrahub.ca with the shortlisted themes. 4. Token classes .t1–.t10
from this file become the canonical theme definitions in app/globals.css.