Playground API
DocsStatsBlogStudio
Playground API

The free, stateful mock REST & GraphQL API sandbox where visitor mutations actually persist in an isolated session overlay without sign-up.

Public API Online (99.98%)

Endpoints

  • /api/v1/posts
  • /api/v1/users
  • /api/v1/comments
  • /api/v1/todos
  • /api/v1/graphql

Simulations

  • JWT Auth & Roles
  • Stripe Payments
  • Virtual Email & OTP
  • Latency & Chaos
  • Realtime Webhooks

Articles & Guides

Deep Dives
  • All Feature Articles→
  • React CRUD Guide
  • Why Static APIs Fail
  • Mocking Stateful Auth
  • WebSockets & SSE

Ecosystem

  • Quickstart Guide
  • TypeScript SDK
  • OpenAPI Spec
  • Postman Collection
  • GitHub Repository

© 2026 Playground API. Created by Nilesh Kumar. Open source under ISC license.

Powered by Express 5, Prisma & Neon PostgreSQLllms.txt
HomeBlogHow to Build and Test Real-Time WebSocket Chat in React Without a Backend Server
Feature Deep Dive3 min read•2026-09-20

How to Build and Test Real-Time WebSocket Chat in React Without a Backend Server

Learn how to test native WebSockets, Socket.io, room messaging, typing indicators, and SSE streams in frontend apps without running local WS servers.

NK
Nilesh Kumar
Creator of Playground API
How to Build and Test Real-Time WebSocket Chat in React Without a Backend Server

How to Build and Test Real-Time WebSocket Chat in React Without a Backend Server

Frontend engineers building real-time collaborative interfaces—such as live customer support widgets, multiplayer notification bars, or team chat channels—inevitably run into a painful testing hurdle:

"How do I test bi-directional message dispatching, typing indicators, reconnection loops, and multi-user room broadcasting before the backend WebSocket server is deployed?"

Traditionally, you either have to write a local Node.js ws or socket.io server script, manage local port tunnels with ngrok for mobile testing, or write brittle in-memory mock classes that don't test true RFC 6455 network frames.

In this guide, we explore the mechanics of real-time protocols, compare Native WebSocket vs Socket.io vs Server-Sent Events (SSE), and demonstrate how to build an interactive, multi-room chat client in React tested against Playground API's zero-config real-time gateway.


1. Comparing Real-Time Transport Protocols

Before writing frontend code, let's look at the three primary real-time communication patterns:

mermaid
1
graph TD
2
subgraph Native WebSocket [Native WebSocket RFC 6455]
3
WSClient[Browser Client] <-->|Bidirectional Full-Duplex TCP wss://| WSServer[WS Gateway]
4
end
5
6
subgraph SocketIO [Socket.io 4.x]
7
SIOClient[Browser Client] <-->|HTTP Long-Polling Fallback + Auto-Upgrade| SIOServer[Socket.io Server]
8
end
9
10
subgraph SSE [Server-Sent Events]
11
SSEClient[Browser Client] <--|Unidirectional text/event-stream| SSEServer[HTTP Stream Endpoint]
12
end

Protocol Comparison Matrix

FeatureNative WebSocket (wss://)Socket.io (/socket.io)Server-Sent Events (SSE)
DirectionalityFull-Duplex Bi-directionalFull-Duplex Bi-directionalUnidirectional (Server &rarr; Client)
Browser Native?✅ Yes (new WebSocket())❌ Requires client library✅ Yes (new EventSource())
Automatic Reconnect❌ Manual implementation✅ Built-in✅ Built-in by browser
Room / Namespace❌ Manual routing✅ Built-in❌ Single stream URL
Best ForLive chat, gaming, standard APIsEnterprise messaging, auto-fallbacksLive notifications, telemetry

2. Connecting to the Live Real-Time Gateway

Playground API provides a unified real-time gateway where Native WebSocket clients and Socket.io clients communicate seamlessly in the exact same room:

  • Native WebSocket: wss://playground.nileslabs.com/ws?room=general&username=Alice
  • Socket.io 4.x: https://playground.nileslabs.com with path /socket.io
  • Server-Sent Events (SSE): https://playground.nileslabs.com/api/v1/stream/notifications

The Standard Message Schema

All incoming and outgoing chat payloads follow this standardized format:

json
1
{
2
"type": "message",
3
"id": "msg-local-12345",
4
"room": "support",
5
"sender_id": 1,
6
"sender_name": "Alice Developer",
7
"recipient_id": "bot_assistant",
8
"text": "Hello, I need help testing real-time events!",
9
"created_at": "2026-09-19T10:00:00.000Z"
10
}

3. Building a Real-Time React Chat Component

Let's build a clean, production-ready React chat component using the native browser WebSocket API with automatic reconnection, typing indicators, and room switching:

tsx
1
// src/components/LiveChatWidget.tsx
2
import React, { useState, useEffect, useRef } from 'react';
3
4
interface ChatMessage {
5
id: string;
6
room: string;
7
sender_name: string;
8
text: string;
9
created_at: string;
10
}
11
12
export function LiveChatWidget() {
13
const [messages, setMessages] = useState<ChatMessage[]>([]);
14
const [inputText, setInputText] = useState('');
15
const [room, setRoom] = useState('support');
16
const [isConnected, setIsConnected] = useState(false);
17
const [botTyping, setBotTyping] = useState(false);
18
const wsRef = useRef<WebSocket | null>(null);
19
20
useEffect(() => {
21
// 1. Establish Native WebSocket connection with query parameters
22
const wsUrl = wss://playground.nileslabs.com/ws?room=${room}&username=FrontendEngineer`;
23
const ws = new WebSocket(wsUrl);
24
wsRef.current = ws;
25
26
ws.onopen = () => {
27
setIsConnected(true);
28
};
29
30
ws.onmessage = (event) => {
31
try {
32
const payload = JSON.parse(event.data);
33
34
if (payload.type === 'message') {
35
setMessages((prev) => [...prev, payload]);
36
} else if (payload.type === 'typing') {
37
setBotTyping(payload.isTyping);
38
}
39
} catch (err) {
40
console.error('Invalid JSON payload:', event.data);
41
}
42
};
43
44
ws.onclose = () => {
45
setIsConnected(false);
46
};
47
48
return () => {
49
ws.close();
50
};
51
}, [room]);
52
53
function handleSendMessage(e: React.FormEvent) {
54
e.preventDefault();
55
if (!inputText.trim() || !wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) return;
56
57
// 2. Dispatch message to the room
58
const messagePayload = {
59
type: 'message',
60
room: room,
61
sender_name: 'FrontendEngineer',
62
text: inputText,
63
};
64
65
wsRef.current.send(JSON.stringify(messagePayload));
66
setInputText('');
67
}
68
69
return (
70
<div className="max-w-lg mx-auto p-4 bg-slate-900 border border-slate-800 rounded-2xl shadow-xl text-slate-100 font-sans">
71
{/* Header & Status */}
72
<div className="flex items-center justify-between pb-3 border-b border-slate-800">
73
<div className="flex items-center gap-2">
74
<span className={w-2.5 h-2.5 rounded-full ${isConnected ? 'bg-emerald-500 animate-pulse' : 'bg-rose-500'}} />
75
<h3 className="font-bold text-sm text-white">Live Chat (#{room})</h3>
76
</div>
77
<select
78
value={room}
79
onChange={(e) => { setMessages([]); setRoom(e.target.value); }}
80
className="bg-slate-950 text-xs px-2 py-1 rounded border border-slate-700 text-slate-300"
81
>
82
<option value="support">#support (Echo Bot Enabled)</option>
83
<option value="general">#general</option>
84
<option value="random">#random</option>
85
</select>
86
</div>
87
88
{/* Messages Feed */}
89
<div className="h-64 overflow-y-auto my-3 space-y-2 p-2 bg-slate-950/60 rounded-xl border border-slate-800/80 text-xs">
90
{messages.length === 0 ? (
91
<p className="text-slate-500 text-center py-20">No messages yet. Send a message to chat with the Echo Bot!</p>
92
) : (
93
messages.map((msg, idx) => (
94
<div key={msg.id || idx} className={p-2 rounded-lg ${msg.sender_name === 'FrontendEngineer' ? 'bg-indigo-600/20 ml-6' : 'bg-slate-800/60 mr-6'}}>
95
<span className="font-bold text-slate-300 block">{msg.sender_name}:</span>
96
<p className="text-slate-200 mt-0.5">{msg.text}</p>
97
</div>
98
))
99
)}
100
{botTyping && (
101
<div className="text-slate-400 italic text-[11px] animate-pulse">
102
Support Bot is typing...
103
</div>
104
)}
105
</div>
106
107
{/* Input Form */}
108
<form onSubmit={handleSendMessage} className="flex gap-2">
109
<input
110
type="text"
111
value={inputText}
112
onChange={(e) => setInputText(e.target.value)}
113
placeholder="Type your message or mention @bot..."
114
className="flex-1 bg-slate-950 border border-slate-700 px-3 py-2 rounded-lg text-xs text-white focus:outline-none focus:border-indigo-500"
115
/>
116
<button
117
type="submit"
118
disabled={!isConnected}
119
className="bg-indigo-600 hover:bg-indigo-500 disabled:bg-slate-800 text-white font-bold text-xs px-4 py-2 rounded-lg transition-colors"
120
>
121
Send
122
</button>
123
</form>
124
</div>
125
);
126
}

4. Testing the Built-in Support Bot Simulator

When testing chat applications locally, it’s frustrating to test alone because you have to open two browser windows to simulate a conversation.

Playground API includes an Automated Echo Support Bot:

  1. When you join the #support room or mention @bot, the gateway automatically fires a { type: "typing", isTyping: true } event.
  2. After 250ms of natural typing delay, the bot replies with an echo acknowledgment.
  3. It automatically turns off the typing indicator event!

5. Summary & Key Takeaways

  1. Native WebSockets and Socket.io can be tested without local servers. By targeting wss://playground.nileslabs.com/ws, frontend developers can verify connection lifecycles, typing indicators, and room routing instantly.
  2. Server-Sent Events (SSE) provide lightweight unidirectional streams. Use GET /api/v1/stream/notifications for testing notification bells and real-time dashboard counters.
  3. Session state is preserved. Chat history created during your session persists across refreshes.

Explore the interactive live Chat Studio and copy starter code at:

👉 https://playground.nileslabs.com/docs/chat

Tags:#react#websocket#javascript#webdev
Continue Reading
Previous Article
Zero-Config GraphQL Prototyping: Nested Queries, Relations & State Mutations
Next Article
How to Test Outgoing Webhooks and HMAC Signatures Without Setting Up an Event Server

Try Playground API in Your Own App

Stateful mock REST & GraphQL API with private sandbox overlays.

Quickstart GuideOpen Interactive Studio
Table of Contents
0%
  • 1. Comparing Real-Time Transport Protocols
  • Protocol Comparison Matrix
  • 2. Connecting to the Live Real-Time Gateway
  • The Standard Message Schema
  • 3. Building a Real-Time React Chat Component
  • 4. Testing the Built-in Support Bot Simulator
  • 5. Summary & Key Takeaways
Feature Deep Dives

In-depth technical guides exploring Playground API features — real-time subscriptions, stateful sandboxes, schema validation, latency simulation, and developer tooling.

Browse All Articles