← ClaudeAtlas

serve-realtime-with-websocketslisted

Use when pushing realtime updates to connected clients over WebSockets (a socket.io / WS gateway) — authenticating the socket at the handshake (once, not per message), joining sockets to rooms for targeted broadcast, scaling across instances with a Redis pub/sub adapter (+ sticky sessions), bridging domain events to room emits, and connection-lifecycle hygiene (reconnect, listener cleanup). NestJS/socket.io reference, framework-flexible.
kennguyen887/agent-foundation · ★ 1 · Web & Frontend · score 77
Install: claude install-skill kennguyen887/agent-foundation
# Serve realtime with WebSockets Pushing live updates to connected clients (call signalling, notifications, presence, live status) over a **WebSocket gateway**. Examples NestJS + socket.io, neutral domain. principle → **▸ Example** → **▸ Other stacks**. Unlike the rest of the backend (request/RPC/queue), a WebSocket holds a **long-lived, stateful connection** — which changes how you auth, target, and scale. Cross-service events that *feed* the broadcasts are `integrate-internal-services`. ## Core principle **Authenticate once at the handshake, target with rooms, and scale with a shared pub/sub adapter.** A connection is long-lived and pinned to one instance, so: verify identity when it opens (not per message), broadcast to **rooms** (never a blind global emit), and put a **Redis adapter** between instances or a multi-pod deploy only reaches the clients on one pod. Keep business logic out of the gateway — it's a transport. ## 1. The gateway + connection lifecycle A gateway declares the server, lifecycle hooks, and message handlers: ```ts @WebSocketGateway({ cors: { origin: corsOrigins } }) export class EventsGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server!: Server; handleConnection(socket: Socket) { if (!socket.handshake.auth.userId) { socket.emit('error', 'unauthenticated'); socket.disconnect(); return; } // reject unauth } handleDisconnect(socket: Socket) { socket.removeAllListeners(); } // cleanup — a