Skip to content

WebSocket Project: Build a Real-Time Application

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Websocket Project: Build a Real. We cover key concepts, practical examples, and best practices to help you master this topic.

This capstone project integrates all WebSocket concepts into a production-quality real-time collaboration application. You will build a team chat platform with rooms, authentication, file sharing, presence, and horizontal scaling.

What You'll Learn

  • Full WebSocket application from scratch
  • Integrating authentication, rooms, and broadcasting
  • Presence detection and typing indicators
  • File sharing over WebSocket
  • Production deployment

Why It Matters

Building a complete project solidifies all WebSocket concepts. You will encounter challenges like connection state management, cross-server broadcasting, and graceful shutdown.

flowchart TD
    Setup[Project Setup] --> Server[WebSocket Server]
    Server --> Auth[Authentication]
    Auth --> Rooms[Room Management]
    Rooms --> Messages[Real-Time Messages]
    Messages --> Presence[Presence Detection]
    Presence --> Files[File Sharing]
    Files --> Security[Security Layer]
    Security --> Deploy[Deployment]

Teacher Mindset

Build incrementally. Start with a basic WebSocket echo server. Add authentication, then rooms, then presence. Deploy early and iterate. Test every feature with both unit tests and manual browser testing.

Code Examples

// Example 1: Server structure
const WebSocket = require('ws');
const url = require('url');

class ChatServer {
  constructor(port) {
    this.wss = new WebSocket.Server({ port });
    this.rooms = new Map();
    this.users = new Map();
    this.setup();
  }

  setup() {
    this.wss.on('connection', (ws, req) => {
      const token = url.parse(req.url, true).query.token;
      const user = this.authenticate(token);
      if (!user) {
        ws.close(4001, 'Authentication failed');
        return;
      }

      ws.user = user;
      ws.rooms = new Set();
      this.users.set(user.id, ws);

      ws.on('message', (data) => this.handleMessage(ws, data));
      ws.on('close', () => this.handleDisconnect(ws));
      ws.on('pong', () => { ws.isAlive = true; });

      ws.send(JSON.stringify({ type: 'connected', user }));
    });

    this.startHeartbeat();
  }

  startHeartbeat() {
    setInterval(() => {
      this.wss.clients.forEach((ws) => {
        if (ws.isAlive === false) return ws.terminate();
        ws.isAlive = false;
        ws.ping();
      });
    }, 30000);
  }
}
// Example 2: Room and message handling
class ChatServer {
  handleMessage(ws, data) {
    const message = JSON.parse(data);

    switch (message.type) {
      case 'join':
        ws.rooms.add(message.room);
        this.broadcast(message.room, {
          type: 'user-joined',
          user: ws.user.name,
          timestamp: Date.now()
        }, ws);
        break;

      case 'message':
        this.broadcast(message.room, {
          type: 'message',
          user: ws.user.name,
          text: this.sanitize(message.text),
          timestamp: Date.now()
        });
        break;

      case 'typing':
        this.broadcast(message.room, {
          type: 'typing',
          user: ws.user.name,
          isTyping: message.isTyping
        }, ws);
        break;

      case 'leave':
        ws.rooms.delete(message.room);
        this.broadcast(message.room, {
          type: 'user-left',
          user: ws.user.name
        });
        break;
    }
  }

  broadcast(room, message, excludeWs) {
    this.wss.clients.forEach((client) => {
      if (client !== excludeWs && client.rooms.has(room) && client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(message));
      }
    });
  }
}
// Example 3: Client structure
class ChatClient {
  constructor(url, token) {
    this.url = url;
    this.token = token;
    this.connect();
  }

  connect() {
    this.ws = new WebSocket(`${this.url}?token=${this.token}`);

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.handleMessage(message);
    };

    this.ws.onclose = () => {
      setTimeout(() => this.connect(), 2000);
    };
  }

  sendMessage(room, text) {
    this.ws.send(JSON.stringify({ type: 'message', room, text }));
  }

  joinRoom(room) {
    this.ws.send(JSON.stringify({ type: 'join', room }));
  }
}

Common Mistakes

  • Trying to implement all features at once instead of building incrementally
  • Not handling WebSocket message ordering and delivery guarantees
  • Forgetting that broadcasting excludes the sender
  • Not sanitizing user-generated content in messages
  • Deploying without proper monitoring and logging

Practice

  1. Design the message protocol (JSON schema for each message type).
  2. Implement user authentication and connection tracking.
  3. Add room creation, joining, and leaving.
  4. Implement presence detection and typing indicators.
  5. Challenge: Add file sharing via binary WebSocket frames with progress indication.

FAQ

How large should the project be?

Aim for 5-6 message types, 3-4 rooms, authentication, presence, and broadcasting. This covers all major WebSocket patterns.

Should I use Socket.IO or raw ws?

Use raw ws for this project to understand the underlying protocol. Socket.IO can be added later for convenience features.

How do I persist messages?

Add a database layer. Store messages after broadcasting. The client can fetch history via an HTTP endpoint.

How do I scale beyond one server?

Add a Redis pub/sub layer. Use sticky sessions at the load balancer. Share room state through Redis.

How do I test the application?

Write unit tests for message handling logic. Use browser testing for real WebSocket interaction. Load test with wsbench or artillery.

Mini Project

Build the complete team chat application with: JWT authentication during handshake, Room creation and management, Real-time messaging with broadcasting, Typing indicators and user presence, File sharing via binary frames, Rate Limiting and origin validation, Heartbeat keepalive, Graceful shutdown, Docker deployment with Kubernetes.

What's Next

You have completed the WebSocket APIs section. Next, explore API Testing to learn how to validate and secure your APIs.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro