← All posts

·6 min read

One codebase, many banks: designing for white-label apps

When two financial institutions want the same product with different brands and rules, the answer is configuration, not branches.

ArchitectureReact NativeTheming
Contents
  1. Why branches are a trap
  2. Make the differences data
  3. Theme through tokens
  4. Keep release pipelines per tenant, code shared
  5. Test the matrix cheaply

White-label sounds simple: change the logo and the colours. In practice each client brings its own legal copy, feature flags, backend quirks, and release calendar. Here is the approach that has held up when one team serves several institutions from a single repository.

Why branches are a trap

Forking per client feels fast for a month. Then a security fix lands in one fork and not the other, features drift, and every merge turns into archaeology. A shared codebase makes the cost of a difference visible, which is exactly what you want.

Make the differences data

Every difference between clients should be expressible as a typed configuration object, resolved once at build or start-up. Code asks the config what to do; it never asks which client it is running for.

type TenantConfig = {
  id: string;
  theme: { primary: string; surface: string; radius: number };
  features: { quizzes: boolean; offers: boolean; savingsGoals: boolean };
  legal: { termsUrl: string; privacyUrl: string };
  api: { baseUrl: string };
};

// Wrong: if (tenant === "bank-a") { ... }
// Right: if (config.features.offers) { ... }

The rule of thumb: the moment you write a check against a client name, stop and add a field to the config instead.

Theme through tokens

  • Components consume semantic tokens (surface, primary, danger), never raw hex values.
  • Each tenant supplies a full token set, validated by the type system at build time.
  • Assets such as icons, illustrations, and fonts are resolved by tenant id from one registry.

Keep release pipelines per tenant, code shared

Different institutions want different release dates and have separate store listings, certificates, and signing identities. Parameterise the build by tenant id, so one commit can produce N artifacts, and let each client's go-live be a deployment decision rather than a code decision.

Test the matrix cheaply

Run the unit and snapshot suites across every tenant config in CI. Most white-label bugs are a missing token or a flag that was never considered for one client, and a loop over configs catches them before a stakeholder does.