HousetableDesign System2025

Multi-bank theming

H T P BRAND THEME Housetable Tower CU Patelco #FF7A45 #4EA08C #AA302E color/brand/primary DERIVED SCALE · 100 → 900 SEMANTIC MAPPING action/primary Primary CTA brand surface/brand-subtle Brand banner brand surface/page Page background core text/primary Headings & body core status/error Errors & alerts semantic Components read meaning, not raw color.

Role

Product Designer

Duration

April 2025

Teams

Design · Dev

Tools

Figma · Tokens Studio

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.

BEFORE, PARALLEL PALETTES, NO STRUCTURE

Housetable

Tower Credit Union

Patelco

⚠ No shared structure. Contrast failures in Borrower 2 & 3. Every screen change = 3× the work. New borrower = rebuild everything.

AFTER, SEMANTIC TOKEN SYSTEM

action/primarySEMANTIC
surface/brand-subtleSEMANTIC
text/primarySEMANTIC
color/brand/primary [Housetable]BRAND
color/brand/primary [Tower]BRAND
color/brand/primary [Patelco]BRAND
✓ One semantic token. Any number of brand values. Every component adapts automatically.

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.

color.text.primary color.surface.page color.border.default color.status.error shadow.focus

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.

action/primary action/quiet surface/card surface/brand-subtle text/secondary

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.

color/brand/primary color/brand/secondary color/brand/accent color/surface/subtle

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.

TokenCategoryMeaningTypical usageLender override?
action/primaryActionMain user actionPrimary CTA buttonsYes · brand color
action/destructiveActionDangerous / irreversibleDelete, RejectNo · always red
surface/pageSurfaceMain page backgroundFull page backgroundTones only (off-white)
surface/elevatedSurfaceElevated surfaceModals, popoversNo · must be white
status/errorStatusError stateErrors, failuresNo · always red
surface/brand-subtleSurfaceSoft brand backgroundBanners, highlightsYes · soft brand tint
text/primaryTextPrimary textHeadings, main contentNo · accessibility locked
icon/brandIconDecorative / brand iconSection icons, onboardingYes · 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 / brandHousetableTowerPatelco
primaryFF7A4346A08C9A302E
primary-softFFE4D9E3F1EEF5EAEA
primary-strongD968391E453D3E1312

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.

Figma Variables tokens.css Mantine theme class="theme-tower"

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.