Skip to content
AK.
All case studies
01 / 09Healthcare / Genomics

Genomas Health Platform

A Turborepo monorepo serving three healthcare products from one typed design system.

Role

Senior Frontend Engineer — frontend architecture & delivery lead

Engagement

Full-time at Segwitz

Client

Genomas

Period

2023 — Present

Genomas Health Platform — interface screenshot
Novameds B2B · Reveal B2C · Admin PortalFig. 01 — interface reference

The problem

Three healthcare products had grown from the same origin into three codebases, each with its own component library, its own fetch layer and its own idea of what a button does. Features shipped to one product had to be re-implemented in the others, healthcare-specific states (loading, empty, error, restricted-by-role) were inconsistent, and clinical reviewers were seeing different behaviour for the same data on different surfaces. Release risk was climbing faster than the roadmap.

My responsibility

Frontend architecture and delivery lead across all three surfaces. I defined the monorepo structure and package boundaries, set the data-fetching and state conventions, built the shared component and type layer, reviewed every significant PR, and worked directly with product and clinical stakeholders to turn ambiguous healthcare requirements into typed interfaces.

Surfaces shipped

Novameds B2B

Wholesale ordering surface for clinics and distributors: catalogues, negotiated pricing tiers, multi-cart checkout and order history.

Reveal B2C

Consumer-facing genetic testing storefront with kit selection, a guided sample-registration flow and result delivery.

Admin Portal

Internal operations console — patient and sample records, lab pipeline states, user roles, content and reporting.

Admin Portal — clinical records, dense tables, audit states
Admin Portal — clinical records, dense tables, audit states
Reveal — consumer storefront and guided checkout
Reveal — consumer storefront and guided checkout

Architecture

How it was structured, and the reasoning behind each boundary.

  1. 01

    Turborepo monorepo

    Three apps — novameds, reveal, admin — plus shared packages for ui, hooks, api-client, types and config. Task graph with remote caching means a change to a shared component rebuilds only what depends on it, and CI stays under control as the repo grows.

  2. 02

    Server state with React Query

    One query-key factory per domain, explicit stale times, and an invalidation map co-located with mutations. Optimistic updates only where the backend contract guarantees them. Prefetching on intent for the flows where perceived latency mattered most.

  3. 03

    UI state with Zustand

    Cart, filters, wizard progress and panel layout live in small Zustand slices with selectors, kept entirely out of the server cache. The rule enforced in review: if the server owns it, React Query owns it.

  4. 04

    Typed contracts end to end

    API response types generated from backend schemas and consumed by all three apps, so a field rename is a compile error rather than a runtime surprise in a clinical workflow.

  5. 05

    Role-aware rendering

    A single permission model drives navigation, row-level actions and route guards across Novameds, Reveal and Admin — implemented once in the shared layer instead of three times with drift.

Key challenges

  1. 01

    Merging three design languages without stalling delivery

    A big-bang rewrite was off the table — features kept shipping. I extracted the shared UI package incrementally, starting with the highest-usage primitives, and codemodded consumers app by app so each migration was independently shippable and revertible.

  2. 02

    Healthcare-grade data handling

    Clinical records mean PII, strict role boundaries and audit trails. Every list, export and mutation needed explicit permission checks, defensive empty states and no client-side caching of sensitive payloads beyond what the flow required.

  3. 03

    Cache coherence across tabs and roles

    An admin action can invalidate data a B2B user is looking at. Invalidation was modelled per domain rather than per screen, with targeted query invalidation instead of blanket refetches that would have hammered the API.

  4. 04

    Long, stateful multi-step flows

    Sample registration and wholesale checkout both span several steps with validation and resumability. A shared wizard primitive handles persistence, step validation and deep-linkable state so each product only writes its business rules.

Implementation

  1. 01

    Defined the boundaries first

    Before moving code, I documented what belongs in each package and why — including what deliberately stays app-specific. That document is the reason the monorepo hasn't decayed into a shared-everything ball of mud.

  2. 02

    Shared UI with documented states

    Components ship with Storybook stories for default, hover, focus, loading, empty, error and disabled. Healthcare flows live or die on the error state, so those were written first, not last.

  3. 03

    Progressive migration

    Legacy screens were wrapped rather than rewritten where a rewrite carried no user-visible benefit, buying time to spend on the flows that did matter.

  4. 04

    Performance guardrails in CI

    Bundle size budgets, lint rules against barrel-file imports in shared packages, and build time tracked per app so regressions surface in the PR that caused them.

Results

3

Products on one codebase

1

Shared design system

B2B · B2C · Admin

Surfaces covered

  • 01Three products now ship from one design system and one type layer — a component built once appears on all three surfaces.
  • 02Duplicated fetch and caching bugs dropped sharply once server state and UI state had enforced homes.
  • 03Onboarding a new frontend engineer takes days rather than weeks: one repo, one convention doc, one component catalogue.
  • 04CI time stayed flat through the migration thanks to Turborepo caching, even as the number of apps grew.
  • 05Role-based access and audit behaviour are now consistent across B2B, B2C and internal admin.

Technologies

  • Next.js
  • React
  • TypeScript
  • Turborepo
  • React Query
  • Zustand
  • Tailwind CSS
  • Storybook
  • Jest
  • Cypress
  • GraphQL
  • Docker

Technical highlights

  • Turborepo app/package topology designed for three diverging products
  • Query-key factory + invalidation map as a team convention
  • Shared wizard primitive with resumable, deep-linkable multi-step state
  • Incremental design-system extraction with zero delivery pause

Building something similar? I’d like to hear about it.

Start a conversation