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.