Hotwire Patterns for Rails
Hotwire (HTML Over The Wire) provides a modern approach to building interactive Rails applications with minimal JavaScript. It consists of Turbo (Drive, Frames, Streams) and Stimulus.
Component Overview
| Component |
Purpose |
When to Use |
| Turbo Drive |
Full page navigation without reload |
Default — enabled automatically |
| Turbo Frames |
Independently updatable page sections |
Inline editing, tabbed content, scoped navigation |
| Turbo Streams |
Targeted DOM updates via CRUD actions |
Multi-element updates from form submissions |
| ActionCable + Streams |
Real-time server-pushed updates |
Chat, notifications, live dashboards |
| Stimulus |
Lightweight client-side behavior |
Toggles, form feedback, debounced search |
Stimulus Essentials
Stimulus controllers add client-side behavior to HTML elements using data attributes.
Naming Conventions
data-controller="search" maps to search_controller.js
data-search-target="input" accesses this.inputTarget
data-action="input->search#search" calls search() method
data-search-url-value="/api/search" accesses this.urlValue
data-search-active-class="highlighted" accesses this.activeClass
Declare targets, values, and classes as static properties. Always implement disconnect() to clean up event listeners and timers.
Turbo Frames Essentials
Turbo Frames decompose pages into independently updatable sections. Key principles:
- Use
dom_id helper for unique, meaningful frame IDs
- Provide loading state content for lazy-loaded frames
- Use
data-turbo-frame="_top" to break out of frame scope
- Wrap both show and edit views in the same frame tag for inline editing
Turbo Streams Actions
| Action |
Description |
append |
Add to end of container |
prepend |
Add to beginning of container |
replace |
Replace entire element |
update |
Update content of element |
remove |
Remove element |
before |
Insert before element |
after |
Insert after element |
morph |
Morph element (Rails 7.1+) |
refresh |
Reload page via morph (Rails 7.1+) |
Respond with format.turbo_stream in controllers. Use .turbo_stream.erb templates for complex responses, or render inline for simple cases.
Review Checklists
Stimulus
Turbo Frames
Turbo Streams
Performance
Quick Reference
| Need |
Solution |
| Navigate without reload |
Turbo Drive (default) |
| Update part of a page |
Turbo Frames |
| Multiple DOM updates |
Turbo Streams |
| Real-time server push |
ActionCable + Turbo Streams |
| Client-side behavior |
Stimulus controller |
| Form with live updates |
Turbo Frame wrapping form |
| Toast notifications |
Turbo Stream append |
| Infinite scroll |
Turbo Frame with lazy loading |
Additional Resources
Reference Files
For detailed code examples and implementation patterns, consult:
references/stimulus-patterns.md — Stimulus controller examples (search, toggle, form feedback) and conventions table
references/turbo-frames-patterns.md — Turbo Frames examples (basic frames, lazy loading, inline editing, breaking out) and Turbo Drive configuration
references/turbo-streams-patterns.md — Turbo Streams controller responses, templates, inline streams, ActionCable model broadcasting, custom broadcasting, and morphing (Rails 7.1+)
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: hotwire-patterns3description: Use when adding interactive UI to a Rails application without custom JavaScript — inline editing, live updates, real-time notifications, or partial page navigation. Also applies when choosing between Turbo Frames, Turbo Streams, and Stimulus, or reviewing Hotwire implementation for correctness.4---56# Hotwire Patterns for Rails78Hotwire (HTML Over The Wire) provides a modern approach to building interactive Rails applications with minimal JavaScript. It consists of Turbo (Drive, Frames, Streams) and Stimulus.910## Component Overview1112| Component | Purpose | When to Use |13| --------------------- | ------------------------------------- | ------------------------------------------------- |14| Turbo Drive | Full page navigation without reload | Default — enabled automatically |15| Turbo Frames | Independently updatable page sections | Inline editing, tabbed content, scoped navigation |16| Turbo Streams | Targeted DOM updates via CRUD actions | Multi-element updates from form submissions |17| ActionCable + Streams | Real-time server-pushed updates | Chat, notifications, live dashboards |18| Stimulus | Lightweight client-side behavior | Toggles, form feedback, debounced search |1920## Stimulus Essentials2122Stimulus controllers add client-side behavior to HTML elements using data attributes.2324### Naming Conventions2526- `data-controller="search"` maps to `search_controller.js`27- `data-search-target="input"` accesses `this.inputTarget`28- `data-action="input->search#search"` calls `search()` method29- `data-search-url-value="/api/search"` accesses `this.urlValue`30- `data-search-active-class="highlighted"` accesses `this.activeClass`3132Declare targets, values, and classes as static properties. Always implement `disconnect()` to clean up event listeners and timers.3334## Turbo Frames Essentials3536Turbo Frames decompose pages into independently updatable sections. Key principles:3738- Use `dom_id` helper for unique, meaningful frame IDs39- Provide loading state content for lazy-loaded frames40- Use `data-turbo-frame="_top"` to break out of frame scope41- Wrap both show and edit views in the same frame tag for inline editing4243## Turbo Streams Actions4445| Action | Description |46| --------- | ---------------------------------- |47| `append` | Add to end of container |48| `prepend` | Add to beginning of container |49| `replace` | Replace entire element |50| `update` | Update content of element |51| `remove` | Remove element |52| `before` | Insert before element |53| `after` | Insert after element |54| `morph` | Morph element (Rails 7.1+) |55| `refresh` | Reload page via morph (Rails 7.1+) |5657Respond with `format.turbo_stream` in controllers. Use `.turbo_stream.erb` templates for complex responses, or render inline for simple cases.5859## Review Checklists6061### Stimulus6263- [ ] Controllers follow naming conventions (`name_controller.js`)64- [ ] Targets, values, and classes are declared as static properties65- [ ] Actions use proper event syntax (`event->controller#method`)66- [ ] No direct DOM queries — use targets instead67- [ ] `disconnect()` cleans up event listeners and timers6869### Turbo Frames7071- [ ] Frame IDs are unique and meaningful (use `dom_id` helper)72- [ ] Loading states provide user feedback73- [ ] Frame boundaries are logical (don't wrap too much or too little)74- [ ] Non-Turbo fallback works for progressive enhancement7576### Turbo Streams7778- [ ] Stream actions match the intended DOM update79- [ ] Target elements exist in the DOM before streaming80- [ ] Partials render correctly in isolation81- [ ] Broadcasting scope is appropriate (don't over-broadcast)8283### Performance8485- [ ] No unnecessary full-page reloads (Turbo Drive not disabled broadly)86- [ ] DOM updates are targeted (prefer replace over full refresh)87- [ ] Caching still works with frames and streams88- [ ] JavaScript bundle size is reasonable8990## Quick Reference9192| Need | Solution |93| ----------------------- | ----------------------------- |94| Navigate without reload | Turbo Drive (default) |95| Update part of a page | Turbo Frames |96| Multiple DOM updates | Turbo Streams |97| Real-time server push | ActionCable + Turbo Streams |98| Client-side behavior | Stimulus controller |99| Form with live updates | Turbo Frame wrapping form |100| Toast notifications | Turbo Stream append |101| Infinite scroll | Turbo Frame with lazy loading |102103## Additional Resources104105### Reference Files106107For detailed code examples and implementation patterns, consult:108109- **`references/stimulus-patterns.md`** — Stimulus controller examples (search, toggle, form feedback) and conventions table110- **`references/turbo-frames-patterns.md`** — Turbo Frames examples (basic frames, lazy loading, inline editing, breaking out) and Turbo Drive configuration111- **`references/turbo-streams-patterns.md`** — Turbo Streams controller responses, templates, inline streams, ActionCable model broadcasting, custom broadcasting, and morphing (Rails 7.1+)112113---114> Converted and distributed by [TomeVault](https://tomevault.io/claim/chaserx) — claim your Tome and manage your conversions.115<!-- tomevault:4.0:skill_md:2026-04-15 -->