Backend
laravel-reverb
Sets up Laravel Reverb WebSocket server for real-time features
Overview
The laravel-reverb agent sets up Laravel Reverb for real-time WebSocket communication. It configures broadcasting, creates events, sets up channel authorization, and integrates Laravel Echo on the client side.
Responsibilities
- Reverb Installation - Install and configure the WebSocket server
- Broadcast Events - Create events that broadcast to channels
- Channel Authorization - Private and presence channel auth
- Echo Integration - Client-side WebSocket setup
- Scaling Configuration - Redis pub/sub for horizontal scaling
- SSL/TLS Setup - Secure WebSocket connections
What It Creates
| Component | Location | Purpose |
|---|---|---|
| Broadcast Config | config/broadcasting.php |
Reverb connection settings |
| Channel Routes | routes/channels.php |
Channel authorization |
| Broadcast Events | app/Events/ |
Real-time event classes |
| Echo Bootstrap | resources/js/bootstrap.js |
Client-side Echo setup |
Generated Broadcast Event
<?php
namespace App\Events;
use App\Models\Message;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public Message $message
) {}
public function broadcastOn(): array
{
return [
new PrivateChannel('chat.' . $this->message->conversation_id),
];
}
public function broadcastWith(): array
{
return [
'id' => $this->message->id,
'body' => $this->message->body,
'user' => [
'id' => $this->message->user->id,
'name' => $this->message->user->name,
'avatar' => $this->message->user->avatar_url,
],
'created_at' => $this->message->created_at->toIso8601String(),
];
}
public function broadcastAs(): string
{
return 'message.sent';
}
}
Channel Authorization
// routes/channels.php
// Private channel
Broadcast::channel('orders.{orderId}', function ($user, $orderId) {
return $user->id === Order::find($orderId)?->user_id;
});
// Presence channel with user data
Broadcast::channel('chat.{conversationId}', function ($user, $conversationId) {
if ($user->canAccessConversation($conversationId)) {
return [
'id' => $user->id,
'name' => $user->name,
'avatar' => $user->avatar_url,
];
}
});
// Public channel (no auth needed)
Broadcast::channel('notifications', function () {
return true;
});
Laravel Echo Setup
// resources/js/bootstrap.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
// Listen to private channel
Echo.private(`chat.${conversationId}`)
.listen('.message.sent', (event) => {
messages.value.push(event);
});
// Presence channel
Echo.join(`chat.${conversationId}`)
.here((users) => {
onlineUsers.value = users;
})
.joining((user) => {
onlineUsers.value.push(user);
})
.leaving((user) => {
onlineUsers.value = onlineUsers.value.filter(u => u.id !== user.id);
});
Reverb Configuration
// config/broadcasting.php
'reverb' => [
'driver' => 'reverb',
'key' => env('REVERB_APP_KEY'),
'secret' => env('REVERB_APP_SECRET'),
'app_id' => env('REVERB_APP_ID'),
'options' => [
'host' => env('REVERB_HOST'),
'port' => env('REVERB_PORT', 443),
'scheme' => env('REVERB_SCHEME', 'https'),
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
],
],
// .env
BROADCAST_DRIVER=reverb
REVERB_APP_ID=app-id
REVERB_APP_KEY=app-key
REVERB_APP_SECRET=app-secret
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http
Invoked By Commands
- /laravel-agent:reverb:setup - Setup Reverb server
- /laravel-agent:broadcast:make - Create broadcast events
Guardrails
The Reverb agent follows strict rules:
- ALWAYS authorize private channels properly
- ALWAYS use broadcastAs() for consistent event names
- ALWAYS keep broadcast payloads small
- NEVER broadcast sensitive data without channel auth
- NEVER forget to run queue workers for ShouldBroadcast
See Also
- laravel-websocket skill - Auto-invoked WebSocket expertise
- laravel-queue - Background jobs for broadcasts