Skip to content

Track example migrations from existing Rails + React apps #3125

@justin808

Description

@justin808

React on Rails Migration Examples: Meta Tracking Issue

This issue tracks open-source Rails applications that are strong candidates for incremental migration to react_on_rails, along with the public PRs, blockers, benchmark notes, and follow-up work.

Public docs should only carry durable example references. This issue is the better home for in-progress third-party PRs, maintainer-contact notes, and other working material that may change quickly.

The goal is not to rewrite large apps wholesale. The goal is to prove a repeatable migration path from existing Rails-plus-React stacks such as react-rails, webpacker, shakapacker, vite_rails, and custom Rails React bridges.

Why This Matters

Teams evaluating react_on_rails want proof from real applications, not only toy examples.

The most credible evidence is:

  1. Real open-source Rails repos
  2. Narrow migration PRs
  3. Reproducible before-and-after notes
  4. Performance or maintainability evidence for each migrated slice

Selection Policy

  1. Prefer very popular or institutionally credible Rails applications.
  2. Favor apps already using React with Rails in some form.
  3. Keep the first PR small enough to review quickly.
  4. Avoid obscure dependencies or novelty migrations that do not help the main adoption story.
  5. Treat Inertia-first apps as stretch targets unless the point is to document architecture differences.

First-Wave Status

Repo Stars Current Integration Status PR Evidence so far Missing proof
EFForg/action-center-platform 517 react-rails PR ready for review #975 Contributor-local benchmark note captured: warm request time and total JS weight both decreased for the slice; local maintainability note is captured for the new explicit Rails prop boundary and the narrowed page-scoped React on Rails entrypoint; local webpack compilation passes, the repo Docker build now passes with the Node 20 + Yarn-aligned container fix, and compose-backed db:test:prepare plus the focused request/helper specs pass Optional browser-level proof if a maintainer asks for stronger route evidence; otherwise the next step is maintainer review
thewca/worldcubeassociation.org 383 react-rails PR ready for review #14010 Local maintainability note captured for the legacy disclaimer page; lint, RuboCop, webpack compile, repo bootstrap via docker compose up --build wca_environment, and the compose-backed disclaimer request spec now pass after the branch restores legacy react_component(...) calls through a coexistence override Optional CI confirmation or one more low-risk legacy Rails slice if maintainers want broader proof; otherwise the next step is maintainer review
demarche-numerique/demarche.numerique.gouv.fr 259 vite_rails + custom React bridge Closed after maintainer feedback #12954 Focused component spec passed; local maintainability note captured for replacing a custom coldwired/react mount contract with a maintained helper contract External blocker: maintainer said the repo depends on coldwired updating React components during DOM morphs, so this migration slice is not a fit for their architecture
GSA/search-gov 68 react-rails + Shakapacker PR ready for review #2010 CircleCI green for checkout code, jest, rspec, and cucumber; local maintainability note captured for splitting low-coupling SERP chrome into smaller mounts; PR rationale already explains the maintainability-first value of shrinking the shell boundary without rewriting the results body Optional public-friendly benchmark note if stronger marketing proof is needed; otherwise the next step is maintainer review
hackclub/hcb 845 react-rails PR ready for review #13489 Repo Dockerfile builds successfully, compose-backed db:test:prepare plus the focused bookkeeping controller spec now pass, containerized yarn build, yarn build:css, and focused RuboCop revalidation all pass once the app uses an explicit React-on-Rails alias plus a legacy-helper coexistence override; local maintainability note is now captured for that coexistence path; asset-level comparison shows bundle.js moved from 2,739,714 to 2,754,760 bytes while yarn build improved from 10,035 ms to 9,101 ms Optional browser-level pass if stronger public performance proof is needed; otherwise the next step is maintainer review
broadinstitute/single_cell_portal_core 70 vite_rails + custom window.SCP.renderComponent bridge Draft PR open #2381 Local helper-test, focused Jest, and vite build --force --clear all pass for the studies#usage_stats slice; asset-level comparison shows application-*.js moved from 2,083,391 to 2,099,314 bytes while full rebuild time moved from 22,947 ms to 23,486 ms Controller/request-level HTML proof once Mongo-backed test auth is available

Second-Wave Targets

These matter, but they are weaker first proof points than the current wave.

Repo Stars Current Integration Current status
thecartercenter/nemo 65 react-rails + shakapacker PR ready for review: #1110. Fresh local db:setup, compile, react_on_rails:doctor, request spec, system spec, RuboCop, and focused JS lint all pass; shared global components chunk dropped from 305,252 to 293,091 bytes
Codeminer42/cm42-central 324 vite_rails + React Draft PR open: #1029. Local Docker/Linux validation passes: db:setup, focused controller spec, focused JS specs, ESLint, and vite build all succeed; the built application-*.js bundle moved from 2,193,537 to 2,209,328 bytes
broadinstitute/single_cell_portal_core 70 vite_rails + custom window.SCP.renderComponent bridge Draft PR open: #2381. Local helper-test, focused Jest, and vite build --force --clear pass; the built application-*.js bundle moved from 2,083,391 to 2,099,314 bytes
indentlabs/notebook 398 react-rails + Webpacker (ReactRailsUJS auto-mount) Compile still passes locally, but a real landing-page request now fails because the migrated helper expects config/shakapacker.yml; the branch is therefore blocked on whether to add real Shakapacker config or stage a broader migration first
saeloun/miru-web 256 vite_rails + SPA root Local Ruby and package installs pass, but the router still falls through home#index into one global Vite entrypoint that mounts a single #react-root, so this is an app-shell case study rather than an incremental island migration
codeforpdx/dwellingly-app 49 react-rails with SPA routing Local work is blocked by the pinned Ruby 3.0.1 not building on this macOS arm64 host
rubyforgood/demand-progress 56 Webpacker + ad hoc React mount Local work is blocked by the locked Ruby 2.5.1 not building on this macOS arm64 host

Stretch and Blocked Targets

Repo Status Reason
antiwork/gumroad Stretch target Important repo, but it is Inertia-first and is not the cleanest first proof point
exercism/website Process-blocked Useful technically, but the repo documents that outside PRs are not accepted

Whale Targets

These are the high-value proof points that should come after the first wave is clearly credible.

Repo Stars Current Integration Notes
mastodon/mastodon 49,825 vite_rails + React Probably the most visible Rails + React migration story if a narrow slice can be found
gitlabhq/gitlabhq 24,295 vite_rails + React Worth documenting, but too broad for the first implementation wave

Institutional Middle Tier

These are not whales, but they are still strong proof points once the first wave is done.

Repo Stars Current Integration Why it matters Recommendation
thecartercenter/nemo 65 react-rails + shakapacker Institutionally credible and still close to the classic migration story Keep using ready PR #1110 as the second-wave institutional proof point; the first slice is maintainability-first, but it already shows an honest shared-bundle reduction and a clean coexistence path
Codeminer42/cm42-central 324 vite_rails + React Strong star count and real page-scoped mounts instead of a catch-all SPA shell Move this up with nemo; draft PR #1029 is now open for the validated projects.index slice
broadinstitute/single_cell_portal_core 70 vite_rails + custom window.SCP.renderComponent bridge Broad Institute credibility plus a repo-owned Rails-to-React mount contract makes it a meaningful non-demo proof point Promote alongside cm42-central; draft PR #2381 is open for the validated studies#usage_stats slice, and the remaining gap is Mongo-backed controller/request proof
digitalepidemiologylab/crowdbreaks 12 Webpacker + webpacker-react Research-institution ownership gives it some signal, but it is the weakest of this tier De-prioritize behind the other institutional targets

Reference Repos Already On React on Rails

These are useful references. Some are also legitimate upgrade-PR candidates.

Repo Current stack snapshot Upgrade fit Recommendation
ifmeorg/ifme react_on_rails 12.0.1, webpacker 5.4.4, React 17 Strong Fork branch justin808/ifme:codex/upgrade-react-on-rails-16 is pushed and locally revalidated; upstream PR is blocked only by the project's Slack-first contribution process
houdiniproject/houdini gem react_on_rails 12.6.0, JS package 12.2.0, webpacker 5.4.4, React 17 Strong Still worth an upgrade PR, but current local work is blocked before app code because Ruby 3.0.7 is brittle on this macOS arm64 host and the patched local install was not healthy enough to run Bundler
avalonmediasystem/avalon react_on_rails 14.2.1, shakapacker 8.3.0, React 19 Good Queue after ifme and houdini, but first fix the missing pinned active-fedora git revision in the baseline app
sharetribe/sharetribe react_on_rails 13.0.2, React 16 Weak Do not prioritize; the repo says it is no longer actively maintained
hostolab/covidliste react_on_rails 12.2.0, webpacker 5.3.0, React 17, Node 12 Weak Do not prioritize; activity looks too stale for unsolicited upgrade work

Known Cross-Cutting Blockers

  1. Existing Rails apps use materially different integration stacks, so this is not a single codemod problem.
  2. Some repos have heavy local setup or native dependency chains that block fast validation, so benchmark and request-proof notes need a pinned Docker or service-backed environment instead of a half-working host install.
  3. Large repos often require very narrow PR scope to be reviewable upstream.
  4. Performance or maintainability evidence needs a shared method or the results will not be credible.

Related Issues and PRs

  • Docs PR: #3126
  • Proof-artifacts issue: #3127
  • Legacy Webpacker compatibility follow-up: #3136
  • React 16/17 react-dom/client warning follow-up: #3137
  • Docs follow-up for legacy migration guidance: #3138
  • Helper-name collision follow-up: #3143
  • Vite package-manager check follow-up: #3145
  • Draft follow-up needed: react_on_rails:doctor and Shakapacker upgrade guidance for repos that keep package.json and node_modules under client/
  • Related but different scope: #1985 for RSC migration success stories
  • Framework-level benchmarking issue: #2169
  • Benchmark workflow issue: #2546

What Is Still Missing

  1. A public-friendly publication path for the local proof notes
  2. A public benchmark note for at least one more repo beyond ACP. nemo now has a local asset-comparison note, but it still needs a browser-level pass before it becomes the next stronger public benchmark
  3. A decision on whether Gumroad stays in the migration queue or becomes an Inertia case study
  4. A later whale-target scouting pass once the first wave lands
  5. A decision on which institutional middle-tier repo should become the next serious target after the current wave once nemo maintainer feedback lands
  6. A reusable benchmark environment for side-by-side demos and videos that includes the service dependencies some apps need for request-level proof
  7. A product/docs answer for supported upgrades where JS dependencies intentionally live under client/ rather than the Rails root

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions