I’m always excited to take on new projects and collaborate with innovative teams to build impactful digital solutions.
Learn how to build real-time features like live notifications, chat, and dashboards using Laravel Reverb, Livewire, and Echo with practical examples.
Real-time functionality is no longer a luxury - users expect live updates, instant notifications, and collaborative features. Laravel's ecosystem offers a complete real-time stack: Reverb (a blazing-fast WebSocket server written in PHP), Livewire for reactive components, and Echo for client-side listening.
Laravel Reverb is a first-party WebSocket server that works seamlessly with Laravel's event broadcasting. It's built on ReactPHP and offers impressive performance - handling thousands of concurrent connections with minimal resources.
composer require laravel/reverb
php artisan reverb:install
npm install --save-dev laravel-echo pusher-js
# .env
BROADCAST_CONNECTION=reverb
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080
REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret
php artisan reverb:start
# With custom options
php artisan reverb:start --host=0.0.0.0 --port=9000
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewOrderNotification implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public string $message,
public int $orderId,
) {}
public function broadcastOn(): array
{
return [
new Channel('orders'),
];
}
public function broadcastAs(): string
{
return 'order.created';
}
}
event(new NewOrderNotification('New order received!', $order->id));
// Or dispatch to a private channel
broadcast(new NewOrderNotification('...', $order->id))->toOthers();
// routes/channels.php
use App\Models\User;
Broadcast::channel('user.{id}', function (User $user, int $id) {
return (int) $user->id === (int) $id;
});
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
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 ?? 8080,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
// Listen on a public channel
window.Echo.channel('orders')
.listen('.order.created', (e) => {
console.log('New order:', e.message);
// Update UI
});
// Listen on a private channel
window.Echo.private(`user.${userId}`)
.notification((notification) => {
// Handle broadcast notification
});
Combine broadcasting with Laravel's notification system:
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Notifications\Notification;
class OrderShipped extends Notification implements ShouldBroadcast
{
use Queueable;
public function __construct(public Order $order) {}
public function via($notifiable): array
{
return ['database', 'broadcast'];
}
public function toBroadcast($notifiable): array
{
return [
'order_id' => $this->order->id,
'status' => $this->order->status,
];
}
public function broadcastOn(): array
{
return [new PrivateChannel('orders.' . $this->order->user_id)];
}
}
Livewire makes building reactive interfaces incredibly simple. Here's a real-time order counter:
<?php
namespace App\Livewire;
use App\Models\Order;
use Livewire\Attributes\On;
use Livewire\Component;
class OrderCounter extends Component
{
public int $count = 0;
public function mount(): void
{
$this->count = Order::count();
}
#[On('echo:orders,order.created')]
public function increment(): void
{
$this->count = Order::count();
}
public function render()
{
return view('livewire.order-counter');
}
}
<div class="p-4 bg-white rounded shadow">
<h3>Total Orders</h3>
<p class="text-3xl font-bold">{{ $count }}</p>
</div>
// MessageSent event
class MessageSent implements ShouldBroadcast
{
public function __construct(
public string $message,
public string $user,
public int $roomId,
) {}
public function broadcastOn(): array
{
return [new PrivateChannel('chat.' . $this->roomId)];
}
}
// ChatComponent
class ChatComponent extends Component
{
public int $roomId;
public string $message = '';
public array $messages = [];
#[On('echo-private:chat.{roomId},message.sent')]
public function onMessage($payload): void
{
$this->messages[] = $payload;
}
public function send(): void
{
broadcast(new MessageSent($this->message, auth()->user()->name, $this->roomId));
$this->message = '';
}
public function render()
{
return view('livewire.chat-component');
}
}
Presence channels show who's currently online:
Broadcast::channel('presence.game.{gameId}', function ($user, $gameId) {
return $user->only(['id', 'name']);
});
window.Echo.join(`game.${gameId}`)
.here((users) => {
console.log('Online users:', users);
})
.joining((user) => {
console.log('User joined:', user.name);
})
.leaving((user) => {
console.log('User left:', user.name);
});
[program:reverb]
command=php /var/www/html/artisan reverb:start --host=0.0.0.0 --port=8080
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/reverb.log
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 60s;
}
}
With Laravel Reverb and Livewire, you can build production-grade real-time applications entirely in PHP. No Node.js servers required. Start with simple notifications, then graduate to chat, dashboards, and collaborative features. The stack scales beautifully and the developer experience is unmatched.
Your email address will not be published. Required fields are marked *