Skip to main content
Back home

React TypeScript Migration

Five internal applications migrated incrementally without a big-bang rewrite

Context

Internal business applications were built with jQuery, server-rendered views, and ad-hoc JavaScript. Each app had its own patterns, no shared components, and adding features required touching multiple layers. Developer experience was poor and onboarding new devs took weeks.

The pain

Every new feature required custom UI code. There was no design system: buttons, forms, and layouts looked different across apps. Type safety was non-existent. Refactoring one app didn't help the others.

Why the old system failed

The original architecture assumed server-rendered pages with progressive enhancement. As requirements grew (real-time updates, complex forms, client-side validation), the jQuery approach became unmaintainable. No shared component library meant every team reinvented the wheel.

What I designed

I led the migration to React TypeScript. We built a custom shared component library with design tokens so all apps could share buttons, forms, modals, and layout primitives. We used the strangler fig pattern: new React routes lived alongside legacy pages, and we migrated route by route. The C# .NET Core API stayed the source of truth; we generated a TypeScript client from OpenAPI for end-to-end type safety. Vite gave us fast HMR and simple builds.

Tradeoffs considered

  • Delayed some feature work to invest in the shared library. Took 2 months before the first app saw benefits. It paid off: velocity on migrated apps tripled.
  • Chose gradual rollout over feature flags. Feature flags would have added complexity; we migrated whole routes at a time instead. Simpler mental model for the team.

Metrics

5
Apps migrated
3x
Velocity improvement
3
Teams on shared library

Lessons learned

  • Invest in the shared library early. It felt slow at first but compound returns were huge.
  • Strangler fig works. We never had a 'rewrite' moment, just steady migration.
  • Generated API clients from OpenAPI eliminated a whole class of bugs.