smithery.ai

developing-with-turbo-streams

>- Develops with Turbo Streams for partial page updates and real-time broadcasting. Activates when using turbo_stream() or turbo_stream_view() helpers; working with stream actions like append, prepend, replace, update, remove, before, after, or refresh; using the Broadcasts trait, broadcastAppend, broadcastPrepend, broadcastReplace, broadcastRemove, or broadcastRefresh methods; listening with x-turbo::stream-from; using the TurboStream facade for handmade broadcasts; combining multiple streams;…

First seen Mar 22, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,142 B
  • docs SUMMARY.md 287 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Turbo Streams

Turbo Streams let you change any part of the page using eight actions: append, prepend, replace, update, remove, before, after, and refresh. They work as HTTP responses (after form submissions) and as real-time broadcasts over WebSocket.

HTTP Turbo Streams

Detecting Turbo Stream Requests

Check if the request accepts Turbo Stream responses before returning them:

@verbatim

<code-snippet name="Detecting" lang="php"> public function store(Request $request) { $post = Post::create($request->validated());

if ($request->wantsTurboStream()) { return turbo_stream($post); }

return redirect()->route('posts.show', $post); } </code-snippet>

@endverbatim

The turbo_stream() Helper

@verbatim

<code-snippet name="turbostream helper" lang="php"> // Auto-detect action from context (uses model state: created → append, updated → replace, deleted → remove) return turbostream($model); return turbo_stream($model, 'prepend');

// Fluent builder (no arguments returns a PendingTurboStreamResponse) return turbostream()->append('posts', view('posts.post', ['post' => $post])); return turbostream()->prepend('posts', view('posts.post', ['post' => $post])); return turbostream()->before(domid($post), view('posts.post', ['post' => $newPost])); return turbostream()->after(domid($post), view('posts.post', ['post' => $newPost])); return turbostream()->replace($post, view('posts.post', ['post' => $post])); return turbostream()->update($post, view('posts.post', ['post' => $post])); return turbostream()->remove($post); return turbostream()->refresh(); </code-snippet>

@endverbatim

Targeting Multiple Elements

Use the *All methods or targets() to target multiple elements by CSS selector:

@verbatim

<code-snippet name="Multiple targets" lang="php"> return turbostream()->appendAll('.comment', view('comments.comment', ['comment' => $comment])); return turbostream()->replaceAll('.notification', view('notifications.notification')); return turbo_stream()->removeAll('.old-item'); </code-snippet>

@endverbatim

Morph Method

Use morph() on replace/update to morph content instead of replacing it:

@verbatim

<code-snippet name="Morph" lang="php"> return turbostream()->replace($post, view('posts.post', ['post' => $post]))->morph(); </code-snippet>

@endverbatim

Combining Multiple Streams

Pass an array or collection to return multiple stream actions in one response:

@verbatim

<code-snippet name="Multiple streams" lang="php"> return turbostream([ turbostream()->append('posts', view('posts.post', ['post' => $post])), turbostream()->update('postcount', view('posts.count', ['count' => Post::count()])), turbostream()->remove('emptystate'), ]); </code-snippet>

@endverbatim

Turbo Stream Views

Render a full Blade view with the Turbo Stream content type. Useful for complex multi-stream responses:

@verbatim

<code-snippet name="Stream view" lang="php"> return turbostreamview('posts.turbo.created', ['post' => $post]); </code-snippet>

<code-snippet name="Stream view template" lang="blade"> {{-- resources/views/posts/turbo/created.blade.php --}} <x-turbo::stream action="append" target="posts"> @include('posts._post', ['post' => $post]) </x-turbo::stream>

<x-turbo::stream action="update" target="post_count"> {{ Post::count() }} posts </x-turbo::stream> </code-snippet>

@endverbatim

The Stream Blade Component

@verbatim

<code-snippet name="Blade component" lang="blade"> {{-- Single target by ID --}} <x-turbo::stream action="append" target="messages"> <div id="message_1">My new message!</div> </x-turbo::stream>

{{-- Target by model (auto-generates DOM ID) --}} <x-turbo::stream action="replace" :target="$post"> @include('posts._post', ['post' => $post]) </x-turbo::stream>

{{-- Multiple targets by CSS selector --}} <x-turbo::stream action="remove" targets=".notification" /> </code-snippet>

@endverbatim

Broadcasting (Real-Time Streams)

The Broadcasts Trait

Add the Broadcasts trait to your Eloquent model:

@verbatim

<code-snippet name="Broadcasts trait" lang="php"> use HotwiredLaravel\TurboLaravel\Models\Broadcasts;

class Post extends Model { use Broadcasts; } </code-snippet>

@endverbatim

Manual Broadcasting

Call broadcast methods directly on a model instance:

@verbatim

<code-snippet name="Manual broadcasting" lang="php"> $comment->broadcastAppend(); $comment->broadcastPrepend(); $comment->broadcastReplace(); $comment->broadcastUpdate(); $comment->broadcastRemove(); $comment->broadcastBefore('sometarget'); $comment->broadcastAfter('sometarget'); $comment->broadcastRefresh();

// Broadcast only to other users (exclude current user) $comment->broadcastAppend()->toOthers();

// Queue the broadcast for async processing $comment->broadcastAppend()->later(); </code-snippet>

@endverbatim

Directed Broadcasting

Broadcast to a specific model's channel:

@verbatim

<code-snippet name="Directed broadcasting" lang="php"> // Broadcast to the post's channel instead of the comment's own channel $comment->broadcastAppendTo($post); $comment->broadcastPrependTo($post); $comment->broadcastReplaceTo($post); $comment->broadcastUpdateTo($post); $comment->broadcastRemoveTo($post); $comment->broadcastRefreshTo($post); </code-snippet>

@endverbatim

Automatic Broadcasting

Enable automatic broadcasts on model lifecycle events:

@verbatim

<code-snippet name="Auto broadcasting" lang="php"> class Comment extends Model { use Broadcasts;

// Enable auto-broadcasting (broadcasts on create, update, delete) protected $broadcasts = true;

// Customize insert action (default is 'append') protected $broadcasts = ['insertsBy' => 'prepend'];

// Specify which model's channel to broadcast to protected $broadcastsTo = 'post';

// Or define dynamically public function broadcastsTo() { return $this->post; } } </code-snippet>

@endverbatim

Page Refresh Broadcasting

Instead of granular stream actions, broadcast a page refresh signal:

@verbatim

<code-snippet name="Refresh broadcasting" lang="php"> class Post extends Model { use Broadcasts;

// Auto-broadcast page refreshes on model changes protected $broadcastsRefreshes = true; } </code-snippet>

@endverbatim

This works best with <x-turbo::refreshes-with method="morph" scroll="preserve" /> in the layout.

Listening for Broadcasts

Use the <x-turbo::stream-from> component in your Blade views to subscribe to a channel:

@verbatim

<code-snippet name="Listening" lang="blade"> {{-- Private channel (default) — requires channel auth --}} <x-turbo::stream-from :source="$post" />

{{-- Public channel — no auth needed --}} <x-turbo::stream-from :source="$post" type="public" /> </code-snippet>

@endverbatim

Define the channel authorization in routes/channels.php:

@verbatim

<code-snippet name="Channel auth" lang="php"> use App\Models\Post;

Broadcast::channel(Post::class, function ($user, Post $post) { return $user->belongsToTeam($post->team); }); </code-snippet>

@endverbatim

Handmade Broadcasts (via Facade)

Use the TurboStream facade for broadcasts not tied to a model:

@verbatim

<code-snippet name="Facade broadcasting" lang="php"> use HotwiredLaravel\TurboLaravel\Facades\TurboStream;

TurboStream::broadcastAppend( content: view('notifications._notification', ['notification' => $notification]), target: 'notifications', channel: 'general', );

TurboStream::broadcastRemove(target: 'notification_1', channel: 'general'); TurboStream::broadcastRefresh(channel: 'general'); </code-snippet>

@endverbatim

Broadcasting from Response Builder

Chain broadcastTo() on a Turbo Stream response to also broadcast it:

@verbatim

<code-snippet name="Response broadcasting" lang="php"> turbostream() ->append('posts', view('posts.post', ['post' => $post])) ->broadcastTo('general'); </code-snippet>

@endverbatim

Global Broadcast Scope

Exclude the current user from all broadcasts in a request:

@verbatim

<code-snippet name="Broadcast to others" lang="php"> use HotwiredLaravel\TurboLaravel\Facades\Turbo;

// In a controller or middleware Turbo::broadcastToOthers();

// Anywhere Turbo::broadcastToOthers(function () { // Turbo Streams broadcasted here will not be delivered to the current user... }); </code-snippet>

@endverbatim