# Laravel Reverb Setup Guide

GLETRA uses **Laravel Reverb** as the self-hosted WebSocket server for real-time chat, typing indicators, presence, and WebRTC call signaling.

## Overview

```
┌─────────┐    WebSocket (Pusher protocol)    ┌──────────────┐
│ Browser │ ◄──────────────────────────────► │ Laravel Reverb│
│  Echo   │                                   │  (port 8080)  │
└─────────┘                                   └──────┬───────┘
                                                     │
                                              Laravel Events
                                              (MessageSent,
                                               CallSignaling, etc.)
```

**No Pusher, Ably, Firebase, or third-party realtime services required.**

## Environment configuration

`.env`:

```env
BROADCAST_CONNECTION=reverb

REVERB_APP_ID=123456
REVERB_APP_KEY=basekey
REVERB_APP_SECRET=secretkey
REVERB_HOST=127.0.0.1
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
VITE_REVERB_ENABLED=true
```

Production with HTTPS:

```env
REVERB_HOST=yourdomain.com
REVERB_PORT=443
REVERB_SCHEME=https
```

After changing `VITE_*` variables, run `npm run build`.

## Start Reverb

Development:

```bash
php artisan reverb:start
```

Production (Supervisor):

```ini
[program:gletra-reverb]
command=php /var/www/gletra/artisan reverb:start
autostart=true
autorestart=true
```

Options:

```bash
php artisan reverb:start --host=0.0.0.0 --port=8080 --debug
```

## Broadcast channels

Defined in `routes/channels.php`:

| Channel | Purpose |
|---------|---------|
| `chat.{conversationId}` | Message delivery, reactions |
| `user.{userId}` | Incoming calls, personal events |
| `online.{userId}` | Presence / last seen |
| `call.{callId}` | WebRTC signaling (offer/answer/ICE) |
| `group.{groupId}` | Group message events |

## Events broadcast

- **Chat:** `MessageSent`, `MessageSeen`, `MessageDeleted`, `MessageReactionUpdated`, `TypingStatus`, `ChatListUpdated`, `UserPresenceUpdated`
- **Calls:** `CallIncoming`, `CallAccepted`, `CallRejected`, `CallEnded`, `CallSignaling`, `CallStatusChanged`
- **Groups:** `GroupMessageSent`
- **Status:** `StatusPosted`, `StatusViewed`

All events use `SafeBroadcast` wrapper for graceful failure if Reverb is down (polling fallback active for messages).

## Nginx WebSocket proxy

```nginx
location /app {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
    proxy_pass http://127.0.0.1:8080;
}
```

## Client configuration

`resources/js/echo.js` initializes Laravel Echo with Reverb:

```javascript
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT,
forceTLS: import.meta.env.VITE_REVERB_SCHEME === 'https',
```

## Authentication

Private channels require authenticated users. Broadcasting routes use web session + Sanctum auth via `bootstrap/app.php` `withBroadcasting()`.

## Scaling (optional)

For high traffic:

1. Use Redis as Reverb scaling backend (see Laravel Reverb docs)
2. Run multiple Reverb instances behind a load balancer with sticky sessions
3. Keep queue workers running for push notifications and media jobs

## Troubleshooting

| Symptom | Check |
|---------|-------|
| Messages only via polling | Reverb not running; check `BROADCAST_CONNECTION=reverb` |
| Echo connection error in console | Wrong `VITE_REVERB_*`; rebuild assets |
| Calls connect but no signaling | User subscribed to `call.{id}` channel; check auth |
| 403 on `/broadcasting/auth` | User not logged in; CSRF token missing |
| Works locally, fails in prod | HTTPS/WSS required; proxy `/app` to Reverb |

## Verify connection

Open browser DevTools → Network → WS. You should see a WebSocket connection to `/app/{key}` with status 101 Switching Protocols.

In Laravel log (with debug):

```bash
php artisan reverb:start --debug
```

You should see client connect/disconnect events when opening the chat page.
