hotwire-coder
Use when implementing Hotwire features with Turbo Drive, Turbo Frames, and Turbo Streams. Applies Rails 8 conventions, morphing, broadcasts, lazy loading, and real-time update patterns.
What this skill does
# Hotwire Coder
## Hotwire Philosophy
Hotwire sends HTML over the wire instead of JSON:
- **Turbo Drive** - Accelerates navigation by replacing `<body>` without full page reloads
- **Turbo Frames** - Decompose pages into independent contexts that update on request
- **Turbo Streams** - Deliver partial page updates from server (HTTP or WebSocket)
## Turbo Drive
### Selective Opt-Out
```erb
<%= link_to "Download PDF", report_path(format: :pdf), data: { turbo: false } %>
<%= form_with model: @legacy, data: { turbo: false } do |f| %>
```
### Form Submissions
```ruby
def create
@post = Post.new(post_params)
@post.save ? redirect_to(@post, notice: "Created!") : render(:new, status: :unprocessable_entity)
end
```
## Turbo Frames
### Basic Frame
```erb
<turbo-frame id="comments">
<%= render @post.comments %>
<%= link_to "Load More", post_comments_path(@post, page: 2) %>
</turbo-frame>
```
### Lazy Loading
```erb
<turbo-frame id="notifications" src="<%= notifications_path %>" loading="lazy">
<p>Loading...</p>
</turbo-frame>
```
See `references/lazy-loading.md` for skeleton UI patterns, infinite scroll, and Stimulus loading controllers.
### Breaking Out of Frames
```erb
<%= link_to "View Post", post_path(@post), data: { turbo_frame: "_top" } %>
<%= link_to "Results", search_path, data: { turbo_frame: "results" } %>
```
### Inline Editing Pattern
```erb
<turbo-frame id="<%= dom_id(post) %>">
<article>
<h2><%= post.title %></h2>
<%= link_to "Edit", edit_post_path(post) %>
</article>
</turbo-frame>
```
## Turbo Streams
### Stream Actions
```erb
<%= turbo_stream.append "comments" do %><%= render @comment %><% end %>
<%= turbo_stream.replace dom_id(@post) do %><%= render @post %><% end %>
<%= turbo_stream.remove dom_id(@comment) %>
```
### HTTP Stream Responses
```ruby
def create
@comment = @post.comments.create(comment_params)
respond_to do |format|
format.turbo_stream # renders create.turbo_stream.erb
format.html { redirect_to @post }
end
end
```
### Real-Time Broadcasts
```ruby
class Comment < ApplicationRecord
after_create_commit -> {
broadcast_append_to post, target: "comments", partial: "comments/comment"
}
after_update_commit -> { broadcast_replace_to post }
after_destroy_commit -> { broadcast_remove_to post }
end
```
```erb
<%= turbo_stream_from @post %>
<div id="comments"><%= render @post.comments %></div>
```
> **Note:** For LLM streaming or features requiring message delivery guarantees, see `anycable-coder` skill. Action Cable provides at-most-once delivery which can lose chunks on reconnection.
## Turbo 8 Morphing
```erb
<head>
<meta name="turbo-refresh-method" content="morph">
<meta name="turbo-refresh-scroll" content="preserve">
</head>
```
```ruby
class Post < ApplicationRecord
after_update_commit -> { broadcast_refresh_to self }
end
```
## Common Patterns
### Modal Pattern
```erb
<%= link_to "New Post", new_post_path, data: { turbo_frame: "modal" } %>
<turbo-frame id="modal"></turbo-frame>
```
### Infinite Scroll
```erb
<div id="posts"><%= render @posts %></div>
<% if @posts.next_page? %>
<turbo-frame id="pagination" src="<%= posts_path(page: @posts.next_page) %>" loading="lazy">
<p>Loading more...</p>
</turbo-frame>
<% end %>
```
## Anti-Patterns
| Anti-Pattern | Problem | Solution |
|--------------|---------|----------|
| Mismatched frame IDs | Silent failures | Validate IDs match |
| Missing status codes | Turbo ignores response | Use 422/303 correctly |
| Implicit locals in broadcasts | Runtime errors | Always pass `request_id: nil` |
## Debugging
```javascript
Turbo.setDebug(true)
document.addEventListener("turbo:frame-missing", (e) => console.error("Frame not found:", e.detail.response))
```
## Output Format
When implementing Hotwire features, provide:
1. **Controller** - Actions with proper response handling
2. **Views** - HTML/ERB with frames and streams
3. **Model** - Broadcast callbacks if real-time needed
4. **JavaScript** - Stimulus controllers if needed
Related 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.