Skip to main content

Hotwire Patterns

Claude Code skill with internals-informed Hotwire mental models — Turbo Drive/Frames/Streams, Morphing, Turbo Cache, ActionCable broadcasting, Stimulus design, and Hotwire Native.

A Claude Code skill that gives Claude internals-informed mental models for building and debugging Hotwire applications. Core philosophy: enhance the browser, don’t reinvent it — start by imagining a JS-free, plain-HTML version of every feature, then compose the pages into an integrated UI with Turbo. HTML is the source of truth for state, everywhere.

It complements Better Stimulus (the authority for writing controllers) and Rails Hotwire Driver (which exercises a running Hotwire app from the terminal). This skill is the knowledge layer — how Turbo and Stimulus actually work under the hood.


What Is This?

A Claude Code skill that helps Claude reason about:

  • Turbo Drive, Frames, and Streams — how each observer scopes an update, and the classic frame-id mismatch that produces “Content missing”
  • Morphing — the idiomorph algorithm, exactly when a morph runs, and how to exclude elements
  • Turbo Cache — snapshot mechanics, preview flashing, turbo-permanent, and cache-control
  • Broadcasting — ActionCable stream sources, the ~0.5s debounce, and request-id dedup
  • Stimulus design — callbacks over connect, composition via events vs outlets
  • Hotwire Native — Path Configuration, Bridge Components, and the native-adapter mental model
  • Testing & debugging — system-test flakiness, collaborative tests, legacy migration, and internals-informed debugging

It is delivered as a skill (a knowledge module plus focused reference files), not an autonomous agent. Claude reads SKILL.md for the decision frameworks and pulls in a reference only when a specific branch needs it.


The Escalation Ladder

The skill’s central idea: Hotwire is a cost/benefit dial, not a single approach. Choose the cheapest tool that works, and escalate only when the previous rung stops being a good tradeoff:

  1. Turbo Drive + Morphing refreshes — re-render everything server-side; fastest to build.
  2. Turbo Frames — decompose the page; localize updates without touching the rest.
  3. Turbo Stream actions — surgical DOM updates; more precise, more maintenance cost.
  4. Stimulus — small client-side behavior where a server round-trip makes no sense.
  5. Island of a reactive framework or API calls — only for genuinely high-interactivity widgets (maps, editors).

Different parts of one app can sit on different rungs; it all composes.


Quick Start

1. Add the Marketplace

/plugin marketplace add maquina-app/rails-claude-code

2. Install the Plugin

/plugin install hotwire-patterns@maquina

3. Ask About Hotwire

The skill triggers on Hotwire design decisions and symptoms:

> Why does morphing wipe my form?
> My Turbo Stream broadcast isn't arriving
> This system test is flaky
> How do I add Turbo to a legacy app?
> Wrap my app with Hotwire Native

What It Covers

The main SKILL.md holds the decision frameworks and per-topic essentials; each deep dive lives in a reference file Claude loads on demand.

Topic Reference Highlights
Turbo internals (in SKILL.md) Drive/Frames/Streams observers, _top escaping, lazy frames, the frame-id mismatch
Morphing morphing.md idiomorph algorithm, when morph actually runs, scoped exclusion via turbo:before-morph-element
Turbo Cache (in SKILL.md) snapshot cloneNode, preview flashing, data-turbo-temporary, cache-control meta
Broadcasting (in SKILL.md) signed stream names, the background-job debounce, originating-client dedup
Stimulus design stimulus.md callbacks over connect, events vs outlets, the dynamic-forms server-render pattern
Hotwire Native hotwire-native.md native adapter, Path Configuration, Bridge Components, publishing
Testing testing-and-legacy.md flakiness (assert stable state), multi-session broadcast tests, gradual Turbo adoption
Debugging debugging.md unminify Turbo, DOM break-on breakpoints, source landmarks, ActionCable filtering

Custom Stream Actions

A recurring theme: the correct UI update is only known server-side after processing. Custom Turbo Stream actions are the sanctioned way to run backend-driven browser behavior with a constrained, maintainable vocabulary — and they keep you CSP-compatible (no unsafe-inline):

Turbo.StreamActions.log = function () {
  console.log(this.getAttribute("message"))
}

Pair with a Ruby helper module included into Turbo::Streams::TagBuilder. Prefer small, app-specific actions over dropping in large libraries.


Package Contents

hotwire-patterns/
└── skills/hotwire-patterns/
    ├── SKILL.md                    # Overview + decision frameworks + per-topic essentials
    └── references/
        ├── morphing.md             # idiomorph algorithm and gotchas
        ├── stimulus.md             # reusable, composable controller design
        ├── hotwire-native.md       # iOS/Android wrapping
        ├── testing-and-legacy.md   # system tests + gradual Turbo adoption
        └── debugging.md            # internals-informed debugging

Team Installation

Add to your project’s .claude/settings.json:

{
  "extraKnownMarketplaces": {
    "maquina": {
      "source": {
        "source": "github",
        "repo": "maquina-app/rails-claude-code"
      }
    }
  },
  "enabledPlugins": [
    "hotwire-patterns@maquina"
  ]
}

Next Steps