Skills websocket-builder
git clone https://github.com/TerminalSkills/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/websocket-builder" ~/.claude/skills/terminalskills-skills-websocket-builder && rm -rf "$T"
skills/websocket-builder/SKILL.mdWebSocket Builder
Overview
Builds production-ready WebSocket servers for real-time features — chat, live dashboards, collaborative editing, notifications. Handles the hard parts: authentication during handshake, room/channel management, connection lifecycle, automatic reconnection, message ordering, and horizontal scaling via Redis pub/sub.
Instructions
1. Server Setup
When setting up a WebSocket server:
- Attach to existing HTTP server (share the port)
- Use a mature library:
for Node.js,ws
for Python,websockets
for Gogorilla/websocket - Implement ping/pong heartbeats (30s interval, 90s timeout)
- Set max message size to prevent abuse (default: 64KB)
- Add connection limits per user (default: 5 concurrent connections)
2. Authentication
Authenticate during the WebSocket handshake, not after:
1. Client connects with token in query string: ws://host/ws?token=<jwt> 2. Server validates JWT before upgrading the connection 3. If invalid → reject with 401 before upgrade completes 4. Attach user context to the socket object for later use
Do NOT accept auth via a post-connection message — the connection is already open and resources allocated.
3. Room/Channel Management
RoomManager: join(socketId, roomId) — Add socket to room, notify members leave(socketId, roomId) — Remove socket, notify members broadcast(roomId, event, data, excludeSocketId?) — Send to all in room getMembers(roomId) — List connected user IDs getUserRooms(socketId) — List rooms for a socket On connect: auto-join user's channel rooms from database On disconnect: leave all rooms, broadcast presence update
4. Event Routing
Use a message format with event types:
{ "event": "message.send", "data": { "channelId": "ch_1", "content": "Hello" }, "id": "client-uuid" }
Route events to handlers:
eventHandlers = { "message.send": handleMessageSend, "message.edit": handleMessageEdit, "typing.start": handleTypingStart, "presence.heartbeat": handleHeartbeat }
Always include a client-generated
id for idempotency and acknowledgment.
5. Scaling with Redis Pub/Sub
For multi-server deployments:
1. Each server subscribes to Redis channels matching room IDs 2. On broadcast: publish to Redis channel instead of local-only broadcast 3. Each server receives the publish and forwards to local sockets in that room 4. Use Redis adapter (e.g., @socket.io/redis-adapter or custom with ioredis)
6. Reconnection Protocol
Client-side: 1. On disconnect: attempt reconnect with exponential backoff (1s, 2s, 4s, max 30s) 2. On reconnect: send last_event_id to server 3. Server replays missed events since that ID 4. Client merges with local state, deduplicating by event ID Server-side: 1. Keep recent events in Redis sorted set (TTL: 1 hour) 2. On reconnect with last_event_id: return all events after that ID 3. If ID is too old (beyond retention): send full state refresh
Examples
Example 1: Chat WebSocket Server (Node.js)
Prompt: "Set up a WebSocket server for my Express app with rooms and JWT auth"
Output: Server with authenticated connections, room manager, event routing, ping/pong heartbeats, and reconnection support. Files:
ws/server.ts, ws/rooms.ts, ws/handlers/, ws/middleware/auth.ts.
Example 2: Live Dashboard (Python)
Prompt: "I need real-time updates for a monitoring dashboard. FastAPI backend, 500 concurrent viewers."
Output: WebSocket endpoint with broadcast-only channels (viewers don't send), Redis pub/sub for horizontal scaling, connection pooling, and automatic cleanup. Files:
realtime/server.py, realtime/broadcaster.py, realtime/redis_pubsub.py.
Guidelines
- Always authenticate at handshake — never after connection is open
- Use binary frames for large payloads (images, files) — text frames for JSON
- Implement backpressure — if a client can't keep up, buffer then disconnect
- Log connection lifecycle — connect, disconnect, error, room join/leave (debugging is hard without this)
- Test with connection drops — kill connections mid-message to verify recovery
- Set idle timeouts — disconnect clients that stop sending heartbeats
- Never trust client input — validate every message against expected schema