mcpField
H
hotwire-coder

hotwire-coder

github.com/majesticlabs-dev開発50174 回インストール7 週間前に更新
リポジトリ

hotwire-coder について

Rails アプリケーションで Hotwire 機能を実装するための開発スキルです。Turbo Drive、Frames、Streams、リアルタイム配信、一般的な UI パターンを扱い、実装成果物の構成も示します。

主な機能

  1. 01Turbo Drive によるナビゲーション
  2. 02Turbo Frames による部分更新
  3. 03Turbo Streams と配信
  4. 04モーダルと無限スクロールのパターン
  5. 05デバッグとアンチパターンの指針

活用シーン

  1. 01ページの部分更新の追加
  2. 02リアルタイムコメント表示の構築
  3. 03モーダルまたは無限スクロール画面の実装

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill hotwire-coder

インストール後、Claude Code で/hotwire-coderを入力して読み込まれたか確認します。

同梱ファイルreferences/lazy-loading.md

詳細

Hotwire コーダー

Hotwire の理念

Hotwire は JSON の代わりに HTML を通信で送信します。

  • Turbo Drive - ページ全体を再読み込みせずに <body> を置き換えて、ナビゲーションを高速化します
  • Turbo Frames - ページを、リクエストに応じて更新される独立したコンテキストに分割します
  • Turbo Streams - サーバーからページの一部を更新します(HTTP または WebSocket)

Turbo Drive

選択的なオプトアウト
<%= link_to "Download PDF", report_path(format: :pdf), data: { turbo: false } %>
<%= form_with model: @legacy, data: { turbo: false } do |f| %>
フォームの送信
def create
  @post = Post.new(post_params)
  @post.save ? redirect_to(@post, notice: "Created!") : render(:new, status: :unprocessable_entity)
end

Turbo Frames

基本的なフレーム
<turbo-frame id="comments">
  <%= render @post.comments %>
  <%= link_to "Load More", post_comments_path(@post, page: 2) %>
</turbo-frame>
遅延読み込み
<turbo-frame id="notifications" src="<%= notifications_path %>" loading="lazy">
  <p>Loading...</p>
</turbo-frame>

スケルトン UI のパターン、無限スクロール、Stimulus の読み込みコントローラーについては、references/lazy-loading.md を参照してください。

フレームから抜け出す
<%= link_to "View Post", post_path(@post), data: { turbo_frame: "_top" } %>
<%= link_to "Results", search_path, data: { turbo_frame: "results" } %>
インライン編集パターン
<turbo-frame id="<%= dom_id(post) %>">
  <article>
    <h2><%= post.title %></h2>
    <%= link_to "Edit", edit_post_path(post) %>
  </article>
</turbo-frame>

Turbo Streams

ストリームアクション
<%= 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 ストリームのレスポンス
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
リアルタイム配信
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
<%= turbo_stream_from @post %>
<div id="comments"><%= render @post.comments %></div>

注記: LLM のストリーミングや、メッセージ配信の保証が必要な機能については、anycable-coder スキルを参照してください。Action Cable は最大 1 回の配信を提供するため、再接続時にチャンクが失われることがあります。

Turbo 8 のモーフィング

<head>
  <meta name="turbo-refresh-method" content="morph">
  <meta name="turbo-refresh-scroll" content="preserve">
</head>
class Post < ApplicationRecord
  after_update_commit -> { broadcast_refresh_to self }
end

よくあるパターン

モーダルパターン
<%= link_to "New Post", new_post_path, data: { turbo_frame: "modal" } %>
<turbo-frame id="modal"></turbo-frame>
無限スクロール
<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 %>

アンチパターン

アンチパターン問題解決策
フレーム ID の不一致エラーが通知されずに失敗しますID が一致することを検証します
ステータスコードの欠落Turbo がレスポンスを無視します422/303 を正しく使用します
ブロードキャストでの暗黙的なローカル変数実行時エラー常に request_id: nil を渡します

デバッグ

Turbo.setDebug(true)
document.addEventListener("turbo:frame-missing", (e) => console.error("Frame not found:", e.detail.response))

出力形式

Hotwire の機能を実装する際は、次の項目を提示してください。

  1. コントローラー - 適切なレスポンス処理を備えたアクション
  2. ビュー - フレームとストリームを含む HTML/ERB
  3. モデル - リアルタイム処理が必要な場合のブロードキャストコールバック
  4. JavaScript - 必要に応じた Stimulus コントローラー

コメント