Back

Replacing jQuery with React: a pragmatic migration plan (with real estimates)

Captain's log, stardate d2.y42/AB

Web development Frontend Javascript React
Àlex Rodríguez Bacardit
Founder & CEO
Replacing jQuery with React: a pragmatic migration plan (with real estimates)

Legacy frontends rarely fail loudly. We have seen them time and again in big corporations, where using bleeding edge frontend frameworks and libraries is restricted, where every change requires too many approvals and committee-based decisions and convenience & compatibility are favoured over fancy looks. In fact, oftentimes they prefer something to look a bit outdated because it provides a sense of stability and trust.

This kind of frontends, they fail quietly: slower iteration, harder UI changes, more edge-case bugs, and a growing sense that every improvement costs too much. That is usually the moment this kind of big companies consider moving from legacy systems like jQuery UIs to a component-based frontend like React.

This post shares a practical, engineering-first approach to migrating a Rails + jQuery application to a modern React stack, including how we model scope, where the hidden work lives, and how to produce an estimate you can defend to both technical- and non-technical stakeholders.

But, before we start, the real question is: why migrating at all?

Big migrations are always faced with a lot of opposition, fear and friction between departments. Teams typically start this conversation for four reasons:

Step 1: quantify the jQuery surface area

Before debating frameworks, count the things that will actually change. Defining the correct scope is key to understanding how much this kind of project will cost in time and money, and who needs to do what.

A common example is API calls. In one audit of the project we're talking about, grepping for $.ajax in the frontend code revealed 197 backend calls.

That number is useful because it turns "we should modernize" into a set of mechanical tasks:

In the referenced plan, that chunk alone was estimated at ~5 days.

Why this matters: Counting calls, screens, and tables is the fastest way to avoid the classic migration trap: underestimating because you are thinking about "a rewrite", and not the dozens (or hundreds) of repeated edits.

Step 2: stop injecting server-side JS and move to real endpoints

Rails-era UIs often rely on patterns like:

React does not want that. You want predictable data contracts: JSON in, UI out.

A pragmatic migration plan identifies "common endpoints" first (shared data needed across pages), then "per-page endpoints" where the UI was previously powered by injected variables or on-the-fly generated JS.

In the plan, this endpoint work was estimated at about 5 days total (2 days common + ~3 days per-page using jQuery).

Migration tip: Do not wait until the whole UI is React to clean up data delivery. Creating stable endpoints early reduces risk and unblocks parallel work.

Step 3: choose a UI approach that matches "rewrite reality"

There is no single "React migration". There are at least three viable paths:

Option A: a new React app (Next.js) + Rails as API

This is the cleanest separation: Rails becomes the backend, Next.js becomes the frontend. It is also the most predictable in the long run because you end up with a modern front-end toolchain and clear boundaries.

Option B: incremental React "islands" inside Rails

If you want faster visible progress with less infrastructure work, mount React components on specific pages first. This reduces early risk but can leave you in a hybrid state longer.

Option C: stay in Rails but modernize (Hotwire, stimulus, componentized views)

If your main pain is not "jQuery vs React" but "UX and iteration speed", Rails-native modernization can be a better ROI. This is not what the referenced plan chooses, but it is worth considering early.

The plan we are discussing explicitly selects Next.js with Rails serving API calls, and budgets ~2 days for the baseline setup: repository, CI, staging, and core libraries (UI/CSS/state/authentication).

Step 4: standardise components before you migrate pages

Teams underestimate how much time is lost re-inventing UI primitives repeatedly during a rewrite. In fact, skipping Step 1 might cause a black hole of time and money because you haven't laid out all the possible components and group them together. It is also the perfect time to rethink workflows, forms, and stuff you can standardise and simplify to remove accumulated product debt and decisions that might've been right 10-15 years ago but don't make sense any longer. Also, try to get rid of those pages, funcionalities and components that are not used at all. You'd be surprised about how much can you chop off from legacy systems.

A better approach, still: build a reusable component set first (inputs, buttons, modals, selects, date pickers, rich text, charts). In the plan, this "generic components" phase totals 123 hours (~15 days).

This is also where design system decisions matter. If your legacy UI is Bootstrap + custom HTML, you can either:

Step 5: estimate page migration using t-shirt sizing

Page-by-page migrations are where estimates go to die. The antidote is to break pages into units, size them consistently, and accept that precision comes later. Some methodologies use estimate points based on Fibonacci, others use company-specific rankings. In this case, we went for something everyone understands: t-shirt sizes. It's a fairly simple approach that will get immediate buy-in from non-technical folks.

The plan proposes t-shirt sizing with explicit day values:

Then it applies those sizes across layouts and screens (dashboard, settings, user profile, search, etc.) to reach ~97 days for the core UI migration. If you want to be on the safe side, you might consider rounding up such numbers to add in a bit of margin.

Why this approach works:

Step 6: rewrite datatables the right way

If your current tables depend on jQuery, you typically cannot "wrap" them safely in React without dragging the old world into the new one. This part might be less relevant to most projects because datatables is pretty specific of this project, but we wanted to include it anyways. You never know who might be stuck using datatables in 2026, too!

In the plan, even a "React version" of the existing datatable library was rejected because it still uses jQuery under the hood. Instead, it proposes TanStack Table and estimates by table size:

Given counts like 3 big tables, 12 medium, 13 small, the plan landed around ~10 days for table migration. How tables are rendered across screen sizes and devices is still a challenging task in 2026, especially when using old libraries. Easier than ever? yes. Fun? not quite.

Putting it together: a full migration estimate

This is what the business stakeholders will see and ask "can you do it in half the time if we double the team size"? We still get these questions, so you might as well want to be prepared to fend them off because throughout the life of the project, you're going to be held accountable for whatever guesstimate you came up with.

The plan sums the major workstreams as:

Total: ~125 days, plus Tech Lead allocation bringing it to ~150 days. Our Tech Lead is the technical person of reference in the project, making architectural decisions, reviewing code and solving the most complex and urgent issues in the project. They usually work only a fraction of hours per full-time developer.

This estimate also explicitly notes what is not included: major UX changes or broader refactors beyond what is required for the migration, to help us focus on what's needed and avoid allowing the scope of the project to become broader every week (or every meeting).

Lessons learned (the parts teams usually miss)

How we run these migrations at MarsBased

The key to keeping a React migration sane is structure:

If you are considering a similar move, this plan is a good starting template: it makes hidden work visible and turns "rewrite anxiety" into scoped engineering tasks.

And if you need a helping hand in scoping it out, laying the project strategy or even executing it altogether, drop us a line and let us help!

Share this post

Related articles

Leak

Dealing with memory leaks in ReactiveX

One annoying thing about RxJS is its memory leaks because of Observables and Subscriptions. Here's what we do to deal with them.

Read full article
TailwindCSS and other web frontend libraries

Comparison of React libraries with Tailwind CSS: Prime React, Next UI and Flowbite

At MarsBased, we always stay at the forefront of web development technologies. This post shares a comparison of three popular libraries for working with React and Tailwind CSS: Prime React, Next UI, and Flowbite.

Read full article
React

React vulnerability (CVE-2025-66478): How we responded and what you should do

A critical React SSR vulnerability (CVE-2025-66478, CVSS 10.0) allows remote code execution. We have swiftly patched all active React/Next.js client projects. Users must apply the official fix immediately.

Read full article