real-time-features

Implement real-time bidirectional communication between clients and servers for instant data synchronization and live updates.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "real-time-features" with this command: npx skills add eddiebe147/claude-settings/eddiebe147-claude-settings-real-time-features

Real-Time Features

Overview

Implement real-time bidirectional communication between clients and servers for instant data synchronization and live updates.

When to Use

  • Chat and messaging applications

  • Live dashboards and analytics

  • Collaborative editing (Google Docs-style)

  • Real-time notifications

  • Live sports scores or stock tickers

  • Multiplayer games

  • Live auctions or bidding systems

  • IoT device monitoring

  • Real-time location tracking

Technologies Comparison

Technology Direction Use Case Browser Support

WebSockets Bidirectional Chat, gaming, collaboration Excellent

SSE Server → Client Live updates, notifications Good (no IE)

Long Polling Request/Response Fallback, simple updates Universal

WebRTC Peer-to-peer Video/audio streaming Good

Implementation Examples

  1. WebSocket Server (Node.js)

// server.ts import WebSocket, { WebSocketServer } from 'ws'; import { createServer } from 'http';

interface Message { type: 'join' | 'message' | 'leave' | 'typing'; userId: string; username: string; content?: string; timestamp: number; }

interface Client { ws: WebSocket; userId: string; username: string; roomId: string; }

class ChatServer { private wss: WebSocketServer; private clients: Map<string, Client> = new Map(); private rooms: Map<string, Set<string>> = new Map();

constructor(port: number) { const server = createServer(); this.wss = new WebSocketServer({ server });

this.wss.on('connection', this.handleConnection.bind(this));

server.listen(port, () => {
  console.log(`WebSocket server running on port ${port}`);
});

// Heartbeat to detect disconnections
this.startHeartbeat();

}

private handleConnection(ws: WebSocket): void { const clientId = this.generateId();

console.log(`New connection: ${clientId}`);

ws.on('message', (data: string) => {
  try {
    const message: Message = JSON.parse(data.toString());
    this.handleMessage(clientId, message, ws);
  } catch (error) {
    console.error('Invalid message format:', error);
  }
});

ws.on('close', () => {
  this.handleDisconnect(clientId);
});

ws.on('error', (error) => {
  console.error(`WebSocket error for ${clientId}:`, error);
});

// Keep connection alive
(ws as any).isAlive = true;
ws.on('pong', () => {
  (ws as any).isAlive = true;
});

}

private handleMessage( clientId: string, message: Message, ws: WebSocket ): void { switch (message.type) { case 'join': this.handleJoin(clientId, message, ws); break;

  case 'message':
    this.broadcastToRoom(clientId, message);
    break;

  case 'typing':
    this.broadcastToRoom(clientId, message, [clientId]);
    break;

  case 'leave':
    this.handleDisconnect(clientId);
    break;
}

}

private handleJoin( clientId: string, message: Message, ws: WebSocket ): void { const client: Client = { ws, userId: message.userId, username: message.username, roomId: 'general' // Could be dynamic };

this.clients.set(clientId, client);

// Add to room
if (!this.rooms.has(client.roomId)) {
  this.rooms.set(client.roomId, new Set());
}
this.rooms.get(client.roomId)!.add(clientId);

// Notify room
this.broadcastToRoom(clientId, {
  type: 'join',
  userId: message.userId,
  username: message.username,
  timestamp: Date.now()
});

// Send room state to new user
this.sendRoomState(clientId);

}

private broadcastToRoom( senderId: string, message: Message, exclude: string[] = [] ): void { const sender = this.clients.get(senderId); if (!sender) return;

const roomClients = this.rooms.get(sender.roomId);
if (!roomClients) return;

const payload = JSON.stringify(message);

roomClients.forEach(clientId => {
  if (!exclude.includes(clientId)) {
    const client = this.clients.get(clientId);
    if (client &#x26;&#x26; client.ws.readyState === WebSocket.OPEN) {
      client.ws.send(payload);
    }
  }
});

}

private sendRoomState(clientId: string): void { const client = this.clients.get(clientId); if (!client) return;

const roomClients = this.rooms.get(client.roomId);
if (!roomClients) return;

const users = Array.from(roomClients)
  .map(id => this.clients.get(id))
  .filter(c => c &#x26;&#x26; c.userId !== client.userId)
  .map(c => ({ userId: c!.userId, username: c!.username }));

client.ws.send(JSON.stringify({
  type: 'room_state',
  users,
  timestamp: Date.now()
}));

}

private handleDisconnect(clientId: string): void { const client = this.clients.get(clientId); if (!client) return;

// Remove from room
const roomClients = this.rooms.get(client.roomId);
if (roomClients) {
  roomClients.delete(clientId);

  // Notify others
  this.broadcastToRoom(clientId, {
    type: 'leave',
    userId: client.userId,
    username: client.username,
    timestamp: Date.now()
  });
}

this.clients.delete(clientId);
console.log(`Client disconnected: ${clientId}`);

}

private startHeartbeat(): void { setInterval(() => { this.wss.clients.forEach((ws: any) => { if (ws.isAlive === false) { return ws.terminate(); } ws.isAlive = false; ws.ping(); }); }, 30000); }

private generateId(): string { return Math.random().toString(36).substr(2, 9); } }

// Start server new ChatServer(8080);

  1. WebSocket Client (React)

// useWebSocket.ts import { useEffect, useRef, useState, useCallback } from 'react';

interface UseWebSocketOptions { url: string; onMessage?: (data: any) => void; onOpen?: () => void; onClose?: () => void; onError?: (error: Event) => void; reconnectAttempts?: number; reconnectInterval?: number; }

export const useWebSocket = (options: UseWebSocketOptions) => { const { url, onMessage, onOpen, onClose, onError, reconnectAttempts = 5, reconnectInterval = 3000 } = options;

const [isConnected, setIsConnected] = useState(false); const [connectionStatus, setConnectionStatus] = useState< 'connecting' | 'connected' | 'disconnected' | 'error'

('connecting');

const wsRef = useRef<WebSocket | null>(null); const reconnectCountRef = useRef(0); const reconnectTimeoutRef = useRef<NodeJS.Timeout>();

const connect = useCallback(() => { try { setConnectionStatus('connecting'); const ws = new WebSocket(url);

  ws.onopen = () => {
    console.log('WebSocket connected');
    setIsConnected(true);
    setConnectionStatus('connected');
    reconnectCountRef.current = 0;
    onOpen?.();
  };

  ws.onmessage = (event) => {
    try {
      const data = JSON.parse(event.data);
      onMessage?.(data);
    } catch (error) {
      console.error('Failed to parse message:', error);
    }
  };

  ws.onerror = (error) => {
    console.error('WebSocket error:', error);
    setConnectionStatus('error');
    onError?.(error);
  };

  ws.onclose = () => {
    console.log('WebSocket disconnected');
    setIsConnected(false);
    setConnectionStatus('disconnected');
    onClose?.();

    // Attempt reconnection
    if (reconnectCountRef.current &#x3C; reconnectAttempts) {
      reconnectCountRef.current++;
      console.log(
        `Reconnecting... (${reconnectCountRef.current}/${reconnectAttempts})`
      );
      reconnectTimeoutRef.current = setTimeout(() => {
        connect();
      }, reconnectInterval);
    }
  };

  wsRef.current = ws;
} catch (error) {
  console.error('Failed to connect:', error);
  setConnectionStatus('error');
}

}, [url, onMessage, onOpen, onClose, onError, reconnectAttempts, reconnectInterval]);

const disconnect = useCallback(() => { if (reconnectTimeoutRef.current) { clearTimeout(reconnectTimeoutRef.current); } wsRef.current?.close(); wsRef.current = null; }, []);

const send = useCallback((data: any) => { if (wsRef.current?.readyState === WebSocket.OPEN) { wsRef.current.send(JSON.stringify(data)); } else { console.warn('WebSocket is not connected'); } }, []);

useEffect(() => { connect(); return () => { disconnect(); }; }, [connect, disconnect]);

return { isConnected, connectionStatus, send, disconnect, reconnect: connect }; };

// Usage in component const ChatComponent: React.FC = () => { const [messages, setMessages] = useState<any[]>([]);

const { isConnected, send } = useWebSocket({ url: 'ws://localhost:8080', onMessage: (data) => { if (data.type === 'message') { setMessages(prev => [...prev, data]); } }, onOpen: () => { send({ type: 'join', userId: 'user123', username: 'John Doe', timestamp: Date.now() }); } });

const sendMessage = (content: string) => { send({ type: 'message', userId: 'user123', username: 'John Doe', content, timestamp: Date.now() }); };

return ( <div> <div>Status: {isConnected ? 'Connected' : 'Disconnected'}</div> <div> {messages.map((msg, i) => ( <div key={i}>{msg.username}: {msg.content}</div> ))} </div> </div> ); };

  1. Server-Sent Events (SSE)

// server.ts - SSE endpoint import express from 'express';

const app = express();

interface Client { id: string; res: express.Response; }

class SSEManager { private clients: Client[] = [];

addClient(id: string, res: express.Response): void { // Set SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.setHeader('Access-Control-Allow-Origin', '*');

this.clients.push({ id, res });

// Send initial connection event
this.sendToClient(id, {
  type: 'connected',
  clientId: id,
  timestamp: Date.now()
});

console.log(`Client ${id} connected. Total: ${this.clients.length}`);

}

removeClient(id: string): void { this.clients = this.clients.filter(client => client.id !== id); console.log(Client ${id} disconnected. Total: ${this.clients.length}); }

sendToClient(id: string, data: any): void { const client = this.clients.find(c => c.id === id); if (client) { client.res.write(data: ${JSON.stringify(data)}\n\n); } }

broadcast(data: any, excludeId?: string): void { const message = data: ${JSON.stringify(data)}\n\n; this.clients.forEach(client => { if (client.id !== excludeId) { client.res.write(message); } }); }

sendEvent(event: string, data: any): void { const message = event: ${event}\ndata: ${JSON.stringify(data)}\n\n; this.clients.forEach(client => { client.res.write(message); }); } }

const sseManager = new SSEManager();

app.get('/events', (req, res) => { const clientId = Math.random().toString(36).substr(2, 9);

sseManager.addClient(clientId, res);

req.on('close', () => { sseManager.removeClient(clientId); }); });

// Simulate real-time updates setInterval(() => { sseManager.broadcast({ type: 'update', value: Math.random() * 100, timestamp: Date.now() }); }, 5000);

app.listen(3000, () => { console.log('SSE server running on port 3000'); });

// client.ts - SSE client class SSEClient { private eventSource: EventSource | null = null; private reconnectAttempts = 0; private maxReconnectAttempts = 5;

connect(url: string, handlers: { onMessage?: (data: any) => void; onError?: (error: Event) => void; onOpen?: () => void; }): void { this.eventSource = new EventSource(url);

this.eventSource.onopen = () => {
  console.log('SSE connected');
  this.reconnectAttempts = 0;
  handlers.onOpen?.();
};

this.eventSource.onmessage = (event) => {
  try {
    const data = JSON.parse(event.data);
    handlers.onMessage?.(data);
  } catch (error) {
    console.error('Failed to parse SSE data:', error);
  }
};

this.eventSource.onerror = (error) => {
  console.error('SSE error:', error);
  handlers.onError?.(error);

  if (this.reconnectAttempts &#x3C; this.maxReconnectAttempts) {
    this.reconnectAttempts++;
    setTimeout(() => {
      console.log('Reconnecting to SSE...');
      this.connect(url, handlers);
    }, 3000);
  }
};

// Custom event listeners
this.eventSource.addEventListener('custom-event', (event: any) => {
  console.log('Custom event:', JSON.parse(event.data));
});

}

disconnect(): void { this.eventSource?.close(); this.eventSource = null; } }

// Usage const client = new SSEClient(); client.connect('http://localhost:3000/events', { onMessage: (data) => { console.log('Received:', data); }, onOpen: () => { console.log('Connected to server'); } });

  1. Socket.IO (Production-Ready)

// server.ts import { Server } from 'socket.io'; import { createServer } from 'http';

const httpServer = createServer(); const io = new Server(httpServer, { cors: { origin: process.env.CLIENT_URL || 'http://localhost:3000', methods: ['GET', 'POST'] }, pingTimeout: 60000, pingInterval: 25000 });

// Middleware io.use((socket, next) => { const token = socket.handshake.auth.token; if (isValidToken(token)) { next(); } else { next(new Error('Authentication error')); } });

io.on('connection', (socket) => { console.log(User connected: ${socket.id});

// Join room socket.on('join-room', (roomId: string) => { socket.join(roomId); socket.to(roomId).emit('user-joined', { userId: socket.id, timestamp: Date.now() }); });

// Handle messages socket.on('message', (data) => { const roomId = Array.from(socket.rooms)[1]; // First is own ID io.to(roomId).emit('message', { ...data, userId: socket.id, timestamp: Date.now() }); });

// Typing indicator socket.on('typing', (isTyping: boolean) => { const roomId = Array.from(socket.rooms)[1]; socket.to(roomId).emit('user-typing', { userId: socket.id, isTyping }); });

socket.on('disconnect', () => { console.log(User disconnected: ${socket.id}); }); });

httpServer.listen(3001);

function isValidToken(token: string): boolean { // Implement token validation return true; }

Best Practices

✅ DO

  • Implement reconnection logic with exponential backoff

  • Use heartbeat/ping-pong to detect dead connections

  • Validate and sanitize all messages

  • Implement authentication and authorization

  • Handle connection limits and rate limiting

  • Use compression for large payloads

  • Implement proper error handling

  • Monitor connection health

  • Use rooms/channels for targeted messaging

  • Implement graceful shutdown

❌ DON'T

  • Send sensitive data without encryption

  • Keep connections open indefinitely without cleanup

  • Broadcast to all users when targeted messaging suffices

  • Ignore connection state management

  • Send large payloads frequently

  • Skip message validation

  • Forget about mobile/unstable connections

  • Ignore scaling considerations

Performance Optimization

// Message batching class MessageBatcher { private queue: any[] = []; private timer: NodeJS.Timeout | null = null; private batchSize = 10; private batchDelay = 100;

constructor( private sendFn: (messages: any[]) => void ) {}

add(message: any): void { this.queue.push(message);

if (this.queue.length >= this.batchSize) {
  this.flush();
} else if (!this.timer) {
  this.timer = setTimeout(() => this.flush(), this.batchDelay);
}

}

private flush(): void { if (this.queue.length > 0) { this.sendFn(this.queue.splice(0)); } if (this.timer) { clearTimeout(this.timer); this.timer = null; } } }

Resources

  • WebSocket API (MDN)

  • Socket.IO Documentation

  • Server-Sent Events

  • ws - WebSocket Library

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

cli-builder

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

referral program designer

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

client onboarding designer

No summary provided by upstream source.

Repository SourceNeeds Review