Real-time applications have become a crucial part of modern web development. Whether it’s a live scoreboard, a collaborative tool, or a chat application, users expect instantaneous updates without needing to refresh the page. One of the most effective ways to build such real-time functionality is by using WebSockets.
In this guide, we will walk through the process of building a real-time chat application with WebSockets in JavaScript, covering both the frontend and backend.
What is WebSocket?
WebSocket is a protocol that enables two-way communication between a client (typically a web browser) and a server over a single, long-lived connection. Unlike traditional HTTP requests (where the client sends a request and the server responds), WebSocket allows the client and server to send messages to each other at any time.
This makes WebSocket an ideal solution for real-time applications like chat apps, where messages need to be instantly sent and received.
Setting Up the Project
We'll be using Node.js for the backend and plain JavaScript for the frontend. For the WebSocket implementation, we'll use the ws library for Node.js.
Step 1: Install Node.js and Express
First, ensure that you have Node.js installed. Then, create a new project directory and initialize it:
mkdir websocket-chat-app
cd websocket-chat-app
npm init -y
Next, install Express and ws for WebSocket support:
npm install express ws
Step 2: Setting Up the Backend with WebSocket
We’ll start by creating a basic WebSocket server using Node.js and Express.
- Create a file called
server.js:
const express = require("express");
const http = require("http");
const WebSocket = require("ws");
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
app.use(express.static("public"));
const clients = new Set();
wss.on("connection", (ws) => {
console.log("New client connected");
clients.add(ws);
ws.on("message", (message) => {
console.log("Received:", message);
clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
ws.on("close", () => {
console.log("Client disconnected");
clients.delete(ws);
});
});
server.listen(3000, () => {
console.log("Server is listening on port 3000");
});
This code does the following:
Sets up an HTTP server using Express to serve static files (HTML, CSS, JS).
Creates a WebSocket server that listens for new connections.
Broadcasts messages received from one client to all other clients.
Step 3: Creating the Frontend
Now that we have the backend WebSocket server, let’s create a simple frontend that will allow users to send and receive messages in real time.
- Create a
public directory with an index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Chat with File Upload</title>
<style>
body {
font-family: Arial, sans-serif;
}
#chat {
max-width: 600px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
background: #f9f9f9;
}
#messages {
height: 300px;
overflow-y: scroll;
border: 1px solid #ddd;
padding: 10px;
}
.message {
margin: 5px 0;
}
#input-form {
display: flex;
margin-top: 10px;
}
#message-input {
flex-grow: 1;
padding: 10px;
border: 1px solid #ddd;
}
#send-button {
padding: 10px;
background: #28a745;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<div id="chat">
<h1>WebSocket Chat</h1>
<div id="messages"></div>
<form id="input-form">
<input type="text" id="message-input" placeholder="Enter your message" autocomplete="off" />
<button id="send-button">Send</button>
</form>
</div>
<script>
const messagesDiv = document.getElementById('messages');
const messageInput = document.getElementById('message-input');
const form = document.getElementById('input-form');
const ws = new WebSocket('ws://localhost:3000');
ws.onmessage = (event) => {
if (event.data instanceof Blob) {
const reader = new FileReader();
reader.onload = function() {
const newMessage = document.createElement('div');
newMessage.classList.add('message');
newMessage.textContent = reader.result;
messagesDiv.appendChild(newMessage);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
};
reader.readAsText(event.data);
} else {
const newMessage = document.createElement('div');
newMessage.classList.add('message');
newMessage.textContent = event.data;
messagesDiv.appendChild(newMessage);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
};
form.addEventListener('submit', (e) => {
e.preventDefault();
const message = messageInput.value;
if (message) {
ws.send(message);
messageInput.value = '';
}
});
</script>
</body>
</html>
This frontend contains:
An input field for typing messages.
A "Send" button to submit the message.
A div that displays incoming messages.
JavaScript to handle WebSocket connections and real-time message updates.

Running the Application
- Start the server:
node server.js
Open your browser and navigate to http://localhost:3000. You should see the chat interface.
Open multiple tabs or windows to simulate different users and start chatting!
Enhancing the Chat App
While this is a basic real-time chat app, there are plenty of ways you can enhance it:
1. Display Usernames
- You can prompt users to enter a username when they join the chat and display their name next to each message.
2. Add Message Timestamps
- Add timestamps to each message to indicate when it was sent.
3. Private Messaging
- Implement direct messaging between specific users instead of broadcasting to everyone.
4. Store Chat History
- Use a database (like MongoDB or MySQL) to store chat history and display past messages when a user connects.
5. Emojis and Rich Text
- Enhance the chat experience by allowing users to send emojis or format text (bold, italics, etc.).
Conclusion
Building a real-time chat application with WebSockets in JavaScript is a great way to understand how real-time web applications work. WebSocket’s full-duplex communication model makes it perfect for chat apps, live updates, collaborative tools, and more.
With a basic understanding of how WebSockets operate, you can now explore and expand upon this foundation to build more feature-rich and scalable applications.
Happy coding! 🎉