stripe-projects
stripe projects
hotwire-turbo
Best practices for using Hotwire Turbo to create reactive applications
Full skill instructions
Rule updated on 12/15/2025 to Turbo version 8.0.18.
Hotwire consists of three main components, each suited for different use cases. Here's when to use each.
For full reference see https://turbo.hotwired.dev/
When to use:
How it works: Intercepts link clicks and form submissions, fetches the new page via AJAX, and swaps the <body> content while keeping the <head> intact.
Best practices:
data-turbo="false" to disable for specific links/forms (e.g., file downloads, external links)data-turbo-method="delete" for non-GET requests from links<%= link_to "Delete", invoice_path(@invoice), data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>
When to use:
How it works: Instead of replacing the entire <body>, morphing intelligently diffs the current DOM against the new HTML and applies only the necessary changes. This preserves:
Enabling morphing:
<%# In your layout or page head %>
<meta name="turbo-refresh-method" content="morph">
<%# Optionally preserve scroll position %>
<meta name="turbo-refresh-scroll" content="preserve">
Per-element control:
<%# Keep an element from being morphed (preserves exact state) %>
<div data-turbo-permanent id="chat-messages">
<!-- Content preserved across page updates -->
</div>
When NOT to use morphing:
When to use:
How it works: Wraps a section of the page in a <turbo-frame> tag. When a link or form inside the frame is activated, only that frame's content is replaced.
Best practices:
<!-- index.html.erb -->
<%= turbo_frame_tag @invoice do %>
<div class="invoice-row">
<%= @invoice.number %>
<%= link_to "Edit", edit_invoice_path(@invoice) %>
</div>
<% end %>
<!-- edit.html.erb -->
<%= turbo_frame_tag @invoice do %>
<%= form_with model: @invoice do |f| %>
<!-- form fields -->
<% end %>
<% end %>
turbo_frame_tag with a model — Rails generates consistent IDs (invoice_123)data-turbo-frame="_top" for full-page navigationsrc and loading: "lazy":
<%= turbo_frame_tag "comments", src: comments_path, loading: "lazy" do %>
<p>Loading comments...</p>
<% end %>
data-turbo-frame="frame_id"When to use:
How it works: Returns <turbo-stream> elements that specify actions (append, prepend, replace, update, remove, before, after, morph, refresh) and target DOM elements by ID.
Best practices:
# Controller
def create
@invoice = current_user.invoices.build(invoice_params)
respond_to do |format|
if @invoice.save
format.turbo_stream # Renders create.turbo_stream.erb
format.html { redirect_to @invoice }
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
<!-- create.turbo_stream.erb -->
<%= turbo_stream.prepend "invoices", @invoice %>
<%= turbo_stream.update "invoice_count", Invoice.count %>
<%= turbo_stream.remove "empty_state" %>
Stream Actions:
| Action | Description |
|---|---|
append | Add to end of target container |
prepend | Add to beginning of target container |
replace | Replace the entire target element |
update | Replace only the content (innerHTML) |
remove | Remove the target element |
before | Insert before the target |
after | Insert after the target |
morph | Morph the target element (intelligent diff) |
refresh | Trigger a full page refresh (optionally with morph) |
Morph stream action example:
<%# Smoothly update a section without replacing it entirely %>
<%= turbo_stream.morph "invoice_#{@invoice.id}", partial: "invoices/invoice", locals: { invoice: @invoice } %>
| Scenario | Solution |
|---|---|
| Standard navigation | Turbo Drive (automatic) |
| Edit form inline | Turbo Frame |
| Load section lazily | Turbo Frame with src |
| Add item to list | Turbo Stream append/prepend |
| Update multiple areas | Turbo Stream |
| Real-time via WebSocket | Turbo Stream over ActionCable |
| Delete from list | Turbo Stream remove |
| Modal/slideout | Turbo Frame targeting a container |
| Preserve scroll on refresh | Morphing with turbo-refresh |
| Smooth inline update | Turbo Stream morph |
| Update without losing focus | Morphing |
dom_id(@invoice)) for reliable targetinghtml format fallback for non-Turbo requestsstripe projects
Harvest every `ponytail:` comment in the codebase into a debt ledger, so the deliberate shortcuts and deferrals ponytail leaves behind get tracked instead of rotting into "later means never". One-shot report, changes nothing.
okx dex market
okx agentic wallet
gmgn portfolio
okx dapp discovery
okx agent payments protocol
Stripe payment processing with checkout sessions, subscriptions, webhooks, and customer management.
Build comprehensive 3-5 year financial models with revenue projections, cost structures, cash flow analysis, and scenario planning for early-stage startups. Use this skill when creating financial projections, calculating burn rate or runway, modeling fundraising scenarios, or preparing investor-r...
Stock and cryptocurrency analysis with portfolio management and multi-dimensional scoring.
Real-time crypto derivatives positioning, whale tracking, liquidations, and institutional ETF flows across 37 specialized tools.
Master dbt (data build tool) for analytics engineering with model organization, testing, documentation, and incremental strategies. Use when building data transformations, creating data models, or implementing analytics engineering best practices.
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Stay Ahead with Finalle.ai: The Ultimate Financial News and Tools Platform
AI-powered Pine Script code generator for TradingView
Research stocks at the speed of thought.
Empower your investment strategies with AI signals, option flow data, and advanced chart patterns.
Danelfin review covering its AI stock and ETF scores, rankings, portfolio tools, current pricing, strengths, risks, and alternatives for investors.
A software for comprehensive market sentiment analysis.
'Stock Correlations' App by Freshly.ai: Reveal Stock Patterns and Trends