ChatifyPHP

Broadcasting

Set up Pusher, Laravel Reverb, or another WebSocket server for real-time messaging

Chatify uses Laravel Broadcasting to deliver real-time events to connected clients. You need a working WebSocket server for typing indicators, new messages, read receipts, and presence updates.

How it works

  1. A server-side action (sending a message, reading a conversation, etc.) dispatches a broadcast event
  2. The event is sent to the broadcasting driver (Pusher, Reverb, etc.)
  3. The frontend listens on the appropriate channel via Laravel Echo
  4. The UI updates in real time

Pusher

Pusher is a hosted WebSocket service. It is the easiest option to get started.

1. Install the PHP SDK

composer require pusher/pusher-php-server

2. Configure .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=mt1

3. Enable client events

In your Pusher dashboard, go to App Settings and enable Client Events. Chatify uses client events for typing indicators.

4. Verify

Start your Laravel app and open the messenger. Messages should appear in real time across multiple browser tabs.

Laravel Reverb

Laravel Reverb is a first-party, self-hosted WebSocket server included with Laravel.

1. Install Reverb

php artisan install:broadcasting

This installs the laravel/reverb package and publishes the config.

2. Configure .env

BROADCAST_CONNECTION=reverb

REVERB_APP_ID=your-app-id
REVERB_APP_KEY=your-app-key
REVERB_APP_SECRET=your-app-secret
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http

PUSHER_APP_KEY="${REVERB_APP_KEY}"
PUSHER_HOST="${REVERB_HOST}"
PUSHER_PORT="${REVERB_PORT}"
PUSHER_APP_USETLS=false

Chatify's frontend reads the PUSHER_* env vars for its Echo connection. When using Reverb, map them to the Reverb values as shown above.

3. Start the Reverb server

php artisan reverb:start

For production, run Reverb behind a reverse proxy (Nginx/Caddy) with TLS:

REVERB_SCHEME=https
REVERB_PORT=443
PUSHER_APP_USETLS=true

Other WebSocket servers

Any WebSocket server that implements the Pusher protocol works with Chatify. For example, beyondcode/laravel-websockets:

Configuration pattern

BROADCAST_CONNECTION=pusher

PUSHER_APP_ID=local
PUSHER_APP_KEY=local
PUSHER_APP_SECRET=local
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_APP_USETLS=false

Set PUSHER_HOST and PUSHER_PORT to your WebSocket server's address, and set PUSHER_APP_USETLS=false for local development.

Broadcast channels

Chatify registers two private broadcast channels:

Conversation channel

private-chatify.conversation.{conversationId}

Used for events scoped to a conversation:

  • MessageSent
  • MessageUpdated
  • MessageDeleted
  • ConversationRead
  • UserTyping
  • GroupParticipantsChanged

User channel

private-chatify.user.{userId}

Used for events targeted at a specific user:

  • ConversationInboxUpdated (alias: InboxUpdated)
  • UserPresenceChanged
  • UserBlockChanged
  • GroupMembershipRevoked

Channel authorization

Chatify publishes a routes/chatify/channels.php file that defines the authorization logic:

Broadcast::channel('chatify.conversation.{conversationId}', function ($user, string $conversationId) {
    return ConversationParticipant::query()
        ->where('conversation_id', $conversationId)
        ->where('user_id', $user->getKey())
        ->exists();
});

Broadcast::channel('chatify.user.{userId}', function ($user, int|string $userId) {
    return (int) $user->getKey() === (int) $userId;
});

A user can only listen to conversation channels they participate in, and user channels that match their own ID.

Broadcasting auth endpoint

Chatify includes its own broadcasting auth endpoint for the frontend:

POST /api/chatify/v1/broadcasting/auth

This handles channel authorization using the same middleware as the rest of the API.

Frontend Echo connection

The bundled UI automatically configures Laravel Echo using the boot data injected into the page. The connection settings come from config/chatify.php:

'frontend' => [
    'broadcast' => [
        'driver'   => env('CHATIFY_BROADCAST_DRIVER', env('BROADCAST_CONNECTION', 'null')),
        'key'      => env('PUSHER_APP_KEY'),
        'cluster'  => env('PUSHER_APP_CLUSTER', 'mt1'),
        'wsHost'   => env('PUSHER_HOST'),
        'wsPort'   => (int) env('PUSHER_PORT', 443),
        'forceTLS' => env('PUSHER_APP_USETLS', true),
    ],
],

If you are building a custom frontend, use these values to configure your own Echo instance.

Troubleshooting

SymptomLikely cause
Messages send but don't appear in real timeBroadcasting driver not configured, or WebSocket server not running
403 on channel authUser is not a participant, or auth middleware mismatch
Typing indicators don't workClient events not enabled in Pusher dashboard
Connection refusedWrong PUSHER_HOST / PUSHER_PORT, or WebSocket server is down
Works locally but not in productionMissing TLS. Set PUSHER_APP_USETLS=true and PUSHER_PORT=443

On this page