2017 – 2021 · Senior Software Engineer · 6 min read
Enterprise Design System
Angular CDK component library, rebrandable design-token layer, and federated governance model that reached 150+ codebases at OneTrust, including a 50-app micro-frontend platform, 70 reusable libraries, and branded products that shipped on customized token overrides. Measurable drop in accessibility and visual-regression defects; a shared vocabulary across hundreds of engineers.
- Angular CDK
- TypeScript
- Design Tokens
- Storybook
An Angular CDK component library, a rebrandable design-token layer, and a federated governance model that reached 150+ codebases at OneTrust: roughly 50 micro-frontend sub-applications, 70 reusable libraries, and a tail of branded products that shipped on customized token overrides. Accessibility and visual-regression defects dropped measurably once product teams adopted the system, and the micro-frontend shell pulled adoption in at the seams where product surfaces met the platform.
The problem
OneTrust grew through acquisition, and the UI surface grew with it. By the time the design system shipped, the frontend estate spanned 150+ codebases: roughly 50 micro-frontend sub-applications assembled into the admin and consumer shells, 70 reusable libraries shared across those apps, and a tail of acquired or externally-branded products that sat alongside the core portfolio. Each acquired product shipped its own UI conventions, its own color values, its own spacing, and its own interaction patterns. The customer experience fragmented at every seam: a single admin session could cross four products that looked and behaved like four different vendors. Product engineers, designers, acquired-product integration teams, and the platform and shell teams that hosted them all paid the tax.
The root cause was not that every team had rebuilt every primitive from scratch. It was that there was no shared theming layer and no shared UI contract. Colors, spacing, typography, and interaction conventions lived inside each codebase as literals. Rebrands, dark mode, accessibility fixes, and simple brand adjustments had to be made across 150-plus codebases, by dozens of teams, on dozens of schedules.
The approach
The design system shipped as three layers, in that order:
- Design tokens first. Tokens defined color, spacing, typography, radius, and motion as the single source of truth. They were shaped for mono-brand delivery but sized for rebrandability: a future palette swap, a dark mode, or an acquired-product skin could drop in without touching component source. A handful of branded products did exactly that, shipping under their own identity via customized token overrides while consuming the unchanged component library underneath. The rebrandability promise was not theoretical; it was load-bearing.
- Components on Angular CDK, compound and slot-based. Rather than
shipping monolithic styled components or pure headless primitives, the
system exposed compound components with projection slots: a
DialogwithDialogHeader,DialogBody,DialogFooter; aMenuwith structured slots for trigger, list, and items. Consumers assembled UI from parts rather than configuring a single inflexible component. Angular CDK provided the accessibility and interaction primitives underneath. - Governance as the third product layer. A core team owned direction and reviewed every change; product teams contributed via a defined RFC and PR path. Breaking changes moved through an RFC, shipped under SemVer with deprecation cycles, and, where the change warranted it, ran as a parallel API alongside the old one until telemetry showed usage had fallen to near zero.
Distribution was deliberate, and adoption was not mandated. The micro-frontend shell required DS-rendered chrome (header, navigation, modal portal), which pulled every remote into the system at the boundary. Beyond the shell, product teams adopted because the compound API was faster to build against than their existing primitives. Pull plus structural force, not executive decree.
The outcome
Accessibility and visual-regression defects dropped measurably once product teams consumed DS components. A single keyboard-navigation fix or a single color-contrast fix in the core reached every surface that used the component, instead of requiring a parallel PR in every consuming codebase. Designers had one source of truth to mock against, and the gap between Figma and shipped UI narrowed to the parts teams consciously customized.
The shell became the most consistent surface at OneTrust first, because it was the only surface where adoption was forced by contract. Surfaces behind the shell followed at the pace their teams chose. The system remained small enough to govern because federation pushed authoring out to product teams while the core retained the review gate.
The principle
A design system is a product, not a project. That reframes every subsequent decision: it has consumers, not users; it has a roadmap, not a launch; it has SLAs around breaking changes, not a one-time migration window. Teams that treat the system that way ship one. Teams that treat it as a deliverable ship a library that decays.
The concrete expression of that principle, in retrospect, was distribution. The system had tokens, components, governance, and a healthy RFC process. What it did not have, early enough, were migration codemods. Rewriting accumulated call sites across 150-plus codebases was the slow grind that gated adoption at the long tail. Had distribution been treated as a first-class product surface from day one, with codemods shipped alongside every breaking change, the adoption curve would have pulled forward by quarters.