HousetableDesign System2025
Multi-bank theming
TL;DR
Housetable needed to support multiple lenders, each with their own brand identity, without rebuilding the UI every time. The solution was a three-layer token architecture that separates brand expression from UI semantics: any lender can theme the product by changing a handful of tokens, and nothing else. One semantic layer, any number of brands, and switching is one line of code.
121
tokens across 4 Figma collections
3
bank modes: Housetable, Tower, Patelco
1
CSS class to switch an entire brand
The problem
It wasn't a color problem. It was an architecture problem.
When I joined Housetable, the product needed to support three lenders with different brand identities. The existing approach defined all three palettes in parallel in Figma with no semantic layer, causing contrast failures, inconsistency, and 3× the work for every change.
The architecture
Three layers. One rule: meaning never changes.
The system is built on a strict separation of responsibilities. Components reference only semantic tokens. Semantic tokens point to brand tokens. Brand tokens are the only thing lenders ever touch.
Layer 01 · Core
Owned by: Design System
System-locked tokens that define hierarchy, accessibility rules, and UX logic. These never change, not per lender, not per screen. Accessibility is enforced here, not hoped for.
Layer 02 · Semantic
Owned by: Design System
Semantic tokens define the purpose of a color, never its value. action/primary means "the main CTA action." What that resolves to visually is delegated entirely to the brand layer. Components only ever reference semantic tokens.
Layer 03 · Brand
Owned by: The Lender
Brand tokens define the lender's visual palette. They supply values to semantic tokens but are never used by components directly. A lender can change what a token looks like. They cannot change what it means, how it's structured, or where it's used. Expression, not semantics.
Live demo
Same components. Any bank.
Switch the brand layer and watch the UI re-theme without a single component change. Components reference semantic tokens; semantic tokens resolve to whichever brand layer is active.
Fully live: switch the bank on the left rail and every component re-themes.
Governance
Brand expression has limits. So does the lender.
A flexible system isn't a permissive one. Lenders own the brand layer: they can change what colors look like, but never what they mean. The structure stays in our hands.
The locked core defines what every color means. The flexible ring defines what every color looks like for a specific lender. Lenders operate on the outside, never on the inside.
Token reference
Every color has a reason to exist.
The semantic layer is organized into five categories: Action, Surface, Status, Text, and Icon. Nothing is named by appearance. Everything is named by role.
| Token | Category | Meaning | Typical usage | Lender override? |
|---|---|---|---|---|
| action/primary | Action | Main user action | Primary CTA buttons | Yes · brand color |
| action/destructive | Action | Dangerous / irreversible | Delete, Reject | No · always red |
| surface/page | Surface | Main page background | Full page background | Tones only (off-white) |
| surface/elevated | Surface | Elevated surface | Modals, popovers | No · must be white |
| status/error | Status | Error state | Errors, failures | No · always red |
| surface/brand-subtle | Surface | Soft brand background | Banners, highlights | Yes · soft brand tint |
| text/primary | Text | Primary text | Headings, main content | No · accessibility locked |
| icon/brand | Icon | Decorative / brand icon | Section icons, onboarding | Yes · brand color |
Designed for developers
From Figma to code, without the guesswork.
A well-structured token system means developers never have to guess what a color is for, and switching lender themes requires changing exactly one thing.
| color / brand | Housetable | Tower | Patelco |
|---|---|---|---|
| primary | FF7A43 | 46A08C | 9A302E |
| primary-soft | FFE4D9 | E3F1EE | F5EAEA |
| primary-strong | D96839 | 1E453D | 3E1312 |
01
Figma Variables, the source of truth
All tokens live in Figma Variables across 4 collections (Brand, Semantic, Core, Typography), each with 3 modes. Every design decision starts here and nowhere else.
02
Variables to CSS, automatic export
A Figma plugin exports all tokens into a single CSS file with all 3 bank modes baked in. Any token updated in Figma, re-export, instantly in sync with code.
03
Mantine theme, write once
The developer maps CSS variables to a Mantine theme object once. Every component references the theme, never raw hex values. New components get the right colors from day one.
04
Bank switch, one line of code
Switching banks means changing one CSS class on the HTML root. Every button, badge, nav item and card re-themes instantly. No designer involvement required.
The exported tokens.css. One file, three bank modes.
The impact
Why it matters.
1
One line re-themes the whole product. Changing a bank's colors never touches a component.
0
Component changes to onboard a bank. Screens read semantic tokens, so design never re-skins them.
AA
WCAG AA contrast enforced once at the core layer, inherited by every bank automatically.
Any
Bank ships from a single brand-layer file. Adding a credit union edits one token set.
Before this system, the developer needed the designer in the room for every decision. Now the system answers instead.
Also check out..