QuickstartLaravel + Echo

Laravel + Echo

Mawjly works with Laravel Echo + Laravel’s built-in pusher broadcast driver — zero changes to your Echo, broadcast events, or Broadcast::channel(...) definitions.

1. Install

composer require pusher/pusher-php-server
npm install --save-dev laravel-echo pusher-js

2. Configure broadcasting

In .env:

BROADCAST_CONNECTION=pusher

PUSHER_APP_ID=YOUR_APP_ID
PUSHER_APP_KEY=YOUR_APP_KEY
PUSHER_APP_SECRET=YOUR_APP_SECRET
PUSHER_APP_CLUSTER=sa

# These four are the only Mawjly-specific changes:
PUSHER_HOST=ws-sa.mawjly.com
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_USE_TLS=true

VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
VITE_PUSHER_HOST="${PUSHER_HOST}"

3. Wire Echo in your frontend

resources/js/echo.ts:

import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
 
window.Pusher = Pusher;
 
window.Echo = new Echo({
  broadcaster: 'pusher',
  key: import.meta.env.VITE_PUSHER_APP_KEY,
  cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
  wsHost: import.meta.env.VITE_PUSHER_HOST,
  wssPort: 443,
  forceTLS: true,
  enabledTransports: ['ws', 'wss'],
});

4. Listen for events

window.Echo.channel('chat').listen('MessageSent', (e) => {
  console.log(e.message);
});
 
// Private:
window.Echo.private(`user.${userId}`).listen('OrderShipped', (e) => {
  console.log(e.order);
});
 
// Presence:
window.Echo.join(`room.${roomId}`)
  .here((users) => console.log('initial members', users))
  .joining((user) => console.log('joined', user))
  .leaving((user) => console.log('left', user));

5. Broadcast from PHP

Define an event with ShouldBroadcast:

namespace App\Events;
 
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
 
class MessageSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets;
 
    public function __construct(public string $message) {}
 
    public function broadcastOn(): array
    {
        return [new Channel('chat')];
    }
}

Dispatch:

event(new MessageSent('Hello from Laravel!'));

That’s it.

Auth callback

Laravel auto-handles the /broadcasting/auth endpoint when you define your channels in routes/channels.php. No extra config needed for Mawjly — Laravel signs with your PUSHER_APP_SECRET, Sockudo verifies with the same secret it has on file.

// routes/channels.php
Broadcast::channel('user.{id}', function ($user, $id) {
    return $user->id === (int) $id;
});
 
Broadcast::channel('room.{id}', function ($user, $id) {
    return [
        'id' => $user->id,
        'name' => $user->name,
        'avatar' => $user->avatar_url,
    ];
});