I recently migrated one of my personal Rails projects from Hotwire to Vite and React (via Inertia.js).
Hotwire is great for pure Rails applications, but for this particular project, UI iteration and AI tooling led me to switch. Here is why I made the change and what the trade-offs look like in practice.
Why I Switched
1. Ready-Made Component Libraries (shadcn/ui)
I’m not strong at writing CSS from scratch. In the Rails ecosystem, building polished, accessible UI components (dialogs, dropdowns, combo-boxes) usually means either writing custom Stimulus controllers and CSS or using gems like ViewComponent / Phlex.
In React, shadcn/ui gives you beautifully designed, accessible components built on Radix UI and Tailwind CSS. You copy what you need into your project, and the styling just works. For solo development where design time is limited, this saves hours of tinkering with CSS.
2. Live AI Previews in Chat
Modern AI assistants (ChatGPT, Claude) excel at generating and updating React components with instant interactive previews.
With Hotwire and ERB, my iteration loop was:
- Ask AI to write ERB + Stimulus
- Copy into the Rails project
- Refresh the browser and test
- Repeat
With React and shadcn/ui:
- Describe the component in chat
- See the rendered component directly inside the AI interface
- Iterate and refine in real-time
- Copy the final component into the codebase
This tighter feedback loop makes frontend prototyping noticeably faster.
3. Snappy DX with Vite
Using Vite with vite-plugin-ruby provides instant server starts and sub-millisecond Hot Module Replacement (HMR). Changes to React components reflect immediately in the browser without full-page reloads, which feels much snappier during active frontend development.
Why Inertia.js Made the Transition Easy
Instead of building a separate GraphQL or REST API backend, I used Inertia.js Rails.
Inertia acts as a glue layer: you keep your Rails routes and controllers as usual, and return render inertia: "Users/Index", props: { users: @users } instead of rendering ERB templates. This allowed me to migrate pages incrementally without rebuilding the application architecture from scratch.
The Real Trade-offs
The switch wasn’t without downsides:
- Deployment overhead: Moving away from
importmapsmeans introducing Node.js and a build step into Docker images and CI/CD pipelines. - Mental context switching: You have to bridge state management between Ruby backend objects and React frontend components.
- More moving parts: Between Vite, React, Tailwind, and Inertia, there are simply more dependencies to keep updated.
Summary
Rails + Inertia + React + shadcn/ui solved my biggest personal bottleneck: creating clean, accessible UIs quickly without spending days wrestling with custom CSS. If you’re already great at CSS or happy with vanilla Hotwire, the extra build complexity might not be worth it. But for fast prototyping with rich UI components, the combination works surprisingly well.