Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Brain Socket Laravel Package

brainboxlabs/brain-socket

BrainSocket adds real-time WebSockets to Laravel apps. Run a dedicated socket server, broadcast server-side events to connected clients, and handle client messages through a simple Laravel-friendly API—ideal for live notifications, chat, and dashboards without a third-party service.

View on GitHub
Deep Wiki
Context7

Getting Started

Brain Socket wires three pieces together: a Laravel package that publishes messages to Redis, a standalone socket server (Node/socket.io) that subscribes to Redis and fans messages out to browsers, and a small JS client that subscribes to named events. To get moving:

  1. Install and register. composer require brainboxlabs/brain-socket, then add the service provider to config/app.php and the BrainSocket alias. Publish the config (php artisan config:publish brainboxlabs/brain-socket on Laravel 4, vendor:publish on 5.x) so you have brain-socket.php with the Redis host/port, the socket port, and the app key.
  2. Start the server. The package ships a socket server you run as its own process (Supervisor in anything real), typically on port 8080, pointed at the same Redis instance the app uses. Nothing works until this process is up — a huge share of "it's broken" reports are just a dead server.
  3. Send your first message. In a controller or tinker session, BrainSocket::message('user-created', ['id' => $user->id, 'name' => $user->name]);. Confirm it lands by watching redis-cli MONITOR and the server's stdout simultaneously.
  4. Subscribe in the browser. Include socket.io's client and the package's brain-socket.js, connect to ws://host:8080 with your app key, and register a handler for user-created. Log the payload to the console before you try to render anything.

Where to look first: the published config file (it's the whole contract), the server/ directory in the package (it is your real runtime and you will end up reading it), the shipped JS client (to see the exact event envelope), and the README's example for the socket server invocation. Your first real use case should be a single one-way broadcast — "a record was created, refresh the list" — not bidirectional chat. Prove the pipe before you build on it.

Implementation Patterns

Bridge Laravel events to the socket, don't call the facade from controllers. This is the pattern that keeps the package from metastasizing through your codebase:

// app/Listeners/BroadcastUserCreated.php
public function handle(UserCreated $event)
{
    BrainSocket::message('user.created', [
        'id'   => $event->user->id,
        'name' => $event->user->name,
    ]);
}

Register the listener on the event and fire event(new UserCreated($user)) from wherever the domain change happens. Swapping transports later (see Gotchas) becomes a one-file change instead of a grep across controllers.

Two naming layers, kept separate. Use dotted, versioned event names (order.shipped.v1) for the socket payload, and let Laravel event class names stay internal. Do not derive one from the other at runtime via get_class() — the FQCN leaks your namespace to the browser and makes renames a breaking change for JS you don't control.

Channel/room scoping for anything user-specific. Broadcast notifications to a per-user channel rather than a global event and filtering client-side. The socket server forwards whatever Redis gives it; a global channel means every connected browser receives every user's payload, which is a data leak, not just noise.

Client-side wrapper, one file. Wrap the raw client in a small module so views never touch the socket object directly:

window.Brain = (function (socket) {
  return {
    on: function (name, fn) { socket.on(name, function (msg) { fn(msg.data || msg); }); },
    connected: false
  };
})(new BrainSocket(...));

Brain.on('user.created', function (u) { /* update row, no page reload */ });

Give the wrapper reconnect/re-subscribe logic. Raw socket.io reconnects will silently drop your handlers if you register them in a .one()-style pattern.

Queue the broadcast. Redis publish is fast but the socket server is a separate failure domain; putting BrainSocket::message() behind ShouldQueue on the listener keeps a dead socket server from throwing inside a web request and rolling back a user's action. It also lets you back-pressure a busy event.

Presence and "live dashboard" use cases want a snapshot-then-stream contract: fetch current state over HTTP on connect, then apply socket deltas. Do not attempt to reconstruct state from a stream of events you started listening to mid-flight.

Integration tip: keep payloads to flat JSON under ~10KB. Eloquent models serialize with relations and hidden fields; always send an explicit ->only([...]) array so you're not leaking password or remember_token through a websocket.

Gotchas and Tips

This package is archived — treat it as a fixed dependency. Pin the exact version in composer.json, and copy the socket server into your repo rather than referencing vendor/ at runtime, because the server is executed, not autoloaded. Have an exit plan: Laravel Reverb or Soketi with Laravel Echo covers the same ground with maintained code, and the bridge-listener pattern above means you migrate by rewriting one listener and one JS module.

socket.io client/server version mismatch is the single most common failure. The shipped server is pinned to an old socket.io major. A CDN client at a newer major will connect and then silently never receive events. Serve the client from the server's own /socket.io/socket.io.js endpoint, or hard-pin the CDN version to match the server's package.json.

Config changes need a server restart, not a cache clear. php artisan config:cache bakes env values at deploy time; the Node server reads its own config file independently. Two sources of truth for the Redis host is the classic "works locally, connects to nothing in staging" bug. Log the resolved Redis host and port at server startup.

Debug in this order: (1) redis-cli MONITOR — is the message leaving Laravel at all? (2) server stdout — did it receive the Redis message? (3) browser devtools → WS frames — did it reach the client? Each stage failing points at a different component, and skipping to step 3 wastes hours.

Redis database index and key prefix. If Laravel publishes to db 0 with a prefix and the server subscribes on db 1 without it, everything looks healthy and nothing arrives. Set the db explicitly on both sides.

Nginx will drop idle WebSockets. Add the Upgrade/Connection proxy headers, raise proxy_read_timeout past your longest idle period, and use wss:// from an HTTPS page — a mixed-content block looks identical to a connection failure in some browsers' consoles.

The app key is not authentication. It's a shared secret in client-visible JavaScript. Never let a client-originated message trigger server-side work without re-validating the session; if the package allows inbound events, assume anyone can forge them.

Emit from the socket server, not the browser, for anything authoritative. Anything the browser sends should be treated as a hint and confirmed against Laravel before other clients see it.

Scaling past one process requires the socket.io Redis adapter so multiple server instances fan out to their own connected clients; without it, half your users are on the wrong instance and simply never see updates.

Extension points: the Redis channel is the seam. You can publish from a non-Laravel service by matching the envelope, or replace the JS client entirely with raw socket.io — the server doesn't care who subscribes. The server process itself is the other seam; if you need TLS termination, auth handshakes, or rooms, doing it in the Node process is far easier than fighting the PHP package.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums