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.
Automate repetitive workflows and reduce manual effort
Example: Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example: Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example: Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Time estimate: 15-45 minutes depending on use case complexity
Prerequisites
Submit your Claude Code skill and start earning
epx add marckohlbrugge/37signals-skills/rails-hotwire-realtimeCompatible with
Supported agents
| name | rails-hotwire-realtime |
| description | 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. |
| disable-model-invocation | true |
Use for Turbo/Stimulus/ActionCable architecture and reviews. Patterns from Campfire (cable-heavy chat) and Fizzy (streams-only kanban).
Two proven 37signals topologies:
turbo_stream_from, broadcasts_refreshes + morph, lazy frames with ETags. Default to this for CRUD-ish apps.Rule of thumb: Turbo Streams for anything that changes the DOM; bare ActionCable only for tiny ephemeral signals.
turbo_refreshes_with method: :morph, scroll: :preserve.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.data-turbo-permanent for elements that must survive navigation/morph (footer trays, in-progress editors).turbo:before-morph-attribute + preventDefault().turbo_exempts_page_from_cache); rely on frame-level ETags instead.<template> partial with $placeholder$ tokens; client clones it with a generated ID before submit; the stream response replaces it.Message::Broadcasts concern with broadcast_create), not in controllers.[board.account, :all_boards], [user, :notifications] — stream names are isolation boundaries.broadcasts_refreshes for direct subscribers plus broadcasts_refreshes_to ->(r) { [r.account, :aggregate_view] } for account-wide views.before_update when preview-relevant fields change; broadcast if: :preview_changed?.Model.suppressing_turbo_broadcasts), e.g. around ActiveStorage analysis.render_to_string once, then broadcast_replace_to user, ..., html: per recipient.broadcast_*_later async variants when synchronous broadcasting hurts request latency.broadcast_image_tag pattern) so URLs resolve.?since=<epoch_ms>); server appends new records and replaces updated ones.HeartbeatChannel gives reliable connected/disconnected callbacks for triggering catch-up and a debounced offline UI.connect() with a turbo-preview check so back/forward cache previews don't open sockets or request permissions.disconnect. For cable subscriptions, defer unsubscribe one animation frame and skip if the element reconnected (morph churn).data-controller/data-action/target wiring in Ruby helpers (message_area_tag) so views stay declarative and the contract lives in one place.<meta> tags into a tiny window.Current object rather than inlining JSON.targetConnected callbacks).maintain_scroll: true) on broadcasts and handle it once in a turbo:before-stream-render listener.id on turbo:submit-start so background broadcasts can't race the form's own stream response.Connection#connect with the same identity resolution as HTTP; scope channel subscriptions through ownership (current_user.rooms.find_by(id: params[:room_id])).ActionCable.server.remote_connections.where(current_user: user).disconnect.connections counter + connected_at, 60s freshness scope) to survive multi-tab and reconnects; debounce visibility changes (~5s) to avoid flicker.request.script_name via a custom meta tag helper.touch: true chains so child edits invalidate parents.data-creator-id, let a Stimulus controller compare against Current.user and toggle visibility — don't break fragment caching for per-user toggles.assert_turbo_stream_broadcasts([user, :notifications], count: 1) { ... } and assert_no_turbo_stream_broadcasts for negatives.as: :turbo_stream + assert_turbo_stream action: :replace, target: dom_id(...).ActionCable.server.pubsub.broadcasts + assert_select covers it.using_session("OtherUser") for multi-user realtime, and wait for turbo-cable-stream-source[connected] before asserting.turbo_stream_from already does.data-turbo-permanent).AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionrails-hotwire-realtimeExecute the skills CLI command in your project's root directory to begin installation:
epx add marckohlbrugge/37signals-skills/rails-hotwire-realtimeFetches rails-hotwire-realtime from marckohlbrugge/37signals-skills and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
.cursor/skills/rails-hotwire-realtime
Restart Cursor to activate rails-hotwire-realtime. Access via /rails-hotwire-realtimein your agent's command palette.
Learn more:View source on GitHubSkills CLI docsAbout CursorWhat are agent skills?
Steps
Common Pitfalls
✓ Do
✗ Don't
💡 Pro Tips
✓ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
dhh
marckohlbrugge/37signals-skills · dhh · same repo
rails-best-practices-core
marckohlbrugge/37signals-skills · rails-best-practices-core · same repo
rails-migrations
marckohlbrugge/37signals-skills · rails-migrations · same repo
rails-jobs
marckohlbrugge/37signals-skills · rails-jobs · same repo
rails-webhooks
marckohlbrugge/37signals-skills · rails-webhooks · same repo
rails-security-multitenancy
marckohlbrugge/37signals-skills · rails-security-multitenancy · same repo
rails-hotwire-realtime fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
rails-hotwire-realtime fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
Useful defaults in rails-hotwire-realtime — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
I recommend rails-hotwire-realtime for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
Solid pick for teams standardizing on skills: rails-hotwire-realtime is focused, and the summary matches what you get after install.
We added rails-hotwire-realtime from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
rails-hotwire-realtime fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
Registry listing for rails-hotwire-realtime matched our evaluation — installs cleanly and behaves as described in the markdown.
Registry listing for rails-hotwire-realtime matched our evaluation — installs cleanly and behaves as described in the markdown.
rails-hotwire-realtime is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
showing 1-10 of 71