Loading...

This is taking longer than expected.

Back to the help centre

Real time with Reverb

Switch on the optional WebSocket server so add-on payments and the notification bell update on their own, locally and on a Ploi server.

The kit ships with real time switched off. With it off, everything works as it always has: the add-on screens ask the server every few seconds while a payment is waiting, and the notification bell shows what there was when the page loaded. Switch it on and two things react within a second, with no polling:

Screen With real time off With real time on
Add-on catalogue and add-on detail, after paying Polls every 3 seconds (catalogue) or 5 seconds (detail) until Stripe confirms the payment No polling. Every Stripe webhook about the account tells its open billing screens to check, and the confirmation shows as soon as the webhook lands
Notification bell in the top bar Counter and list are loaded with the page A new notification updates the counter and the list in every open tab of the person it was sent to, and only of that person

The decision is the application's, not each screen's: real time is on when BROADCAST_CONNECTION is reverb, and off with any other value. There is no fallback: if Reverb is on and its server is down, nothing breaks, the screens simply stop updating on their own until it is back (a payment is still confirmed; the person sees it on reload).

Reverb is a process of its own that runs on the same server as the application, so it shares that server's memory and processor. It is light, but it is one more thing to keep alive, which is why the kit leaves the choice to each product.

What is involved

  • Server side. laravel/reverb is the WebSocket server. Broadcasting is immediate (ShouldBroadcastNow), so it does not need the queue worker.
  • Browser side. laravel-echo and pusher-js are bundled in resources/js/bootstrap.js. The layout only hands the browser the connection settings when the person is signed in and real time is on, so a visitor without a session, or any page with real time off, never opens a connection.
  • Channels. Two private channels, both authorised at POST /broadcasting/auth: App.Models.User.{id} (only that user, declared in routes/channels.php) carries notification.received; billing-account.{id} (only someone who can manage that billing account, declared by Billing Core) carries billing-account.updated.

Try it locally

  1. Make sure the dependencies are installed: composer install and npm install (laravel/reverb, laravel-echo and pusher-js come with the kit).

  2. Add to your local .env. The three app values are any random strings you choose; php -r "echo bin2hex(random_bytes(16));" makes one.

    BROADCAST_CONNECTION=reverb
    REVERB_APP_ID=local
    REVERB_APP_KEY=a-random-string
    REVERB_APP_SECRET=another-random-string
    REVERB_HOST=weblabor-base.test
    REVERB_PORT=8080
    REVERB_SCHEME=https
    

    Use your own site name in REVERB_HOST. Do not run php artisan reverb:install or php artisan install:broadcasting: the kit is already wired, and both commands rewrite files it owns.

  3. Start the server, naming the secured Herd or Valet site so Reverb serves TLS with its certificate (an https page cannot open a plain ws:// connection):

    php artisan reverb:start --hostname=weblabor-base.test --debug
    
  4. php artisan config:clear, then npm run dev (or npm run build) and reload the page. With --debug the terminal prints each connection and each message.

  5. Check both cases. Buy an add-on with a Stripe test card and the confirmation appears as soon as the webhook arrives (forward webhooks with stripe listen locally), with no checkSubscriptionStatus or checkPending requests repeating in the network tab. Then make a notification reach someone, for example answer their ticket from another account, and their bell changes without a reload while another signed-in person's does not.

Switch it on or off

On: set BROADCAST_CONNECTION=reverb with the REVERB_* values, start the Reverb process, and run php artisan config:clear (or php artisan optimize if you cache the configuration). Off: set BROADCAST_CONNECTION=null (or remove it, null is the default), run the same command, and stop the process. Nothing needs rebuilding: the browser reads the settings from the page, not from the bundle.

Deploy it on Ploi

Ploi keeps processes alive with Supervisor and serves the site with Nginx. It can run Reverb for you, but it does not write the Nginx block that forwards the WebSocket traffic: that part is yours.

  1. Supervisor. Reverb runs as a Ploi daemon, and daemons run under Supervisor, so Supervisor has to be installed and running on the server. A server that already runs the queue worker as a Ploi daemon has it; on a new one, check it among the server's services before adding the daemon.

  2. The Reverb process. In the server's Daemons, add one:

    Field Value
    Command php /home/ploi/your-domain.com/artisan reverb:start --host=127.0.0.1 --port=8080
    User ploi
    Processes 1

    It listens only on the server itself, port 8080; Nginx is the only thing that reaches it.

  3. Nginx. In the site's Manage, open the Nginx configuration and add, inside the server block that listens on 443, the two routes Reverb uses: /app for the browsers' WebSocket connections and /apps for the application publishing events.

    location /app {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://127.0.0.1:8080;
    }
    
    location /apps {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://127.0.0.1:8080;
    }
    

    Save it; Ploi tests and reloads Nginx.

  4. Environment. In the site's environment, with your own random values:

    BROADCAST_CONNECTION=reverb
    REVERB_APP_ID=your-app-id
    REVERB_APP_KEY=your-app-key
    REVERB_APP_SECRET=your-app-secret
    REVERB_HOST=your-domain.com
    REVERB_PORT=443
    REVERB_SCHEME=https
    

    REVERB_HOST, REVERB_PORT and REVERB_SCHEME are the public address, the one Nginx answers on, used both by the browsers and by the application to publish. The process itself keeps listening on 127.0.0.1:8080.

  5. Deploy script. The usual commands already rebuild the application's assets (npm ci and npm run build), which is what bundles Echo; keep them. Add, after php artisan queue:restart:

    php artisan reverb:restart
    

    Like the queue worker, Reverb keeps the code it started with in memory, and this is what makes Supervisor start it again with the new release.

The Ploi steps are documented here but not tested by the kit. After the first deploy, open a page signed in and check in the browser's network tab that the connection to wss://your-domain.com/app/... opens with status 101.