Rails and the Frontend: Hotwire
Many modern sites are two programs: a backend that sends JSON and a JavaScript app that builds the page. Rails can work that way, but its default is simpler. The server sends ready-made HTML, and a set of tools called Hotwire makes those pages feel as quick as a single-page app.
The rule
Send HTML over the wire; add JavaScript only where HTML cannot reach.
Hotwire is included in every new Rails app. It has two main parts:
- Turbo — speeds up server-rendered HTML.
- Turbo Drive: intercepts link clicks and form submissions, fetches the new page in the background and swaps the
<body>. No full reload, no code from you. - Turbo Frames: wrap part of a page in
<turbo-frame id="...">so a link or form inside it replaces only that part. - Turbo Streams: the server sends small instructions such as
append,replaceorremovewith a piece of HTML, over a normal response or a WebSocket.
- Turbo Drive: intercepts link clicks and form submissions, fetches the new page in the background and swaps the
- Stimulus — small JavaScript controllers attached to existing HTML with
data-controllerattributes, for behaviour that needs no server, like toggling or copying.
<turbo-frame id="reviews">
<%= render @book.reviews %>
</turbo-frame><div data-controller="expand">
<button data-action="expand#toggle">Show more</button>
</div>If you need a separate React or mobile client instead, rails new bookclub --api builds a JSON-only backend with no views.
The shortcut
Climb a ladder and stop at the first rung that works: plain page (Drive) → part of a page (Frame) → pushed changes (Stream) → client-only behaviour (Stimulus).
Default navigation
Turbo Drive already makes the book page load without a full refresh. Nothing to write.
The trap is reaching for a big JavaScript framework for something Turbo already does. Start with HTML and add only what is missing.
Drills
Answer fast — trust the rule.
Which part of Hotwire makes ordinary link clicks load pages without a full browser reload?
A dropdown menu opens and closes with no server involvement. What fits best?
What does the server send back in a Hotwire app when a review is added?
Which command creates a backend meant for a separate React client?
Remember
- Send HTML over the wire; add JavaScript only where HTML cannot reach.
- Ladder: Drive, then Frame, then Stream, then Stimulus.
- Trap: pulling in a JavaScript framework for what Turbo does by default.
