Live WebSockets Demo

Real-time chat and a streaming local LLM, over WebSockets.

Messages appear the instant they are sent, presence shows who is online, and a small language model running on the server streams its replies into the chat token by token. Built on Laravel 12 and Reverb.

The first two need no sign-in. Sign in for the full app: pick who you are and message anyone, including the AI.

Try it live, in two windows

The chat is multi-user, so it is best seen with two people signed in at once.

  1. Open the chat and sign in as Demo User.
  2. Open a private / incognito window (or a different browser) and sign in as one of the people on the right.
    A normal second window shares your session, so the second person needs a separate private window.
  3. In both windows, open the conversation with the other person, send a message, and watch it arrive instantly, with no refresh.
  4. Or open the AI Chatbot contact and watch a local model stream its reply token by token.
Sign-inpassword: password
  • Demo User demo@example.com talks to everyone
  • Adison Lee adison@example.com
  • Lisa Lamar lisa@example.com
  • Troy Norman troy@example.com
  • Sadi Orlaf sadi@example.com
  • Amanda Yang amanda@example.com

Six people can be signed in at once, one per window. Pair Demo User with anyone else (Demo has a conversation with each). The AI Chatbot is a bot you message, not a login.

No second window to spare? Open the side-by-side demo to watch two people chat in a single window.

How it is built

Solid arrows are HTTP; dotted arrows are the WebSocket and real-time paths.

flowchart LR
  B["Your browser"]
  A["apache TLS proxy"]
  subgraph net["Docker compose network"]
    N["nginx"]
    L["php-fpm Laravel"]
    DB[("MySQL")]
    W["queue worker"]
    O["Ollama local LLM"]
    R(["Laravel Reverb"])
  end
  B -->|HTTPS and WSS| A
  A -->|HTTP| N
  A -.->|app websocket| R
  N --> L
  L --> DB
  L -->|queue bot reply| W
  W -->|generate| O
  W -.->|stream tokens| R
  L -.->|broadcast| R
  R -.->|live events| A
  classDef hub fill:#eef0ff,stroke:#4f46e5,color:#1c1f26,stroke-width:2px;
  class R,O hub;

How a message travels

Person to person

  1. You send a message: a POST to the Laravel app.
  2. Laravel saves it and broadcasts it over Reverb.
  3. The other person's Echo client receives it and appends it live, with no refresh.

You and the AI assistant

  1. You message the AI Chatbot contact.
  2. Laravel queues a job; the worker calls the local model through Ollama.
  3. As the model generates, the worker streams the tokens over Reverb.
  4. Your browser renders each token as it arrives.

Design choices

Instant delivery

Broadcasts are sent synchronously (ShouldBroadcastNow), so chat stays instant even though the slow LLM work runs on a queue.

No self-echo

The client sends its socket id, so the server's toOthers() never bounces your own message back to you.

Live presence

A Reverb presence channel tracks who is connected and marks each contact online in real time.

Streaming, not blocking

The assistant reply is a queued job; tokens are broadcast as start, token and done frames while the model runs.

Local model

qwen2.5:0.5b runs on the server through Ollama. No external API, CPU-only, swappable by one env value.

Lightweight UI

Hand-written CSS and one small JS bundle. No UI framework, no theme, no icon font.

Stack: Laravel 12, PHP 8.3, MySQL 8, nginx, Laravel Reverb, Ollama, Vite.