turbo

System test: asserting Turbo Stream responses

I don’t test Hotwire behavior by guessing; I add system tests that exercise the UI. With Capybara, I click a button that triggers a Turbo Stream response and assert that the DOM changes without a full page reload. The exact assertion depends on the fe

Turbo Frames: infinite scroll with lazy-loading frame

Infinite scroll can be done with plain HTML + Turbo Frames. Render a “next page” frame with loading: :lazy so Turbo fetches it when it enters the viewport. No JS required, and it degrades gracefully.

Filter UI that syncs query params via Stimulus (no front-end router)

Filters are better when the URL reflects state. I use a small Stimulus controller that updates the query string as filters change, then triggers a Turbo visit (often with data-turbo-action='replace'). This gives shareable URLs and correct back-button

Remove deleted items instantly with turbo_stream.remove

Destructive actions should feel immediate. For delete links inside a list, I return a Turbo Stream that does turbo_stream.remove dom_id(record). That removes the DOM node without re-rendering the rest of the list, which avoids the common “jump” effect

Debounced live search with Stimulus + Turbo Streams

For search-as-you-type, I keep the server in charge and use a small Stimulus controller to debounce form submission. The controller listens to input events, waits ~250ms, then triggers a normal Turbo form submit. The server responds with index.turbo_s

Presence indicator with ActionCable + Turbo Streams

Presence is usually overkill, but for collaboration features it’s valuable: show who’s online in a room. I identify connections with current_member in ApplicationCable::Connection, then in a channel I broadcast updates when members subscribe/unsubscri

Disable submit button while Turbo form is submitting

Double-submits are easy to trigger on slow connections, especially with Turbo where the page doesn’t visibly reload. I add a Stimulus controller that listens to turbo:submit-start and turbo:submit-end events on the form. On submit start, disable the s

Turbo confirmation dialogs with custom modal

The default browser confirm() dialog is ugly and doesn't match your design system. Turbo provides hooks to intercept confirmation dialogs and show custom modals instead. I listen for the turbo:before-fetch-request event, check if the element has data-

Live comments with model broadcasts + turbo_stream_from

If a feature is fundamentally “live” (comments, activity), I reach for model broadcasts. Rails can broadcast Turbo Stream fragments on after_create_commit, and the UI subscribes with turbo_stream_from. The beauty is that it’s still server-rendered HTM

Turbo Streams + authorization: signed per-user stream name

Never subscribe clients to guessable user-specific streams. Use signed_stream_name so a user can only subscribe to their own broadcasts. This is essential when streaming private notifications.

Frame navigation that targets a specific frame via form_with

Sometimes a form submission should update a specific section rather than navigate the whole page. With Turbo, this is as easy as setting data-turbo-frame on the form. For example, a filter form can target a results frame, so submissions replace only t

Speed up perceived performance with Turbo preload links

Turbo can preload pages on hover (or on touchstart) which makes navigation feel instantaneous. I use data-turbo-preload on links that are likely to be clicked (like list item titles). The server still controls caching and ETags, so it remains safe and