All Work
Product BuildFamily office

BrightZen OS

A business operating system for a family office and the companies in its portfolio. One platform, three tiers of access, and a brand that repaints itself per tenant.

BrightZen OS — Command Central — the financial model, shown under a Weekly Accounting tenant brand. Figures are prototype data.
Command Central — the financial model, shown under a Weekly Accounting tenant brand. Figures are prototype data.

The problem

A family office holding a portfolio of operating companies has the same question about every one of them, every month: is this business actually working. The answer normally arrives late, in a spreadsheet, assembled by hand from whatever each company's bookkeeper happened to export.

BrightZen OS is the attempt to make that answer continuous instead of periodic — one system that every portfolio company operates inside, so the numbers are a by-product of the work rather than a monthly reconstruction of it.

One product, three tiers

The interface is split three ways, and the split is the architecture. A platform admin sees tenants and data health across everything. A tenant — the family office, or an accounting firm — sees the companies it manages. A company sees only itself.

That is not three products with shared components. It is one route tree, grouped by audience, where the same financial model screen renders for a company looking at itself and for a tenant looking at that company. Getting that right is what keeps 58 screens from becoming 150.

A brand that repaints itself

The screenshots here are not violet, and BrightZen's brand is. They show the platform running under a Weekly Accounting tenant — one of the portfolio companies — because the brand colours are CSS variables a tenant overrides at runtime rather than values compiled into the build.

Only three tokens move: primary, secondary and accent. Headings, surfaces and borders stay fixed, so a tenant can look like itself without being able to break contrast or drift the layout. White-labelling that lets a client change everything is white-labelling that eventually ships something illegible.

A token collision worth documenting

The shared Tailwind config deliberately does not define a --color-primary, and the reason is written into the file. When it did, bg-primary in the web app resolved to the brand violet while the identical class inside the shared UI package resolved to that package's own near-black. Because the app's stylesheet loads after the package's, an app-authored bg-primary silently shadowed the component's own rule.

The fix was to give the brand colour a different name — brand-primary — and leave primary to the component library. A naming problem rather than a styling one, and the sort that only appears once a design system is split across a package boundary.

Palette

Brand primary

#42307D

Violet — tenant-overridable

Brand secondary

#FFE169

Tenant-overridable

Brand accent

#A853BA

Tenant-overridable

Heading

#0A192F

Fixed across tenants

Container

#FFFDF3

Warm surface

Border

#E2E8FD

Cool hairline

Scope

Screens
58
Shared UI components
47
API files
929
DB schemas
50
Migrations
72
Tests
671

Screens

BrightZen OS — The CFO view — portfolio health across every company the tenant manages.
The CFO view — portfolio health across every company the tenant manages.
BrightZen OS — Dashboard.
Dashboard.
BrightZen OS — Operations.
Operations.

What we did

  • Product design
  • Design system — shared UI package
  • Multi-tenant white-labelling
  • Interface design — 58 screens
  • Full-stack build
  • Data modelling

Built with

  • Next.js 16
  • React 19
  • Tailwind 4
  • TanStack Query
  • Turborepo
  • NestJS 11
  • Drizzle ORM
  • Postgres
  • Supabase
  • Redis
  • BullMQ
  • Nix