0Pricing
Node.js Backend Development Bootcamp · Lesson

Real-time Chat Application

Build a simple real-time chat application demonstrating message broadcasting and private messaging functionality.

Real-time Chat Application is a free Node.js Backend Development Bootcamp lesson on CoddyKit — lesson 6 of 6. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Node.js Backend Development Bootcamp learning path, one of 6 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Makes a Chat App Real-time?

Real-time chat applications allow users to send and receive messages instantly, without refreshing their browser.

This is made possible by WebSockets, which provide a persistent, bidirectional communication channel between the client and server.

In this lesson, we'll build a simple chat app with NestJS, demonstrating message broadcasting and private messaging.

Setting Up Our Chat Gateway

In NestJS, a Gateway is a class annotated with @WebSocketGateway() that handles WebSocket connections and messages.

It acts as the entry point for real-time communication. We'll specify a port for our WebSocket server.

import { WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';

@WebSocketGateway(3001, { cors: true }) // Port 3001, enable CORS
export class ChatGateway {
  @WebSocketServer() server: Server; // socket.io server instance

  // More logic will go here
}

Managing Client Connections

Our gateway needs to know when clients connect and disconnect. We implement OnGatewayConnection and OnGatewayDisconnect interfaces.

This allows us to run logic when a new user joins or leaves the chat.

import {
  WebSocketGateway, WebSocketServer,
  OnGatewayConnection, OnGatewayDisconnect
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway(3001, { cors: true })
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer() server: Server;

  handleConnection(client: Socket, ...args: any[]) {
    console.log(`Client connected: ${client.id}`);
    // You might add client to a list here
  }

  handleDisconnect(client: Socket) {
    console.log(`Client disconnected: ${client.id}`);
    // Remove client from any lists
  }
}

Sending Messages to Everyone

To broadcast a message, we listen for an event (e.g., 'sendMessage') from a client. When received, we use this.server.emit() to send it to ALL connected clients.

The @SubscribeMessage() decorator maps incoming WebSocket messages to handler methods.

import {
  WebSocketGateway, WebSocketServer,
  OnGatewayConnection, OnGatewayDisconnect,
  SubscribeMessage, MessageBody
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway(3001, { cors: true })
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer() server: Server;

  handleConnection(client: Socket) { /* ... */ }
  handleDisconnect(client: Socket) { /* ... */ }

  @SubscribeMessage('sendMessage')
  handleMessage(@MessageBody() data: { message: string, senderId: string }): void {
    console.log(`Message from ${data.senderId}: ${data.message}`);
    this.server.emit('receiveMessage', data); // Broadcast to all
  }
}

Client-side: Basic Chat Interaction

On the client, we use a library like socket.io-client to connect to our NestJS gateway.

We can then emit messages and on events to receive broadcasts.

// index.html (conceptual client-side script)
const socket = io('http://localhost:3001');

socket.on('connect', () => {
  console.log('Connected to chat server!');
  socket.emit('sendMessage', {
    message: 'Hello everyone!',
    senderId: 'user123'
  });
});

socket.on('receiveMessage', (data) => {
  console.log(`New message: ${data.message} from ${data.senderId}`);
  // Update chat UI
});

Targeting Specific Users (Private Chat)

Broadcasting is great for general announcements, but what about private conversations between two users?

For private messages, we need a way to identify individual clients and send messages only to them, or to a specific group (a 'room').

Identifying Individual Clients

To send private messages, we need to map a user's unique ID (e.g., from their login) to their specific WebSocket connection ID (client.id).

We can store this mapping in a simple object or Map within our gateway.

import {
  WebSocketGateway, WebSocketServer,
  OnGatewayConnection, OnGatewayDisconnect,
  ConnectedSocket
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway(3001, { cors: true })
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer() server: Server;
  private connectedUsers: Map<string, string> = new Map(); // userId -> socketId

  handleConnection(@ConnectedSocket() client: Socket) {
    const userId = client.handshake.query.userId as string; // Get user ID from query
    if (userId) {
      this.connectedUsers.set(userId, client.id);
      console.log(`User ${userId} connected with socket ID: ${client.id}`);
    } else {
      console.log(`Client connected without userId: ${client.id}`);
    }
  }

  handleDisconnect(@ConnectedSocket() client: Socket) {
    const userId = [...this.connectedUsers.entries()]
                    .find(([key, val]) => val === client.id)?.[0];
    if (userId) {
      this.connectedUsers.delete(userId);
      console.log(`User ${userId} disconnected.`);
    } else {
      console.log(`Client disconnected: ${client.id}`);
    }
  }
  // ... handleMessage for broadcasting ...
}

Sending Direct Messages to a User

With our user-to-socket mapping, we can now send messages directly to a target user's socket.

We listen for a 'privateMessage' event, look up the recipient's socket ID, and use this.server.to(socketId).emit().

import {
  WebSocketGateway, WebSocketServer,
  OnGatewayConnection, OnGatewayDisconnect,
  SubscribeMessage, MessageBody
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway(3001, { cors: true })
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer() server: Server;
  private connectedUsers: Map<string, string> = new Map(); // userId -> socketId

  handleConnection(client: Socket) { /* ... */ }
  handleDisconnect(client: Socket) { /* ... */ }
  @SubscribeMessage('sendMessage')
  handleMessage(data: { message: string, senderId: string }): void { /* ... */ }

  @SubscribeMessage('privateMessage')
  handlePrivateMessage(
    @MessageBody() data: { recipientId: string, message: string, senderId: string }
  ): void {
    const recipientSocketId = this.connectedUsers.get(data.recipientId);

    if (recipientSocketId) {
      this.server.to(recipientSocketId).emit('receivePrivateMessage', {
        message: data.message,
        senderId: data.senderId
      });
      console.log(`Private message from ${data.senderId} to ${data.recipientId}`);
    } else {
      console.log(`Recipient ${data.recipientId} not found or offline.`);
    }
  }
}

Using Rooms for Group Chats

For group chats, or even 1-on-1 chats, Socket.IO rooms are a powerful feature. Clients can 'join' a room, and you can then broadcast messages to that specific room.

  • client.join('roomName'): Adds a client to a room.
  • this.server.to('roomName').emit(): Sends a message to all clients in that room.

This simplifies managing message distribution for multiple participants.

Distinguishing Message Types

Consider a NestJS chat application. A user sends a message. You want to ensure only a specific group of 5 users (who are all online) receives this message, not everyone connected.

Real-time Chat: Broadcast & Private

In this lesson, you learned to build a basic real-time chat application using NestJS WebSockets.

  • We set up a Gateway to handle connections.
  • Implemented broadcasting messages to all connected clients.
  • Explored private messaging by mapping user IDs to socket IDs.
  • Briefly touched on using Socket.IO rooms for efficient group communication.

These concepts are fundamental for creating interactive, real-time features in your applications!

Frequently asked questions

Is the “Real-time Chat Application” lesson free?

Yes — the full text of “Real-time Chat Application” is free to read here on the web, and the Node.js Backend Development Bootcamp course includes 6 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Node.js Backend Development Bootcamp course, upgrade to CoddyKit PRO.

What will I learn in “Real-time Chat Application”?

Build a simple real-time chat application demonstrating message broadcasting and private messaging functionality. You practise Node.js Backend Development Bootcamp with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Node.js Backend Development Bootcamp?

No prior experience is required. Node.js Backend Development Bootcamp on CoddyKit is structured for beginners through advanced learners; this is — lesson 6 of 6, so you can start here or from the beginning and move at your own pace.

How long does the “Real-time Chat Application” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Node.js Backend Development Bootcamp lesson?

Yes. Every Node.js Backend Development Bootcamp lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Introduction to WebSockets
  2. WebSockets with NestJS
  3. Implementing Socket.IO in Node.js
  4. Gateway Configuration
  5. Building a Real-time Chat Application
  6. Real-time Chat Application
← Back to Node.js Backend Development Bootcamp