Comprehensive guide for building interactive Rails applications with Hotwire (Turbo + Stimulus), maintained by Community. Contains 53 rules across 9 categories, prioritized by impact to guide automated refactoring and code generation. Follows the DHH "One Person Framework" philosophy: the server renders HTML, Turbo makes it feel like an SPA, Stimulus adds the sprinkle of JS where needed.
When to Apply
Reference these guidelines when:
Configuring Turbo Drive navigation, prefetching, and caching behavior
Adding Turbo Frames for partial page updates and lazy loading
Delivering Turbo Streams for surgical DOM mutations
Broadcasting real-time updates over ActionCable
Enabling Turbo 8 morphing for page refreshes
Writing Stimulus controllers for client-side behavior
Handling errors in Turbo navigation, frames, and WebSocket connections
Choosing between Drive, Frames, Streams, Morphing, and Stimulus
Testing Hotwire interactions in system and integration tests
Rule Categories by Priority
Priority
Category
Impact
Prefix
1
Navigation & Drive
CRITICAL
drive-
2
Turbo Frames
CRITICAL
frame-
3
Turbo Streams
HIGH
stream-
4
Broadcasting & Real-Time
HIGH
bcast-
5
Morphing & Page Refresh
HIGH
morph-
6
Performance Optimization
MEDIUM-HIGH
perf-
7
Stimulus Patterns
MEDIUM-HIGH
stim-
8
Architecture Decisions
MEDIUM
arch-
9
Testing Hotwire
MEDIUM
test-
Quick Reference
1. Navigation & Drive (CRITICAL)
drive-prefetch-links - Enable link prefetching for instant navigation
drive-form-submissions - Use Turbo Drive for form submissions
drive-visit-actions - Control history with visit actions
drive-cache-control - Configure Turbo cache for preview pages
drive-selective-disable - Disable Turbo Drive on incompatible pages
drive-progress-bar - Customize the Turbo progress bar
drive-confirm-dialog - Use data-turbo-confirm for destructive actions
drive-error-recovery - Handle Turbo navigation and fetch errors gracefully
2. Turbo Frames (CRITICAL)
frame-lazy-loading - Defer frame loading until viewport entry
frame-scope-navigation - Scope navigation within frames
frame-src-navigation - Use src for dynamic frame content
frame-break-out - Handle frame breakout for redirects
frame-promote-visits - Promote frame navigation to page visits
frame-dom-id - Use dom_id for frame identification
frame-empty-state - Provide meaningful frame loading states
3. Turbo Streams (HIGH)
stream-progressive-enhance - Always provide HTML fallback for streams
stream-action-selection - Choose the right stream action for DOM mutations
stream-multi-target - Use targets for multi-element updates
stream-http-delivery - Deliver streams via HTTP for form responses
stream-websocket-source - Connect WebSocket sources in the body
stream-custom-actions - Register custom stream actions for complex DOM updates
4. Broadcasting & Real-Time (HIGH)
bcast-model-broadcasts - Use broadcasts_refreshes for simple model updates
bcast-debounce-n1 - Debounce broadcasts to prevent N+1 broadcast storms
bcast-scope-streams - Scope broadcast streams to accounts or users
bcast-refresh-over-replace - Prefer broadcast refresh over granular stream updates
bcast-avoid-view-logic-in-models - Keep broadcasting logic out of models
bcast-signed-stream-names - Use signed stream names for security
bcast-reconnect-handling - Handle WebSocket disconnection and reconnection
5. Morphing & Page Refresh (HIGH)
morph-enable-page-refresh - Enable morphing for page refreshes
morph-permanent-elements - Mark stateful elements as permanent
morph-scroll-preservation - Preserve scroll position during morphing
morph-stimulus-reconnect - Handle Stimulus controller reconnection after morph
morph-frame-refresh - Use refresh='morph' on frames for additive content
morph-vs-streams - Choose morphing over complex stream orchestration
6. Performance Optimization (MEDIUM-HIGH)
perf-optimistic-ui - Implement optimistic UI updates before server confirmation
perf-batch-streams - Batch multiple stream updates into single responses
perf-frame-caching - Cache Turbo Frame responses with fragment caching
perf-prefetch-strategic - Disable prefetch on expensive endpoints
perf-memory-leak-prevention - Clean up subscriptions and event listeners
7. Stimulus Patterns (MEDIUM-HIGH)
stim-outlets-communication - Use outlets for cross-controller communication
stim-values-reactive-state - Use Values API for reactive controller state
stim-action-descriptors - Use declarative action descriptors over addEventListener
stim-small-reusable-controllers - Keep Stimulus controllers small and reusable
8. Architecture Decisions (MEDIUM)
arch-progressive-enhancement - Follow the progressive enhancement hierarchy
arch-frame-vs-stream-decision - Use frames for scoped navigation, streams for multi-target updates
arch-importmap-management - Pin JavaScript dependencies with import maps
arch-avoid-client-state - Keep state on the server, not the client
arch-stimulus-boundaries - Use Stimulus only for client-side behavior
9. Testing Hotwire (MEDIUM)
test-system-test-async - Wait for Turbo updates in system tests
test-stream-assertions - Use Turbo Stream test helpers in integration tests
test-broadcast-assertions - Assert broadcasts with Turbo test helpers
test-frame-navigation - Test frame navigation with scoped assertions
test-websocket-timing - Handle WebSocket connection timing in system tests
How to Use
Read individual reference files for detailed explanations and code examples:
Section definitions - Category structure and impact levels
Rule template - Template for adding new rules
Reference Files
File
Description
references/_sections.md
Category definitions and ordering
assets/templates/_template.md
Template for new rules
metadata.json
Version and reference information
1---2name: rails-hotwire3description: Community Rails Hotwire Best Practices4---5# Community Rails Hotwire Best Practices67Comprehensive guide for building interactive Rails applications with Hotwire (Turbo + Stimulus), maintained by Community. Contains 53 rules across 9 categories, prioritized by impact to guide automated refactoring and code generation. Follows the DHH "One Person Framework" philosophy: the server renders HTML, Turbo makes it feel like an SPA, Stimulus adds the sprinkle of JS where needed.89## When to Apply1011Reference these guidelines when:12- Configuring Turbo Drive navigation, prefetching, and caching behavior13- Adding Turbo Frames for partial page updates and lazy loading14- Delivering Turbo Streams for surgical DOM mutations15- Broadcasting real-time updates over ActionCable16- Enabling Turbo 8 morphing for page refreshes17- Writing Stimulus controllers for client-side behavior18- Handling errors in Turbo navigation, frames, and WebSocket connections19- Choosing between Drive, Frames, Streams, Morphing, and Stimulus20- Testing Hotwire interactions in system and integration tests2122## Rule Categories by Priority2324| Priority | Category | Impact | Prefix |25|----------|----------|--------|--------|26| 1 | Navigation & Drive | CRITICAL | `drive-` |27| 2 | Turbo Frames | CRITICAL | `frame-` |28| 3 | Turbo Streams | HIGH | `stream-` |29| 4 | Broadcasting & Real-Time | HIGH | `bcast-` |30| 5 | Morphing & Page Refresh | HIGH | `morph-` |31| 6 | Performance Optimization | MEDIUM-HIGH | `perf-` |32| 7 | Stimulus Patterns | MEDIUM-HIGH | `stim-` |33| 8 | Architecture Decisions | MEDIUM | `arch-` |34| 9 | Testing Hotwire | MEDIUM | `test-` |3536## Quick Reference3738### 1. Navigation & Drive (CRITICAL)3940- [`drive-prefetch-links`](references/drive-prefetch-links.md) - Enable link prefetching for instant navigation41- [`drive-form-submissions`](references/drive-form-submissions.md) - Use Turbo Drive for form submissions42- [`drive-visit-actions`](references/drive-visit-actions.md) - Control history with visit actions43- [`drive-cache-control`](references/drive-cache-control.md) - Configure Turbo cache for preview pages44- [`drive-selective-disable`](references/drive-selective-disable.md) - Disable Turbo Drive on incompatible pages45- [`drive-progress-bar`](references/drive-progress-bar.md) - Customize the Turbo progress bar46- [`drive-confirm-dialog`](references/drive-confirm-dialog.md) - Use data-turbo-confirm for destructive actions47- [`drive-error-recovery`](references/drive-error-recovery.md) - Handle Turbo navigation and fetch errors gracefully4849### 2. Turbo Frames (CRITICAL)5051- [`frame-lazy-loading`](references/frame-lazy-loading.md) - Defer frame loading until viewport entry52- [`frame-scope-navigation`](references/frame-scope-navigation.md) - Scope navigation within frames53- [`frame-src-navigation`](references/frame-src-navigation.md) - Use src for dynamic frame content54- [`frame-break-out`](references/frame-break-out.md) - Handle frame breakout for redirects55- [`frame-promote-visits`](references/frame-promote-visits.md) - Promote frame navigation to page visits56- [`frame-dom-id`](references/frame-dom-id.md) - Use dom_id for frame identification57- [`frame-empty-state`](references/frame-empty-state.md) - Provide meaningful frame loading states5859### 3. Turbo Streams (HIGH)6061- [`stream-progressive-enhance`](references/stream-progressive-enhance.md) - Always provide HTML fallback for streams62- [`stream-action-selection`](references/stream-action-selection.md) - Choose the right stream action for DOM mutations63- [`stream-multi-target`](references/stream-multi-target.md) - Use targets for multi-element updates64- [`stream-http-delivery`](references/stream-http-delivery.md) - Deliver streams via HTTP for form responses65- [`stream-websocket-source`](references/stream-websocket-source.md) - Connect WebSocket sources in the body66- [`stream-custom-actions`](references/stream-custom-actions.md) - Register custom stream actions for complex DOM updates6768### 4. Broadcasting & Real-Time (HIGH)6970- [`bcast-model-broadcasts`](references/bcast-model-broadcasts.md) - Use broadcasts_refreshes for simple model updates71- [`bcast-debounce-n1`](references/bcast-debounce-n1.md) - Debounce broadcasts to prevent N+1 broadcast storms72- [`bcast-scope-streams`](references/bcast-scope-streams.md) - Scope broadcast streams to accounts or users73- [`bcast-refresh-over-replace`](references/bcast-refresh-over-replace.md) - Prefer broadcast refresh over granular stream updates74- [`bcast-avoid-view-logic-in-models`](references/bcast-avoid-view-logic-in-models.md) - Keep broadcasting logic out of models75- [`bcast-signed-stream-names`](references/bcast-signed-stream-names.md) - Use signed stream names for security76- [`bcast-reconnect-handling`](references/bcast-reconnect-handling.md) - Handle WebSocket disconnection and reconnection7778### 5. Morphing & Page Refresh (HIGH)7980- [`morph-enable-page-refresh`](references/morph-enable-page-refresh.md) - Enable morphing for page refreshes81- [`morph-permanent-elements`](references/morph-permanent-elements.md) - Mark stateful elements as permanent82- [`morph-scroll-preservation`](references/morph-scroll-preservation.md) - Preserve scroll position during morphing83- [`morph-stimulus-reconnect`](references/morph-stimulus-reconnect.md) - Handle Stimulus controller reconnection after morph84- [`morph-frame-refresh`](references/morph-frame-refresh.md) - Use refresh='morph' on frames for additive content85- [`morph-vs-streams`](references/morph-vs-streams.md) - Choose morphing over complex stream orchestration8687### 6. Performance Optimization (MEDIUM-HIGH)8889- [`perf-optimistic-ui`](references/perf-optimistic-ui.md) - Implement optimistic UI updates before server confirmation90- [`perf-batch-streams`](references/perf-batch-streams.md) - Batch multiple stream updates into single responses91- [`perf-frame-caching`](references/perf-frame-caching.md) - Cache Turbo Frame responses with fragment caching92- [`perf-prefetch-strategic`](references/perf-prefetch-strategic.md) - Disable prefetch on expensive endpoints93- [`perf-memory-leak-prevention`](references/perf-memory-leak-prevention.md) - Clean up subscriptions and event listeners9495### 7. Stimulus Patterns (MEDIUM-HIGH)9697- [`stim-outlets-communication`](references/stim-outlets-communication.md) - Use outlets for cross-controller communication98- [`stim-values-reactive-state`](references/stim-values-reactive-state.md) - Use Values API for reactive controller state99- [`stim-action-descriptors`](references/stim-action-descriptors.md) - Use declarative action descriptors over addEventListener100- [`stim-small-reusable-controllers`](references/stim-small-reusable-controllers.md) - Keep Stimulus controllers small and reusable101102### 8. Architecture Decisions (MEDIUM)103104- [`arch-progressive-enhancement`](references/arch-progressive-enhancement.md) - Follow the progressive enhancement hierarchy105- [`arch-frame-vs-stream-decision`](references/arch-frame-vs-stream-decision.md) - Use frames for scoped navigation, streams for multi-target updates106- [`arch-importmap-management`](references/arch-importmap-management.md) - Pin JavaScript dependencies with import maps107- [`arch-avoid-client-state`](references/arch-avoid-client-state.md) - Keep state on the server, not the client108- [`arch-stimulus-boundaries`](references/arch-stimulus-boundaries.md) - Use Stimulus only for client-side behavior109110### 9. Testing Hotwire (MEDIUM)111112- [`test-system-test-async`](references/test-system-test-async.md) - Wait for Turbo updates in system tests113- [`test-stream-assertions`](references/test-stream-assertions.md) - Use Turbo Stream test helpers in integration tests114- [`test-broadcast-assertions`](references/test-broadcast-assertions.md) - Assert broadcasts with Turbo test helpers115- [`test-frame-navigation`](references/test-frame-navigation.md) - Test frame navigation with scoped assertions116- [`test-websocket-timing`](references/test-websocket-timing.md) - Handle WebSocket connection timing in system tests117118## How to Use119120Read individual reference files for detailed explanations and code examples:121122- [Section definitions](references/_sections.md) - Category structure and impact levels123- [Rule template](assets/templates/_template.md) - Template for adding new rules124125## Reference Files126127| File | Description |128|------|-------------|129| [references/_sections.md](references/_sections.md) | Category definitions and ordering |130| [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules |131| [metadata.json](metadata.json) | Version and reference information |
Run npx skillmds@latest add comeonoliver/rails-hotwire in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Community Rails Hotwire Best Practices It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
ComeOnOliver (@comeonoliver) published this skill. Their other Agent Skills are listed on their SkillMD profile.