Legacy Platform Rewrite
Shipped on deadline · 18-month MVP
- Client
- A US-based media and publishing group
- Engagement
- Engineering Lead, Frontend Architecture, Technical Advisory
- Stack
- Next.js, React 19, TypeScript, Kendo React, CKEditor 5, Node.js, NX Monorepo, Vite, Vitest
The Project
The client’s legacy internal marketing platform was a fifteen-year-old PHP + jQuery application that had grown over time as the company moved toward a centralized tool rather than a mix of Excel, email, and ad-hoc solutions.
Part of the codebase had been rewritten in React over the years, but the work was never completed. As the codebase grew, complexity and risk grew with it. After a point, making any change was so difficult and risky that the client decided on a full rewrite, with one hard constraint: hit an 18-month deadline to deliver the MVP.
The Mandate and the Trade-offs
The client was explicit about the deadline and asked the engineering team to trade off some code quality to hit it.
That is a risky request. Followed blindly, it would have led straight back to the same situation: another complete rewrite in a few years. My job was to design the frontend architecture and choose the right trade-offs to gain development speed without sacrificing the quality and maintainability of the codebase.
Adding to the complexity: the client required the UI to look and behave exactly like the legacy application. That was a real challenge, given that many of its UI patterns had been built ad-hoc over many years and were not available in Kendo React or any other library on the market.
We split the project into two phases:
- Phase 1: MVP development, 18-month deadline
- Phase 2: non-MVP features and tech debt payoff
Phase 1 - MVP
What I let slide
- Thin unit-test coverage on non-critical components (e2e was owned by another team, so we could rely on their work)
- Duplication inside feature modules where extracting an abstraction would have cost more than it saved at that stage
- “Good enough to ship” code for individual features
- Loose guards around React usage, with some useEffect misuse and other anti-patterns making it through
What I did not let slide
- Module boundaries and the integrity of the shared component layer
- Heavy testing of critical shared components
- Abstraction layers in the right places, knowing they would save significant time once in place
- A solid approach to Kendo React customization: leveraging their component APIs rather than touching internals, which would have made future library updates much harder
Scale
- 200 internal users across multiple roles with different personas and workflows
- ~20 screens managing ~20 domain entities; heavy, information-dense CRUD
- Deep customization of the KendoReact DataGrid component
- A form scaffolding tool built on configuration objects, covering:
- Standard and custom input types
- Validation rules
- Default values
- Callbacks
- Field dependencies driving visibility and available values
- A significant WYSIWYG editor evaluation, conducted under a near-total absence of requirements, with real constraints surfacing only as we built
Leading the Delivery
I led a team of six. A second team of six, more backend-focused, worked the same project in parallel.
The other team lead and I worked in close partnership with the Product Owner on:
- Estimation and timeframe management against the fixed date
- Feature sequencing across two teams to avoid overlap and conflict
- Acting as the technical point of contact for the PO and stakeholders, translating between business intent and technical reality
With production deployments at two to three per week, we hit the deadline right on target.
The Monorepo Bet
A major architectural decision early in the project was building a monorepo with NX. The reasoning: the company would eventually need similar applications, so a consistent stack and set of shared libraries would make future development and maintenance significantly easier. New applications could build on already-developed, production-tested components rather than starting from scratch.
This paid off within the year. A second project, heavily reliant on forms and data grids, launched on a timeline significantly shorter than any greenfield build would have allowed.
Phase 2 - Tech Debt Payoff
Phase 2 delivered the features cut from MVP scope and began retiring the debt.
- I introduced stricter engineering guardrails targeting the React anti-patterns Phase 1 had let through.
- I brought unit testing back up to where it should have been.
- I wrote a one-year incremental debt-repayment plan, structured to run with minimal risk and without stalling feature delivery, the constraint that kills most efforts like this.
- The plan covered both application teams, since both now depended on the shared layer.
- I allocated work against individual aptitude and disposition. Some engineers thrive on methodical remediation; others need a creative problem to solve. Matching work to the person is what kept the team engaged, and that has a direct impact on productivity.
Outcome
- A business-critical platform rewritten and delivered on a fixed 18-month deadline
- From a single engineer, maintenance hell, and a legacy codebase to a system any engineer can onboard into and be productive in immediately
- A shared component foundation that cut the cost of the client’s next internal application
- Deliberate debt priced, documented, and scheduled, rather than inherited by whoever came next