Lesson 1 — The Hotwire mental model
A brief history
When Hotwire launched with Rails 7, the recommended approach to
interactivity was Turbo Frames and Turbo Streams. Frames let you scope
updates to a region of the page. Streams let you send targeted DOM
operations from the server. Together they covered most interactive UI
needs — but they required explicit wiring: matching frame IDs, separate
format.turbo_stream blocks, and careful coordination between
templates.
In practice this was more work than it looked. Building a calendar in HEY, the Basecamp team hit the ceiling — too many frames, too many stream actions, an explosion of partial updates to coordinate. They looked for a better approach and found it in DOM morphing.
Turbo 8, released in early 2024, introduced page refresh with
morphing. The idea is simple: after a form submission or action, the
server re-renders the full page and redirects back. Instead of replacing
the entire <body> as Turbo Drive did, Turbo 8 diffs the new HTML
against the current DOM using the idiomorph library and applies only the
changes — morphing in place, preserving scroll position and ephemeral
state.
The result is that the default Rails programming model — render a full page, redirect after POST — now produces a genuinely smooth UI without any explicit Turbo wiring.
The honest tool hierarchy
Turbo Drive — always active. Intercepts link clicks and form submissions, prevents full page reloads. You’ve been using this since Module 4 without thinking about it.
Turbo Morph — opt-in upgrade to Drive. Instead of replacing the
<body>, it diffs and patches. Two meta tags to enable. Controllers
stay simple — just redirect as normal.
Turbo Frames — scope a navigation or form submission to a region of the page. Still useful for one specific case: lazy-loading content that shouldn’t block the initial render.
Turbo Streams — targeted DOM surgery from the server. Still useful for two specific cases: re-rendering a form with validation errors in-place (no redirect), and broadcasting real-time updates to other users via ActionCable.
The decision rule
Start with Morph. It handles the vast majority of interactions — creating, updating, and deleting records — with no wiring beyond a redirect. Reach for Frames or Streams only when you hit a specific limitation morphing can’t address.
Throughout this module we’ll follow this rule in the order we hit each limitation. Morph first. Streams for validation errors. Frames for lazy loading. Streams again for real-time broadcasting.