April 03, 2026

Building Real-Time Collaborative Dashboards with Laravel Reverb and React

By Paresh Prajapati • Lead Architect

Building Real-Time Collaborative Dashboards with Laravel Reverb and React

The Problem: Stale Data in B2B Decision Making

In the high-stakes world of B2B SaaS and industrial management platforms, stale data is more than an inconvenience; it is a critical bottleneck. When multiple stakeholders are viewing the same analytical dashboard, decisions must be made based on live, concurrent state. If user A updates a critical inventory metric, user B must see that change reflected instantly without a manual page refresh. Traditional polling methods (repeatedly hitting an API endpoint) are resource-intensive, introduce unacceptable latency, and fail to scale under the load required by modern enterprise applications built at Smart Tech Devs.

The Solution: Event-Driven Real-Time Architecture

To build truly interactive, collaborative environments, we must shift from a Request/Response model to an Event-Driven model. In the Laravel ecosystem of 2026, this is achieved effortlessly using Laravel Reverb—a first-party, high-performance WebSocket server designed specifically for Laravel applications. When paired with a React frontend (integrated via Inertia.js or as a decoupled client), we create a seamless synchronization layer.

Architectural Breakdown

The workflow relies on four core components:

  1. The Backend Event: A standard Laravel event that implements the ShouldBroadcast interface.
  2. The Broadcasting Driver (Reverb): The WebSocket server that accepts the event and broadcasts the payload to connected clients.
  3. Presence Channels: Specific WebSocket channels that allow us to track not just data changes, but also *who* is currently viewing or interacting with a component (creating a "Google Docs" type awareness).
  4. The Frontend Listener (React Echo): A React hook using Laravel Echo to subscribe to channels and update the component state dynamically when an event is received.

Comprehensive Code Implementation Guide

Step 1: Laravel Event Configuration ( `app/Events/InventoryUpdated.php` )

Our backend event handles the payload and defines the secure channel.


namespace App\Events;

use App\Models\Inventory;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel; // For user awareness
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class InventoryUpdated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $inventory;
    public $userId;

    /**
     * Create a new event instance.
     */
    public function __construct(Inventory $inventory, $userId)
    {
        $this->inventory = $inventory;
        $this->userId = $userId; // Pass who made the change
    }

    /**
     * Get the channels the event should broadcast on.
     */
    public function broadcastOn(): array
    {
        // Use a presence channel for the specific warehouse dashboard
        return [
            new PresenceChannel('warehouse.' . $this->inventory->warehouse_id),
        ];
    }

    /**
     * Custom payload to send to the frontend.
     */
    public function broadcastWith(): array
    {
        return [
            'id' => $this->inventory->id,
            'stock_level' => $this->inventory->stock_level,
            'updated_by' => $this->userId,
        ];
    }
}

Step 2: Backend Trigger (A Service or Controller)

When the inventory model is updated, we dispatch the broadcast event.


// Inside app/Services/InventoryService.php

public function updateStockLevel(Inventory $inventory, int $newLevel)
{
    // 1. Perform complex validation and update logic...
    $inventory->update(['stock_level' => $newLevel]);

    // 2. Dispatch the real-time broadcast
    // Pass the user ID making the change for frontend awareness
    event(new InventoryUpdated($inventory, auth()->id()));
}

Step 3: React Frontend Hook ( `hooks/useInventoryRealtime.js` )

This hook manages the WebSocket connection, subscribes to the channel, and provides user presence data to the component.


import { useEffect, useState } from 'react';
import Echo from 'laravel-echo';
import Pusher from 'pusher-js'; // Echo requires a Pusher-compatible client

// Ensure Echo is initialized globally or inside a provider
window.Pusher = Pusher;
const echoInstance = new Echo({
    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: false, // For local or internal network development
    enabledTransports: ['ws', 'wss'],
});

export const useInventoryRealtime = (warehouseId) => {
    const [liveInventory, setLiveInventory] = useState([]);
    const [activeUsers, setActiveUsers] = useState([]);

    useEffect(() => {
        if (!warehouseId) return;

        // 1. Subscribe to the secure Presence Channel
        const channel = echoInstance.join(`warehouse.${warehouseId}`)
            // Track who is already here
            .here((users) => {
                setActiveUsers(users);
            })
            // Track when a new stakeholder joins
            .joining((user) => {
                setActiveUsers((prev) => [...prev, user]);
                console.log(`${user.name} joined the dashboard.`);
            })
            // Track when a stakeholder leaves
            .leaving((user) => {
                setActiveUsers((prev) => prev.filter(u => u.id !== user.id));
            })
            // 2. Listen for the InventoryUpdated event payload
            .listen('.InventoryUpdated', (eventPayload) => {
                console.log('Real-time stock update received:', eventPayload);
                // Update the local state instantly without a refresh
                setLiveInventory((prev) => 
                    prev.map(item => item.id === eventPayload.id ? { ...item, stock_level: eventPayload.stock_level } : item)
                );
            });

        // 3. Cleanup connection on component unmount
        return () => {
            echoInstance.leave(`warehouse.${warehouseId}`);
        };
    }, [warehouseId]);

    // Initial data loading would typically happen via Inertia or useQuery,
    // and setLiveInventory would be initialized there.

    return { liveInventory, setLiveInventory, activeUsers };
};

Deeper Technical Benefits

By shifting to Laravel Reverb and React for real-time synchronization, we achieve several major advantages crucial for durable B2B products:

  1. Enterprise-Grade UX: Instant data consistency across all stakeholders builds massive user trust in your platform's reliability.
  2. Highly Optimized Server Resources: Unlike continuous polling, WebSockets use a single persistent connection per client. This dramatically reduces backend API overhead and database query load, allowing you to serve thousands of concurrent B2B users on modest infrastructure.
  3. Presence Awareness: Knowing which stakeholders are currently "active" on a dashboard prevents collision errors (e.g., two admins editing the same client record simultaneously) and facilitates seamless collaboration workflows.

Conclusion

The shift from static data presentation to dynamic, event-driven collaboration is a defining requirement for any modern B2B SaaS platform. Leveraging Laravel Reverb provides a robust, native infrastructure layer that, when paired with the reactive state management of React, allows Smart Tech Devs to build world-class collaborative experiences that scale.

Paresh Prajapati
Lead Architect, Smart Tech Devs