websockets-grid-demo

6
3
6
TypeScript
public

๐ŸŽจ Laravel Reverb Grid - Real-Time Collaborative Demo

A modern, real-time collaborative emoji grid showcasing Laravel 12, React 19, Inertia.js, and Laravel Reverb broadcasting capabilities. This demo demonstrates best practices for building real-time collaborative applications with Laravel.

โ˜๏ธ Laravel Cloud Deployment

This application is designed to be deployed on Laravel Cloud. Youโ€™ll need to provision:

  • ๐Ÿ—„๏ธ Database - Required for sessions, cache table, and avoiding log errors (even though grid data uses cache)
  • ๐Ÿ’พ Cache - Required for grid state, user presence tracking, and session storage
  • โšก Queue (or Queue Cluster) - Required for background job processing and scheduled tasks
  • ๐ŸŒ WebSockets (Laravel Reverb) - Required for real-time broadcasting functionality

Note: While the grid itself uses cache storage, a database is still required to prevent errors in Laravelโ€™s session and cache drivers. The database cache driver writes to a cache table created by migrations.

โœจ Features

  • ๐ŸŽฏ 10ร—10 Interactive Grid - Click cells to level up emojis through 5 stages
  • ๐Ÿ‘ฅ Live User Count - See how many artisans are online in real-time
  • โšก Real-Time Sync - Instant updates via WebSockets with optimistic UI
  • ๐ŸŽญ Progressive Emoji Levels - โค๏ธ โ†’ ๐Ÿš€ โ†’ ๐Ÿคฏ โ†’ ๐Ÿ”ฅ โ†’ Secret Emoji
  • ๐ŸŒง๏ธ Emoji Rain - Fill the entire grid with one emoji to trigger a celebration
  • ๐Ÿ’พ Persistent State - Grid state and click counts survive page refreshes
  • ๐Ÿ”“ Public Access - No authentication required for demo purposes
  • ๐Ÿ“ก Optimized Broadcasting - Uses toOthers() to prevent duplicate updates

๐Ÿ—๏ธ Architecture

Browser โ†’ React Component โ†’ Axios โ†’ Laravel Controller โ†’
Cache Update โ†’ Event Dispatch โ†’ Reverb WebSocket โ†’
All Other Browsers (Echo) โ†’ UI Update

Key Broadcasting Patterns:

  • Optimistic UI Updates - Immediate local state changes before server confirmation
  • toOthers() Pattern - Broadcasts exclude the originating user
  • Axios + Socket ID - Automatic X-Socket-ID header for proper toOthers() behavior
  • Presence Tracking - Session-based user tracking with automatic cleanup

๐Ÿ“‹ Requirements

Local Development:

  • PHP 8.4+
  • Node.js 18+
  • Composer & npm
  • Laravel 12
  • SQLite (or MySQL/PostgreSQL)

Production (Laravel Cloud):

  • Database (MySQL/PostgreSQL recommended)
  • Cache service
  • Queue or Queue Cluster
  • WebSockets (Laravel Reverb)

๐Ÿš€ Quick Start

1. Install Dependencies

composer install
npm install

2. Environment Setup

cp .env.example .env
php artisan key:generate

3. Run Migrations

php artisan migrate

4. Start Development Servers

Option A: One Command (Recommended)

composer run dev

This starts:

Option B: Manual Start (3 terminals)

# Terminal 1: Laravel
php artisan serve

# Terminal 2: Vite
npm run dev

# Terminal 3: Reverb
php artisan reverb:start

5. Open Application

Visit http://localhost:8000 (or the port shown in your terminal)

๐ŸŽฎ How to Use

  1. Click any cell to place an emoji (starts at โค๏ธ level 1)
  2. Keep clicking the same cell to level it up:
    • 1 click: โค๏ธ
    • 10 clicks: ๐Ÿš€
    • 50 clicks: ๐Ÿคฏ
    • 100 clicks: ๐Ÿ”ฅ
    • 500 clicks: Special Emoij ๐Ÿ‘€
  3. Watch the counter in the center 2ร—2 area to see live user count
  4. Open multiple tabs to see real-time collaboration
  5. Fill the entire grid with one emoji type to trigger emoji rain! ๐ŸŒง๏ธ

๐Ÿ“ Project Structure

app/
โ”œโ”€โ”€ Broadcasting/
โ”‚   โ””โ”€โ”€ GridPresence.php           # Presence channel authorization
โ”œโ”€โ”€ Events/
โ”‚   โ”œโ”€โ”€ GridCellClicked.php        # Shake animation event
โ”‚   โ”œโ”€โ”€ GridCellUpdated.php        # Cell emoji update event
โ”‚   โ”œโ”€โ”€ GridRainStarted.php        # Celebration rain event
โ”‚   โ””โ”€โ”€ UserCountUpdated.php       # Active user count event
โ”œโ”€โ”€ Http/
โ”‚   โ”œโ”€โ”€ Controllers/
โ”‚   โ”‚   โ””โ”€โ”€ GridController.php     # Main grid logic
โ”‚   โ””โ”€โ”€ Middleware/
โ”‚       โ””โ”€โ”€ TrackActiveUsers.php   # Session-based user tracking
โ””โ”€โ”€ Services/
    โ””โ”€โ”€ UserPresenceService.php    # User presence management

resources/
โ”œโ”€โ”€ js/
โ”‚   โ”œโ”€โ”€ app.tsx                    # Axios + Echo configuration
โ”‚   โ””โ”€โ”€ pages/
โ”‚       โ””โ”€โ”€ Grid.tsx               # React grid component
โ””โ”€โ”€ css/
    โ””โ”€โ”€ app.css                    # Tailwind styling

routes/
โ”œโ”€โ”€ web.php                        # Web routes
โ””โ”€โ”€ channels.php                   # Broadcasting channel definitions

๐Ÿ”‘ Key Implementation Details

1. Axios Configuration with Echo (resources/js/app.tsx)

// Automatically attach Socket ID to Axios requests
axios.interceptors.request.use((config) => {
    if (window.Echo && typeof window.Echo.socketId === 'function') {
        config.headers['X-Socket-ID'] = window.Echo.socketId();
    }
    return config;
});

2. Broadcasting with toOthers() (app/Http/Controllers/GridController.php)

// Broadcast to everyone except the person who clicked
broadcast(new GridCellUpdated([...]))->toOthers();
broadcast(new GridCellClicked(...))->toOthers();

3. Optimistic UI Updates (resources/js/pages/Grid.tsx)

// Update local state immediately for instant feedback
setCells((prev) => ({ ...prev, [position]: newEmoji }));

// Then send to server
await axios.put(`/grid/${position}`, { click: true });

4. User Presence Tracking

  • Session-based: Each user gets a unique UUID stored in session
  • Cache storage: Active users stored in cache with timestamps
  • Automatic cleanup: Scheduled task removes inactive users every minute
  • Real-time updates: Broadcasts user count changes to all clients

๐Ÿ“Š Event Flow Diagram

User Clicks Cell
    โ†“
1. Optimistic UI Update (instant)
    โ†“
2. Axios PUT with X-Socket-ID header
    โ†“
3. Laravel updates cache + click count
    โ†“
4. Broadcast GridCellUpdated โ†’toOthers()
    โ†“
5. Broadcast GridCellClicked โ†’toOthers()
    โ†“
6. Check if grid is uniform (rain trigger)
    โ†“
7. Other browsers receive via WebSocket
    โ†“
8. React updates with animations

๐Ÿ”ง Configuration

Environment Variables (.env)

BROADCAST_CONNECTION=reverb
REVERB_APP_ID=your-app-id
REVERB_APP_KEY=your-app-key
REVERB_APP_SECRET=your-app-secret
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}"

Broadcasting Configuration (config/broadcasting.php)

Already configured for Reverb! No changes needed.

๐Ÿงช Testing Real-Time Features

Test 1: Multi-Client Sync

# Open app in 2 browser tabs
# Click a cell in tab 1
# Should appear instantly in tab 2 with animations

Test 2: User Count Updates

# Open app in multiple tabs/browsers
# Watch center display update with "X artisans online"
# Close tabs and see count decrease after ~5 minutes

Test 3: Emoji Rain

# Click all 96 clickable cells (excluding center 4) to the same emoji
# Watch the emoji rain celebration trigger!

Test 4: Persistence

# Click various cells to add emojis
# Refresh the page
# All emojis and click counts should persist

Clear Grid Data

php artisan cache:clear
# or
php artisan tinker
>>> Cache::forget('emoji_grid')
>>> Cache::forget('emoji_grid_click_counts')
>>> Cache::forget('emoji_grid_timestamps')
>>> Cache::forget('active_users')

๐Ÿ› Troubleshooting

Problem Solution
Emojis not persisting Run php artisan migrate for cache table
Real-time not working Verify php artisan reverb:start is running
User count not updating Check middleware is registered in bootstrap/app.php
Animations feel delayed Ensure toOthers() is used in broadcasts
WebSocket connection fails Check BROADCAST_CONNECTION=reverb in .env
Axios errors Verify CSRF token meta tag in app.blade.php
Log errors (no database) Database is required even with cache - run migrations

Why Database is Required:

Even though the grid uses cache for storage, Laravel requires a database for:

  • Session management (database driver)
  • Cache table (database cache driver uses this)
  • Queue table (for job tracking)
  • Migrations table (Laravelโ€™s migration tracking)

Without a database, you may see errors in logs related to sessions and cache operations, even if the application appears to work correctly.

๐ŸŽฏ Best Practices Demonstrated

1. Inertia.js Props

  • โœ… Pass initial data via props (no separate API call on load)
  • โœ… Keep routes in web.php (not api.php)

2. Broadcasting

  • โœ… Use toOthers() to prevent duplicate updates
  • โœ… Axios with automatic X-Socket-ID header
  • โœ… Optimistic UI updates for instant feedback

3. User Presence

  • โœ… Session-based tracking (no database needed)
  • โœ… Cache storage for performance
  • โœ… Scheduled cleanup of inactive users

4. Code Quality

  • โœ… Laravel Pint for consistent formatting
  • โœ… TypeScript for type safety
  • โœ… Service classes for business logic

๐Ÿ“ˆ Performance

  • Grid Load: ~50ms (cache read)
  • Update Latency: ~20-30ms end-to-end
  • Memory: ~50MB (React + Echo)
  • WebSocket: ~1KB per message
  • Clickable Cells: 96 (10ร—10 grid minus center 4)

๐Ÿ” Security

  • โœ… CSRF protection on all mutations
  • โœ… Axios automatic CSRF token handling
  • โœ… Click count validation
  • โœ… Position validation (0-99)
  • โœ… No authentication (public demo)
  • โœ… Cache-based storage (no SQL injection risk)

๐Ÿ“š Laravel Versions

  • Laravel Framework: 12.x
  • Laravel Reverb: 1.x
  • Inertia.js: 2.x
  • Laravel Echo: 2.x
  • React: 19.x
  • Tailwind CSS: 4.x

๐ŸŽ“ Learning Resources

This demo is perfect for learning:

  • Real-time Laravel features with Reverb
  • Broadcasting patterns with toOthers()
  • Optimistic UI updates in React
  • Inertia.js best practices for SPAs
  • WebSocket implementation with Echo
  • User presence tracking without authentication
  • Axios integration with Laravel Echo

๐Ÿ“– Further Reading

๐Ÿ“„ License

MIT

๐Ÿ‘ค Author

Built as a comprehensive demo for Laravel Reverb WebSocket broadcasting with Inertia.js and React.


Status: โœ… Production Ready
Last Updated: November 2, 2025
Framework Versions: Laravel 12, React 19, Inertia 2, Reverb 1

Happy coding! ๐Ÿš€

v0.3.3[beta]