How to Migrate a jQuery Frontend With AI
Migrating a jQuery frontend to a modern framework with AI is doable if you go component by component. Here is the safe path from spaghetti to a real app.
Migrating a jQuery frontend to a modern framework is one of the most common legacy jobs there is, and AI makes it faster than it has ever been, if you resist the urge to do it all at once. jQuery frontends are usually a decade of DOM manipulation, global state living in the page, and event handlers wired to selectors nobody dares touch. You cannot big-bang rewrite that safely. The path that works is to migrate one component at a time, behind a boundary, with the old and new code running side by side until the old is gone.
Why the big-bang rewrite fails
The instinct is to rewrite the whole thing in React or Vue in one heroic sprint. It fails every time, and AI does not change that. The problem is not writing the new code. The model can produce the new components fast. The problem is that a jQuery app has a thousand undocumented behaviors, and you cannot verify a full rewrite against them all at once. You ship, something breaks, and you have no idea which of the thousand changes caused it.
The proven approach is the strangler pattern for legacy code: wrap the old system, replace it piece by piece, and let the new grow inside the old until the old can be deleted. jQuery-to-modern is close to the textbook case for it.
Migrate one component at a time behind a boundary
Pick the smallest, most self-contained piece of UI. A form, a widget, a single panel. Draw a boundary around it: a div the modern framework mounts into, while jQuery keeps running everywhere else. The two coexist on the same page. Users see no difference.
Then work the loop:
- Have the model read the jQuery code for that component and describe every behavior it can find, including the ugly ones.
- Turn that description into a spec, because writing the spec before the prompt is what keeps the new component faithful to the old.
- Build the modern component to that spec, mounted behind the boundary.
- Verify behavior matches, including the edge cases the model surfaced.
- Delete the jQuery for that piece. One component down.
Each step is small enough to review and reversible if it goes wrong. That is the whole point.
Where the model needs a leash
jQuery migrations have specific traps the model will walk into:
Global state. jQuery apps stash state on the DOM and in globals. The model will happily rebuild a component that reads a global your new framework does not know about, and it will look fine until that global changes elsewhere. Map the shared state before you migrate, not after.
Implicit event ordering. A lot of jQuery works by accident of load order. The model cannot see that from one file. When behavior depends on "this runs before that," write it into the spec explicitly.
Selectors as an API. Other code may reach into this component by selector. Migrate the internals and you can silently break those external hooks. This is why characterization tests before the refactor matter: they catch the behavior you did not know something depended on.
Verify each step, do not trust the diff
The model's diff will look clean. Clean is not the bar. The bar is behavior unchanged. After each component, run it against the old behavior, click through the real flows, and check that nothing elsewhere on the page broke. Then review the generated PR for the subtle stuff that compiles but drifts. Small steps make this manageable, which is the whole reason to refactor with AI in small steps instead of one giant leap.
This component-by-component migration is exactly the kind of bounded legacy work I run through Bootspring: the model reads the old code, produces a spec, builds behind a boundary, and every step is gated before it merges.
The takeaway
Do not rewrite a jQuery frontend in one shot. Migrate it one component at a time, behind a boundary, with old and new running side by side. Let AI read the old code and draft the new, but write the behaviors into a spec, leash it on global state and event ordering, and verify each piece against the real thing before you delete the jQuery. Slow and boundaried beats fast and broken.