Building a Multi-Room WebSocket Chat Server with User Presence in Node.js

Building a Multi-Room WebSocket Chat Server with User Presence in Node.js WebSockets are the go-to technology for real-time web applications. In this tutorial, we’ll take things to the next level by creating a multi-room chat server that supports user presence using Node.js and the native ws library. Overview This project will feature: Multiple chat rooms Real-time user join/leave notifications Broadcasting messages to specific rooms only Tracking and syncing online users per room Step 1: Set Up Your Project mkdir multiroom-chat cd multiroom-chat npm init -y npm install ws uuid Step 2: The WebSocket Server // server.js const WebSocket = require('ws'); const { v4: uuidv4 } = require('uuid'); const wss = new WebSocket.Server({ port: 3000 }); const rooms = {}; function broadcastToRoom(roomId, data, exceptSocket = null) { rooms[roomId].forEach((client) => { if (client.readyState === WebSocket.OPEN && client !== exceptSocket) { client.send(JSON.stringify(data)); } }); } wss.on('connection', (ws) => { let userId = uuidv4(); let roomId = null; let username = null; ws.on('message', (message) => { try { const msg = JSON.parse(message); if (msg.type === 'join') { roomId = msg.room; username = msg.username; if (!rooms[roomId]) rooms[roomId] = new Set(); rooms[roomId].add(ws); broadcastToRoom(roomId, { type: 'notification', message: `${username} joined the room.`, }, ws); const users = Array.from(rooms[roomId]) .map((client) => client.username) .filter(Boolean); ws.username = username; ws.send(JSON.stringify({ type: 'users', users })); } if (msg.type === 'chat') { broadcastToRoom(roomId, { type: 'chat', message: msg.message, username, }); } } catch (err) { console.error('Invalid message received:', message); } }); ws.on('close', () => { if (roomId && rooms[roomId]) { rooms[roomId].delete(ws); broadcastToRoom(roomId, { type: 'notification', message: `${username} left the room.`, }); } }); }); console.log('WebSocket chat server running on ws://localhost:3000'); Step 3: Sample Client HTML Join Room Send let socket; function joinRoom() { const name = document.getElementById('username').value; const room = document.getElementById('room').value; socket = new WebSocket('ws://localhost:3000'); socket.addEventListener('open', () => { socket.send(JSON.stringify({ type: 'join', username: name, room })); }); socket.addEventListener('message', (event) => { const data = JSON.parse(event.data); const chat = document.getElementById('chat'); if (data.type === 'chat') { chat.innerHTML += `${data.username}: ${data.message}`; } else if (data.type === 'notification') { chat.innerHTML += `${data.message}`; } else if (data.type === 'users') { chat.innerHTML += `Users in room: ${data.users.join(', ')}`; } }); } function sendMessage() { const message = document.getElementById('msg').value; socket.send(JSON.stringify({ type: 'chat', message })); } Conclusion By building this multi-room chat with user presence from scratch, you've touched on several key aspects of WebSocket server architecture: stateful connections, group-based broadcasting, and dynamic user tracking. This setup can be expanded into more complex systems like collaborative workspaces, gaming lobbies, and live Q&A rooms. If this guide helped you, consider supporting me: buymeacoffee.com/hexshift

Apr 15, 2025 - 03:13
 0
Building a Multi-Room WebSocket Chat Server with User Presence in Node.js

Building a Multi-Room WebSocket Chat Server with User Presence in Node.js

WebSockets are the go-to technology for real-time web applications. In this tutorial, we’ll take things to the next level by creating a multi-room chat server that supports user presence using Node.js and the native ws library.

Overview

This project will feature:

  • Multiple chat rooms
  • Real-time user join/leave notifications
  • Broadcasting messages to specific rooms only
  • Tracking and syncing online users per room

Step 1: Set Up Your Project

mkdir multiroom-chat
cd multiroom-chat
npm init -y
npm install ws uuid

Step 2: The WebSocket Server

// server.js
const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');

const wss = new WebSocket.Server({ port: 3000 });
const rooms = {};

function broadcastToRoom(roomId, data, exceptSocket = null) {
  rooms[roomId].forEach((client) => {
    if (client.readyState === WebSocket.OPEN && client !== exceptSocket) {
      client.send(JSON.stringify(data));
    }
  });
}

wss.on('connection', (ws) => {
  let userId = uuidv4();
  let roomId = null;
  let username = null;

  ws.on('message', (message) => {
    try {
      const msg = JSON.parse(message);

      if (msg.type === 'join') {
        roomId = msg.room;
        username = msg.username;

        if (!rooms[roomId]) rooms[roomId] = new Set();
        rooms[roomId].add(ws);

        broadcastToRoom(roomId, {
          type: 'notification',
          message: `${username} joined the room.`,
        }, ws);

        const users = Array.from(rooms[roomId])
          .map((client) => client.username)
          .filter(Boolean);

        ws.username = username;
        ws.send(JSON.stringify({ type: 'users', users }));
      }

      if (msg.type === 'chat') {
        broadcastToRoom(roomId, {
          type: 'chat',
          message: msg.message,
          username,
        });
      }
    } catch (err) {
      console.error('Invalid message received:', message);
    }
  });

  ws.on('close', () => {
    if (roomId && rooms[roomId]) {
      rooms[roomId].delete(ws);
      broadcastToRoom(roomId, {
        type: 'notification',
        message: `${username} left the room.`,
      });
    }
  });
});

console.log('WebSocket chat server running on ws://localhost:3000');

Step 3: Sample Client HTML




  
  
  
  

Conclusion

By building this multi-room chat with user presence from scratch, you've touched on several key aspects of WebSocket server architecture: stateful connections, group-based broadcasting, and dynamic user tracking. This setup can be expanded into more complex systems like collaborative workspaces, gaming lobbies, and live Q&A rooms.

If this guide helped you, consider supporting me: buymeacoffee.com/hexshift