rails-ai:hotwire
Use when adding interactivity to Rails views - Hotwire Turbo (Drive, Frames, Streams, Morph) and Stimulus controllers
What this skill does
# Hotwire (Turbo + Stimulus)
Build fast, interactive, SPA-like experiences using server-rendered HTML with Hotwire. Turbo provides navigation and real-time updates without writing JavaScript. Stimulus enhances HTML with lightweight JavaScript controllers.
<when-to-use>
- Adding interactivity without heavy JavaScript frameworks
- Building real-time, SPA-like experiences with server-rendered HTML
- Implementing live updates, infinite scroll, or dynamic content
- Creating modals, inline editing, or interactive UI components
- Replacing traditional AJAX with modern, declarative patterns
</when-to-use>
<benefits>
- **SPA-Like Speed** - Turbo Drive accelerates navigation without full page reloads
- **Real-time Updates** - Turbo Streams deliver live changes via ActionCable
- **Progressive Enhancement** - Works without JavaScript, enhanced with it (TEAM RULE #13)
- **Simpler Architecture** - Server-rendered HTML reduces client-side complexity
- **Turbo Morph** - Intelligent DOM updates preserve scroll, focus, form state (TEAM RULE #7)
- **Less JavaScript** - Stimulus provides just enough JS for interactivity
</benefits>
<team-rules-enforcement>
**This skill enforces:**
- ✅ **Rule #5:** Turbo Morph by default (Frames only for modals, inline editing, pagination, tabs)
- ✅ **Rule #6:** Progressive enhancement (must work without JavaScript)
**Reject any requests to:**
- Use Turbo Frames everywhere (use Turbo Morph for general CRUD)
- Skip progressive enhancement (features that require JavaScript to function)
- Build non-functional UIs without JavaScript fallbacks
</team-rules-enforcement>
<verification-checklist>
Before completing Hotwire features:
- ✅ Works without JavaScript (progressive enhancement verified)
- ✅ Turbo Morph used for CRUD operations (not Frames)
- ✅ Turbo Frames only for: modals, inline editing, pagination, tabs
- ✅ Stimulus controllers clean up in disconnect()
- ✅ All interactive features tested
- ✅ All tests passing
</verification-checklist>
<standards>
- **TEAM RULE #7:** Prefer Turbo Morph over Turbo Frames/Stimulus for general CRUD
- **TEAM RULE #13:** Ensure progressive enhancement (works without JavaScript)
- Use Turbo Drive for automatic page acceleration
- Use Turbo Morph for list updates and CRUD operations (preserves state)
- Use Turbo Frames ONLY for: modals, inline editing, tabs, pagination, lazy loading
- Use Turbo Streams for real-time updates via ActionCable
- Use Stimulus for client-side interactions (dropdowns, character counters, dynamic forms)
- Always clean up in Stimulus disconnect() to prevent memory leaks
- Test with JavaScript disabled to verify progressive enhancement
</standards>
---
## Hotwire Turbo
Turbo provides fast, SPA-like navigation and real-time updates using server-rendered HTML. Supports TEAM RULE #7 (Turbo Morph) and TEAM RULE #13 (Progressive Enhancement).
### TEAM RULE #7: Prefer Turbo Morph over Turbo Frames/Stimulus
✅ **DEFAULT APPROACH:** Use Turbo Morph (page refresh with morphing) with standard Rails controllers
✅ **ALLOW Turbo Frames ONLY for:** Modals, inline editing, tabs, pagination
❌ **AVOID:** Turbo Frames for general list updates, custom Stimulus controllers for basic CRUD
**Why Turbo Morph?** Preserves scroll position, focus, form state, and video playback. Works with stock Rails scaffolds. Simpler than Frames/Stimulus in 90% of cases.
### Turbo Drive
<pattern name="turbo-drive-basics">
<description>Automatic page acceleration with Turbo Drive</description>
Turbo Drive intercepts links and forms automatically. Control with `data` attributes:
```erb
<%# Disable Turbo for specific links %>
<%= link_to "Download PDF", pdf_path, data: { turbo: false } %>
<%# Replace without history %>
<%= link_to "Dismiss", dismiss_path, data: { turbo_action: "replace" } %>
```
</pattern>
### Turbo Morphing (Page Refresh) - PREFERRED
**Use Turbo Morph by default with standard Rails controllers.** Morphing intelligently updates only changed DOM elements while preserving scroll position, focus, form state, and media playback.
<pattern name="enable-morphing-layout">
<description>Enable Turbo Morph in your layout (one-time setup)</description>
```erb
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
<title><%= content_for?(:title) ? yield(:title) : "App" %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
<%# Enable Turbo Morph for page refreshes %>
<meta name="turbo-refresh-method" content="morph">
<meta name="turbo-refresh-scroll" content="preserve">
</head>
<body>
<%= yield %>
</body>
</html>
```
**That's it!** Standard Rails controllers now work with morphing. No custom JavaScript needed.
**Reference:** [Turbo Page Refreshes Documentation](https://turbo.hotwired.dev/handbook/page_refreshes)
</pattern>
<pattern name="standard-rails-crud-with-morph">
<description>Standard Rails CRUD works automatically with Turbo Morph</description>
**Controller (stock Rails scaffold):**
```ruby
class FeedbacksController < ApplicationController
def index
@feedbacks = Feedback.all
end
def create
@feedback = Feedback.new(feedback_params)
if @feedback.save
redirect_to feedbacks_path, notice: "Feedback created"
else
render :new, status: :unprocessable_entity
end
end
def update
if @feedback.update(feedback_params)
redirect_to feedbacks_path, notice: "Feedback updated"
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@feedback.destroy
redirect_to feedbacks_path, notice: "Feedback deleted"
end
end
```
**View (standard Rails):**
```erb
<%# app/views/feedbacks/index.html.erb %>
<h1>Feedbacks</h1>
<%= link_to "New Feedback", new_feedback_path, class: "btn btn-primary" %>
<div id="feedbacks">
<% @feedbacks.each do |feedback| %>
<%= render feedback %>
<% end %>
</div>
<%# app/views/feedbacks/_feedback.html.erb %>
<div id="<%= dom_id(feedback) %>" class="card">
<h3><%= feedback.content %></h3>
<div class="actions">
<%= link_to "Edit", edit_feedback_path(feedback), class: "btn btn-sm" %>
<%= button_to "Delete", feedback_path(feedback), method: :delete,
class: "btn btn-sm btn-error",
form: { data: { turbo_confirm: "Are you sure?" } } %>
</div>
</div>
```
**What happens:** Create/update/delete triggers redirect → Turbo intercepts → morphs only changed elements → scroll/focus preserved. No custom code needed!
</pattern>
<pattern name="permanent-elements-morph">
<description>Prevent specific elements from morphing with data-turbo-permanent</description>
```erb
<%# Flash messages persist during morphing %>
<div id="flash-messages" data-turbo-permanent>
<% flash.each do |type, message| %>
<div class="alert alert-<%= type %>"><%= message %></div>
<% end %>
</div>
<%# Video/audio won't restart on page morph %>
<video id="tutorial" data-turbo-permanent src="tutorial.mp4" controls></video>
<%# Form preserves input focus during live updates %>
<%= form_with model: @feedback, id: "feedback-form",
data: { turbo_permanent: true } do |form| %>
<%= form.text_area :content %>
<%= form.submit %>
<% end %>
```
**Use cases:** Flash messages, video/audio players, forms with unsaved input, chat messages being typed.
</pattern>
<pattern name="broadcast-refresh-realtime">
<description>Real-time updates with broadcasts_refreshes (morphs all connected clients)</description>
```ruby
# Model broadcasts page refresh to all subscribers (Rails 8+)
class Feedback < ApplicationRecord
broadcasts_refreshes
end
```
```erb
<%# View subscribes to stream - morphs when model changes %>
<%= turbo_stream_from @feedback %>
<div id="feedbacks">
<% @feedbacks.each do |feedback| %>
<%= render feedback %>
<% end %>
</div>
```
**What happens:** User A creates feedback → server broadcasts `<turbo-stream acRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.