Claude Skills for WebSocket Realtime App Development
Real-time communication has become essential for modern web applications Chat systems, live dashboards, collaborative tools, and gaming platforms all rely on WebSocket connections to deliver instant data updates. Building these features from scratch presents unique challenges that Claude skills can help you overcome.
This guide shows you how to use specific Claude skills to accelerate WebSocket development, from initial architecture to production deployment.
Why WebSocket Development Benefits from Claude Skills
WebSocket development differs significantly from traditional HTTP request-response patterns. You must handle connection lifecycles, manage bidirectional messaging, implement reconnection logic, and deal with state synchronization across client and server. These concerns create boilerplate that takes time to implement correctly.
Claude skills encapsulate best practices for these patterns. Rather than researching solutions each time, you invoke a skill that applies proven approaches to your specific codebase. The skills work alongside your existing stack—whether you use Node.js, Python, or Go on the backend, and React, Vue, or vanilla JavaScript on the frontend.
Essential Skills for WebSocket Projects
Several Claude skills prove particularly valuable when building real-time applications. Each addresses a specific aspect of the development workflow.
frontend-design for UI Components
The frontend-design skill helps you create the visual layer of your real-time application. When building WebSocket-powered interfaces, you need components that handle incoming data gracefully—status indicators, message lists, live counters, and notification systems.
With frontend-design, you describe your requirements and receive implementation code that follows modern patterns:
Create a message thread component that displays real-time updates with fade-in animations and a connection status badge in the corner.
The skill generates React or Vue components with proper state management for handling WebSocket messages. It ensures your UI updates efficiently without unnecessary re-renders, which matters significantly when handling high-frequency updates.
tdd for Protocol Implementation
Writing tests for WebSocket code requires understanding connection states, message formats, and timing considerations. The tdd skill guides you through test-driven development for real-time systems.
When you invoke tdd, it helps you:
- Structure test suites for WebSocket handlers
- Mock WebSocket connections in your test environment
- Verify message serialization and deserialization
- Test reconnection scenarios without timing flakiness
The skill suggests test patterns specific to your testing framework. For instance, if you use Jest, it might recommend using fake timers and connection mocks to create deterministic tests for reconnection logic.
pdf for Documentation
Production WebSocket applications need documentation—API specifications, protocol guides, and architecture decisions. The pdf skill enables you to generate documentation from your codebase.
When your WebSocket protocol evolves, use pdf to export updated documentation:
Generate a PDF documenting the WebSocket message format, including the JSON schema for each message type and example payloads.
This keeps your team aligned without maintaining separate documentation files.
Practical Implementation Patterns
Let me walk through how these skills work together in a real project scenario.
Setting Up the Connection Layer
Before writing your connection manager, initialize your project with the necessary dependencies:
mkdir websocket-server && cd websocket-server
npm init -y
npm install ws express
Create your main server file with Express and the ws library:
const WebSocket = require('ws');
const express = require('express');
const http = require('http');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws, req) => {
console.log('Client connected');
ws.on('message', (message) => {
const data = JSON.parse(message);
handleMessage(ws, data);
});
ws.on('close', () => {
console.log('Client disconnected');
});
});
function handleMessage(ws, data) {
switch (data.type) {
case 'ping':
ws.send(JSON.stringify({ type: 'pong', timestamp: Date.now() }));
break;
case 'broadcast':
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(data.payload));
}
});
break;
}
}
server.listen(8080, () => {
console.log('WebSocket server running on port 8080');
});
Once your scaffold is in place, build a more complete connection manager. Use the tdd skill to drive the implementation:
class WebSocketManager {
constructor(url, options = {}) {
this.url = url;
this.options = options;
this.socket = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = options.maxReconnectAttempts || 5;
this.listeners = new Map();
}
connect() {
this.socket = new WebSocket(this.url);
this.socket.onopen = () => {
this.reconnectAttempts = 0;
this.emit('connected');
};
this.socket.onclose = (event) => {
this.handleReconnect();
};
this.socket.onmessage = (event) => {
const data = JSON.parse(event.data);
this.emit(data.type, data.payload);
};
}
handleReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
setTimeout(() => this.connect(), this.getBackoffDelay());
}
}
getBackoffDelay() {
return Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
}
}
The tdd skill would have guided you to write tests covering connection success, connection failure, message routing, and exponential backoff before writing this implementation.
Message Protocol Design
Establish a consistent message protocol across your application. The following schema captures the minimal contract your client and server should share:
// Message schema
const messageSchema = {
type: 'string', // Required: event type
payload: 'object', // Required: event data
id: 'string', // Optional: message ID for acknowledgment
timestamp: 'number' // Optional: client timestamp
};
Including an optional id field allows you to implement request-acknowledgment patterns where the server echoes the id back to confirm receipt. The timestamp field helps measure latency and order out-of-sequence messages on the client.
React Hook for WebSocket State
The custom hook pattern keeps your WebSocket logic reusable across components. Use the frontend-design skill to scaffold this:
// useWebSocket.js
import { useState, useEffect, useCallback, useRef } from 'react';
export function useWebSocket(url) {
const [messages, setMessages] = useState([]);
const [connected, setConnected] = useState(false);
const wsRef = useRef(null);
const connect = useCallback(() => {
wsRef.current = new WebSocket(url);
wsRef.current.onopen = () => {
setConnected(true);
};
wsRef.current.onmessage = (event) => {
const message = JSON.parse(event.data);
setMessages((prev) => [...prev, message]);
};
wsRef.current.onclose = () => {
setConnected(false);
// Attempt reconnection after 3 seconds
setTimeout(connect, 3000);
};
wsRef.current.onerror = (error) => {
console.error('WebSocket error:', error);
};
}, [url]);
const sendMessage = useCallback((message) => {
if (wsRef.current?.readyState === WebSocket.OPEN) {
wsRef.current.send(JSON.stringify(message));
}
}, []);
useEffect(() => {
connect();
return () => {
wsRef.current?.close();
};
}, [connect]);
return { messages, connected, sendMessage };
}
This hook handles connection lifecycle, automatic reconnection, and message state—patterns you’ll reuse across real-time features.
Building Real-Time UI Components
Once your connection layer exists, use frontend-design to create components that consume it. A chat interface might look like:
function ChatComponent({ wsManager }) {
const [messages, setMessages] = useState([]);
const [status, setStatus] = useState('disconnected');
useEffect(() => {
wsManager.on('connected', () => setStatus('connected'));
wsManager.on('message', (payload) => {
setMessages(prev => [...prev, payload]);
});
}, [wsManager]);
return (
<div className="chat-container">
<div className="status-badge">{status}</div>
<MessageList messages={messages} />
</div>
);
}
The frontend-design skill ensures your components follow your project’s styling conventions and include accessibility considerations.
Generating Protocol Documentation
As your application grows, document your message protocol. Use pdf to create a reference document:
## WebSocket Protocol Specification
### Message Format
All messages use JSON with the following structure:
{
"type": "string",
"payload": "object",
"timestamp": "ISO8601"
}
### Message Types
#### chat.message
- payload: { userId, content, roomId }
- Direction: Client to Server
#### chat.broadcast
- payload: { messageId, userId, content, timestamp }
- Direction: Server to Client
The pdf skill converts this markdown into a formatted PDF your team can reference.
Heartbeat Detection for Stale Connections
Production WebSocket servers must detect and close stale connections. Implement ping/pong heartbeats on the server:
// server.js
const { WebSocketServer } = require('ws');
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
ws.isAlive = true;
ws.on('pong', () => {
ws.isAlive = true;
});
// Send ping every 30 seconds
const interval = setInterval(() => {
if (ws.isAlive === false) {
clearInterval(interval);
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
}, 30000);
ws.on('close', () => {
clearInterval(interval);
});
});
To keep the heartbeat logic reusable, extract it into a named function you can apply to every new connection:
const HEARTBEAT_INTERVAL = 30000;
function setupHeartbeat(ws) {
ws.isAlive = true;
ws.on('pong', () => {
ws.isAlive = true;
});
const interval = setInterval(() => {
if (ws.isAlive === false) {
clearInterval(interval);
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
}, HEARTBEAT_INTERVAL);
ws.on('close', () => clearInterval(interval));
}
wss.on('connection', (ws) => {
setupHeartbeat(ws);
// ...rest of connection logic
});
Pair this with a client-side connection status indicator:
function ConnectionStatus({ connected }) {
const statusStyles = {
connected: 'bg-green-500',
disconnected: 'bg-red-500'
};
return (
<div className={`w-3 h-3 rounded-full ${statusStyles[connected ? 'connected' : 'disconnected']}`} />
);
}
Python Asyncio WebSocket Server
If your backend stack is Python, Claude skills work equally well for asyncio-based implementations. Here is a subscription-based event server:
# websocket-server.py
import asyncio
import websockets
import json
from datetime import datetime
async def handle_client(websocket, path):
try:
async for message in websocket:
data = json.loads(message)
if data.get('type') == 'subscribe':
channel = data.get('channel')
await websocket.send(json.dumps({
'type': 'subscribed',
'channel': channel,
'timestamp': datetime.now().isoformat()
}))
elif data.get('type') == 'event':
event_type = data.get('event_type')
payload = data.get('payload')
print(f"Received event: {event_type}")
await broadcast_event(event_type, payload)
except websockets.exceptions.ConnectionClosed:
print("Client disconnected")
async def broadcast_event(event_type, payload):
# Broadcast to all connected subscribers
pass
async def main():
async with websockets.serve(handle_client, "localhost", 8765):
print("WebSocket server running on ws://localhost:8765")
await asyncio.Future() # Run forever
if __name__ == "__main__":
asyncio.run(main())
For Python clients with robust reconnection, use an exponential backoff class:
import websocket
import time
import json
class ReconnectingClient:
def __init__(self, url, max_retries=5):
self.url = url
self.max_retries = max_retries
self.ws = None
def connect(self):
retries = 0
while retries < self.max_retries:
try:
self.ws = websocket.WebSocketApp(
self.url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close
)
self.ws.on_open = self.on_open
self.ws.run_forever()
except Exception as e:
retries += 1
wait_time = min(2 ** retries, 30)
print(f"Reconnecting in {wait_time}s (attempt {retries})")
time.sleep(wait_time)
print("Max retries exceeded")
def on_message(self, ws, message):
data = json.loads(message)
# Process message
def on_open(self, ws):
ws.send(json.dumps({'type': 'subscribe', 'channel': 'events'}))
def on_error(self, ws, error):
print(f"Error: {error}")
def on_close(self, ws, close_status_code, close_msg):
print("Connection closed, attempting reconnect...")
Live Dashboard Pattern
For skills that drive visual dashboards, Claude skills can generate a bridge between your WebSocket stream and a file-polled frontend:
# dashboard-updater.py
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
if data['type'] == 'update':
with open('./public/live-data.json', 'w') as f:
json.dump(data['payload'], f)
print(f"Updated dashboard at {data['timestamp']}")
def on_open(ws):
ws.send(json.dumps({
'type': 'subscribe',
'channel': 'metrics'
}))
if __name__ == "__main__":
ws = websocket.WebSocketApp(
"ws://localhost:8765",
on_open=on_open,
on_message=on_message,
on_error=lambda ws, e: print(f"Error: {e}"),
on_close=lambda ws, c, m: print("Connection closed")
)
ws.run_forever()
The frontend-design skill can then generate a dashboard that polls this file for updates, creating a near-real-time experience without a persistent browser WebSocket connection.
Advanced Considerations
Handling High-Frequency Updates
When your application sends many messages per second, consider implementing:
- Message batching on the server
- Throttled updates on the client using requestAnimationFrame
- Binary message formats (Protocol Buffers or MessagePack) for reduced payload size
The tdd skill helps you test these optimizations without introducing bugs.
Scaling WebSocket Connections with Redis
At scale, a single server cannot maintain all connections. Redis pub/sub enables cross-server message broadcasting:
const Redis = require('ioredis');
const redis = new Redis();
const wss = new WebSocketServer({ port: 8080 });
// Subscribe to Redis channel
redis.subscribe('chat-messages', (err) => {
if (err) console.error('Redis subscribe error:', err);
});
redis.on('message', (channel, message) => {
// Broadcast Redis messages to all connected WebSocket clients
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
wss.on('connection', (ws) => {
ws.on('message', (message) => {
// Publish to Redis for other servers to receive
redis.publish('chat-messages', message);
});
});
This pattern ensures messages reach all connected clients regardless of which server instance handles the original request. Pair it with:
- Connection state stored in Redis or a similar shared store
- A pub/sub message broker (Redis, RabbitMQ) for event routing
- Horizontal scaling with multiple WebSocket server instances
Document your architecture using pdf so operations teams can maintain the system.
Security Best Practices
Always implement:
- WSS (WebSocket Secure) connections in production
- Authentication tokens in the connection handshake
- Origin validation on the server
- Message validation and sanitization
- Rate limiting per connection
The tdd skill can guide you to write security tests covering these concerns. A basic token-based authentication pattern that validates the token and places the user into a personal channel:
wss.on('connection', (ws, req) => {
const url = new URL(req.url, `http://${req.headers.host}`);
const token = url.searchParams.get('token');
if (!validateToken(token)) {
ws.close(4001, 'Authentication failed');
return;
}
const userId = getUserIdFromToken(token);
ws.userId = userId;
// Join user to their personal channel
joinRoom(ws, `user:${userId}`);
});
For more granular channel authorization, extend this pattern to verify access on each incoming message:
wss.on('connection', (ws, req) => {
const url = new URL(req.url, `http://${req.headers.host}`);
const token = url.searchParams.get('token');
try {
const user = verifyToken(token);
ws.user = user;
} catch (error) {
ws.close(4001, 'Authentication required');
return;
}
ws.on('message', (message) => {
const data = JSON.parse(message);
if (!canUserAccessChannel(ws.user, data.channel)) {
ws.send(JSON.stringify({ error: 'Access denied' }));
return;
}
// Process message...
});
});
Testing WebSocket Applications
Write integration tests that verify message flow end-to-end. The tdd skill helps you structure these:
// tests/websocket.test.js
const { WebSocket } = require('ws');
describe('WebSocket Chat', () => {
let server;
beforeAll(() => {
server = require('../server');
});
afterAll(() => {
server.close();
});
it('broadcasts messages to all clients', (done) => {
const client1 = new WebSocket('ws://localhost:8080');
const client2 = new WebSocket('ws://localhost:8080');
client1.on('open', () => {
client2.on('open', () => {
client1.send(JSON.stringify({ text: 'Hello' }));
});
client2.on('message', (data) => {
const message = JSON.parse(data);
expect(message.text).toBe('Hello');
client1.close();
client2.close();
done();
});
});
});
});
The supermemory skill benefits from WebSocket connections when syncing memories across devices in real-time. The tdd skill can stream test results as they execute, providing immediate feedback. For documentation generation with the docx skill, WebSocket connections enable progress updates during lengthy document assembly.
Debugging and Monitoring
Intermittent connection drops and race conditions are among the hardest WebSocket bugs to reproduce. The superMemory skill maintains your investigation context across multiple Claude sessions, so you can continue a debugging thread without re-explaining the problem from scratch.
Implement structured logging to capture connection metrics:
function logConnectionEvent(event) {
console.log(JSON.stringify({
timestamp: Date.now(),
event: event.type,
clientId: event.clientId,
serverTime: Date.now()
}));
}
Call logConnectionEvent on connection, disconnection, authentication failures, and message errors. Structured JSON output lets you pipe logs into aggregation tools (Datadog, Loki, CloudWatch) for alerting and trend analysis without additional parsing.
The docx skill is also useful here: it creates formatted Word documents for post-incident reports and architectural decision records that require tracked changes or collaborative editing.
Bringing It Together
Building WebSocket real-time applications requires coordination across multiple concerns—connection management, UI updates, documentation, and testing. Claude skills provide structured guidance for each aspect.
Start with tdd to establish your connection layer with proper test coverage. Use frontend-design for the reactive components that display real-time data. Keep your protocol documented with pdf as it evolves. These skills work together to accelerate your development cycle while maintaining code quality.
The combination of test-driven development, thoughtful UI implementation, and living documentation creates a foundation you can build on—whether you’re building a simple chat or a complex collaborative platform.
Related Reading
- Claude Skills for GraphQL Schema Design and Testing — Combine WebSocket real-time subscriptions with GraphQL schema design for full-stack real-time APIs.
- Claude Code Skills for Kubernetes Operator Development — Scale your WebSocket application infrastructure using Kubernetes operator patterns.
- Rate Limit Management for Claude Code Skill Intensive Workflows — Manage API rate limits when skill-generating high-frequency WebSocket message handlers.
- Can Claude Code Skills Call External APIs Automatically — Extend WebSocket patterns to REST and streaming API integrations.
- Claude Skills Use Cases — Explore more specialized use cases for Claude skills in real-time and event-driven architectures.
- Claude Code Server Sent Events API Guide — Compare WebSocket bidirectional messaging with SSE for one-way streaming use cases.
- Claude Code gRPC API Development Guide — Use gRPC streaming as an alternative transport for high-performance real-time services.
- Claude Code REST API Design Best Practices — Design the complementary REST endpoints that pair with your WebSocket event stream.
Built by theluckystrike — More at zovo.one