Hotwire consists of Turbo, a library that manages user navigation and communication with the server without needing custom JavaScript, and Stimulus, which supports client-side interactions written in JavaScript. Stimulus is designed to be written as an extension to the HTML markup you are already writing and is well suited to small interactions that don’t need to manage a lot of state, or where the majority of the state is managed by the server application. A third tool, Strada, which manages interactions with native mobile devices, has not yet been released as I write this.

Excerpt From Modern Front-End Development for Rails, Second Edition

Working with JavaScript in Rails

  • Hotwire: a framework that allows you to keep most of your logic on the server and communicate with the client by sending HTML
  • Turbo: a library that allows you to do complex client-server interactions without writing custom JavaScript
    • Turbo Drive: speed up basic links through your site (successor to Turbolinks). Click a link to the same domain, and it replaces the body instead of reloading the page from scratch, improving performance
    • Turbo Frames: replace part of your page with new HTML from the server. Server navigations automatically handled via fetch(), and replace the frame portion of the page. Can also do lazy loading
    • Turbo Streams: do arbitrary DOM replacement without any custom JS, either in response to a form submission or over WebSockets from server events
    • turbo-rails: Ruby gem for Rails integration
  • Stimulus: JS library that manages client-side interactions more directly
  • Import Maps for Rails: allows browser to import separate JS modules individually; allows skipping bundling
  • JavaScript Bundling for Rails: allows you to use the JS bundling tool of your choice
    • esbuild: an extremely fast JS bundler
  • CSS Bundling for Rails: allows you to use one of a few CSS processing tools
  • Propshaft: takes output of bundling tools and delivers to browser (simpler replacement for Sprockets)


respond_to do |format|
  format.turbo_stream do
    render turbo_stream: turbo_stream.replace(
      partial: "path/to/partial",
      locals: {key: value}
  format.html {...}
  format.json {...}



<%= turbo_stream.replace 'notice' do %>
  <%= render partial: 'store/notice', locals: {notice: @notice} %>
<% end %>

<%= turbo_stream.replace 'cart' do %>
  <%= render partial: 'layouts/cart', locals: {cart: @cart} %>
<% end %>

Action Cable

(hard to summarize)