Yogi Prasetya monogram logo
Skill Graph
Loading theme switcher
Projects

React Design System

Shorter ship cycles, one UI system for all teams

Problem

Smarteye shipped multiple products: VR/AR experiences, immersive web tours, enterprise portals, all built by the same frontend team. Every new project started the same way: copy components from the last project, adjust them manually, and discover three weeks later that the copies had diverged. There was no shared source of truth for UI patterns and no systematic way to check visual correctness across the product line.

As the team grew from 4 to 6 engineers, the inconsistency got worse. Two engineers implementing the same component would produce two different results, both shipped.

Role

I designed and built the design system end to end, working directly with the product and design teams to extract the canonical component set. I also wrote the Storybook stories and documentation, and drove adoption across the active products.

Approach

Component extraction over invention

Rather than designing components from scratch, I audited the existing products to find what already existed. Any UI element that appeared in more than one product became a candidate for the shared library.

The extraction process was deliberately conservative: the first version of every component matched the most common existing usage, not an idealized spec. Engineers were already familiar with the output, which made adoption faster.

Storybook as the contract

Each component had a Storybook story for every meaningful state: default, disabled, loading, error, empty. The story was the spec. If a component didn't have a story for a state, that state wasn't guaranteed to work.

This gave designers and PMs a browsable, always-current reference, which cut the round-trip cost of design reviews. "Does it look like the design?" became answerable without shipping to staging.

Composition over configuration

The component API was built around composition rather than a growing list of boolean props. A Button has a variant enum and accepts children. It doesn't have 15 variant props. This kept the API surface predictable and the component tree readable.

Zero-friction adoption

The library was published as an internal npm package with a semver contract. Consuming products pinned to a version and updated on their own schedule, with no coordinated deploys across teams.

Technical Decisions

Why React + TypeScript from day one?

Smarteye's product codebases were already React. TypeScript gave us prop validation at the call site: engineers got autocomplete for valid values and a compile-time error for invalid ones. The main benefit was fewer runtime errors from misused components.

Why Storybook over a custom documentation site?

Storybook gave us interactive documentation with no custom infrastructure. Stories doubled as manual test cases, and the Storybook build could be shared with designers without them needing a dev environment.

Why an internal npm package over a monorepo?

At the time, the consuming products were in separate repositories. A monorepo migration was a separate, larger project. Publishing a package let us ship immediately without restructuring existing products. The tradeoff was a publish step per release, which was acceptable for a library that changed infrequently once stable.

Outcome

  • New product UIs were assembled from proven components rather than rebuilt from scratch
  • Consistent UI across the entire Smarteye product line
  • Reduced the design-to-code iteration loop by giving designers a live, interactive reference
  • As new engineers joined, they learned the product's visual language through the component library rather than reading old code
ReactDesign SystemStorybook