Skills

Rails Hotwire Realtime

Apply Hotwire, Turbo, Stimulus, and ActionCable best practices for real-time Rails...

Install

npx skills add marckohlbrugge/37signals-skills --skill rails-hotwire-realtime -g -a claude-code -y
Category
Engineering
Updated
5mo ago
License
See repository
Context cost
Mediumabout 1,870 tokens
Runs scripts
No, instructions only

What it does

Apply Hotwire, Turbo, Stimulus, and ActionCable best practices for real-time Rails interfaces. Use when building Turbo Streams/Frames, Stimulus interactions, or websocket-driven updates.

Rails Hotwire + Realtime

Use for Turbo/Stimulus/ActionCable architecture and reviews. Patterns from Campfire (cable-heavy chat) and Fizzy (streams-only kanban).

Choose the Right Realtime Architecture

Two proven 37signals topologies:

  • Streams-only (Fizzy): no custom ActionCable channels at all. turbo_stream_from, broadcasts_refreshes + morph, lazy frames with ETags. Default to this for CRUD-ish apps.
  • Cable-augmented (Campfire): custom channels only for lightweight JSON signals (presence, typing, unread pings) where rendering HTML server-side would be wasteful. Durable DOM state still goes through Turbo Streams.

Rule of thumb: Turbo Streams for anything that changes the DOM; bare ActionCable only for tiny ephemeral signals.

Turbo Defaults

  • Prefer server-rendered partial updates over heavy client-side state systems.
  • Set global morph refresh in the layout: turbo_refreshes_with method: :morph, scroll: :preserve.
  • Use Turbo Streams for targeted updates; one action can render a multi-target stream template that updates every affected region atomically (source column + destination + detail pane).
  • Lazy-load expensive sections with turbo_frame_tag ..., src:, loading: :lazy and give the frame endpoint its own fresh_when ETag. Extract frequently-changing fragments into their own frames so they don't bust the parent cache.
  • Use data-turbo-permanent for elements that must survive navigation/morph (footer trays, in-progress editors).
  • Block morph from clobbering client-owned state (e.g. localStorage-driven collapsed columns) via turbo:before-morph-attribute + preventDefault().
  • Exempt realtime-heavy pages from Turbo's page cache (turbo_exempts_page_from_cache); rely on frame-level ETags instead.
  • Optimistic UI without a JS framework: server-render a <template> partial with $placeholder$ tokens; client clones it with a generated ID before submit; the stream response replaces it.

Broadcast Patterns

Read the whole SKILL.md on GitHub

More in Engineering