How We Migrated 183 Screens from AngularJS to React with AI Loops
· 6 min read
Contents
We moved 183 workflow screens in a large enterprise front end from an old version of AngularJS to React. Feature development didn’t stop, users didn’t notice, and human QA for all 183 screens took seven days.
We used AI loops heavily. But the thing that made it work wasn’t the AI. It was how we broke the problem down: one screen at a time, each one checked against tests written for the old screen.
The obvious approach doesn’t work
The obvious approach is to point an AI agent at the old codebase and ask for a React version.
That works until you check it. Every time we tried, the AI missed a feature somewhere, or hallucinated one that never existed.
So a full rewrite was out. What we needed was a way to move one small piece at a time, and know for certain that each piece was right.
Users shouldn’t notice anything
The second constraint was the user experience. We didn’t want to change it at all. Same components, same positions, same behaviour. The React version of a screen is a translation, not a redesign.
That raises a practical question. What does a user see while half the app is React and half is still AngularJS?
Our answer was a React shell. The shell owns navigation, login and layout. A migrated screen renders in React inside it. A screen that isn’t migrated yet loads the old app in an iframe.
The tricky part is making the two look identical. So the old app got an embedded mode. In embedded mode it hides its own navigation and uses the same design tokens as the new app: the same font, the same padding, the same buttons.
From the user’s side, there’s no seam. When a screen is migrated, the shell swaps the iframe for the React version, and nothing visibly changes.
First, understand the old app
Before migrating anything, we needed to know what the old app actually does. Not what we think it does.
So we wrote seven AI skills just for reconnaissance, and ran them in loops over every tab and every piece of functionality. For each one, they documented the workflows, the APIs it calls and the edge cases.
That documentation is what the migration works from. An agent moving a screen to React starts from a written description of the screen, not from its own guess about old code.
One loop per screen
Then the migration itself: one screen at a time, starting with the lowest-hanging fruit.
For each screen, a loop documents it, writes tests against the old version, migrates it, and runs the same tests on the new version. If a test fails, it fixes the code and runs them again. It only moves on when everything passes. Then a human checks it, and the shell starts serving the React version.
We leaned heavily on loop engineering1 By loop engineering we mean designing the loop an AI agent runs in: what it picks up next, how its output is checked, when it retries and when a person steps in. for all of this.
Tests are the real specification
The tests are what make this work.
A test written against the old screen is an exact, executable description of what that screen does. Recreate the same test for the new screen, and “is the migration correct?” becomes a yes-or-no question.
We used two kinds. API tests run against the real sandbox APIs, so they check what a screen actually sends and receives, not what the AI assumes it should. End-to-end UI tests click through the screen in a browser, the way a user would.
Remember the features the AI kept missing? This is where they show up. A forgotten feature is now a failing test, not something a customer finds.
Humans still check, just less
Tests catch a lot. Not everything. So every migrated screen also got a human check before it was merged.
For that we used burstable verify boxes: short-lived preview environments, spun up for one branch and torn down after. A reviewer opens the migrated screen against the sandbox and clicks through it.
Human QA for 183 workflow screens took seven days. That’s only possible because by the time a person saw a screen, it had already passed the same tests as the old one.
What about new features?
Product work didn’t pause. In the interim, features were built in both apps.
That’s extra work. But it meant the product kept moving while the migration caught up.
The numbers
183 workflow screens. Seven days of human QA. Six million new lines of code, app and tests. Seven AI skills written just for recon.
What we learned
Ask AI to rewrite a large app, and you get something that looks finished and quietly isn’t.
The fix isn’t a better prompt. It’s making each piece of work small enough to check, and making the check impossible to argue with. Tests written against the old system do exactly that. They replace “trust the AI” with “the new screen passes the same tests as the old one”.
The AI does the work. The loop decides when the work is done.