MERN Stack Tutorial: Creating a Real-Time Chat Application from Scratch

By | February 27, 2026

MERN Stack Tutorial: Creating a Real-Time Chat Application from Scratch

In this tutorial, we will learn how to build a real-time chat application using the MERN (MongoDB, Express, React, and Node.js) stack. The MERN stack is a popular choice for building modern web applications, and it’s ideal for creating real-time applications like chat apps. By the end of this tutorial, you’ll have a fully functional chat application that allows users to send and receive messages in real-time.

Prerequisites

Before we begin, make sure you have the following installed on your machine:

  • Node.js (version 14 or higher)
  • MongoDB (version 4 or higher)
  • A code editor or IDE of your choice
  • Basic knowledge of JavaScript, HTML, and CSS

Step 1: Setting up the Project Structure

Create a new project folder and navigate to it in your terminal or command prompt. Run the following command to initialize a new Node.js project:
bash
npm init

Fill in the required information, and then install the following dependencies:
bash
npm install express mongoose socket.io react react-dom

Create the following folders and files:

  • server: This folder will contain our server-side code.
  • client: This folder will contain our client-side code.
  • models: This folder will contain our database models.
  • index.js: This file will be the entry point of our server.
  • package.json: This file contains metadata for our project.

Step 2: Setting up the Server

In the server folder, create a new file called index.js. This file will contain our server-side code. Add the following code to get started:
javascript
const express = require(‘express’);
const app = express();
const http = require(‘http’).createServer(app);
const io = require(‘socket.io’)(http);
const mongoose = require(‘mongoose’);

mongoose.connect(‘mongodb://localhost:27017/chat-app’, { useNewUrlParser: true, useUnifiedTopology: true });

app.use(express.static(‘client’));

http.listen(3000, () => {
console.log(‘Server listening on port 3000’);
});

This code sets up an Express server, creates a new HTTP server, and sets up Socket.IO for real-time communication. It also connects to our MongoDB database.

Step 3: Creating the Database Model

In the models folder, create a new file called message.js. This file will contain our database model for messages. Add the following code:
javascript
const mongoose = require(‘mongoose’);

const messageSchema = new mongoose.Schema({
text: String,
sender: String,
receiver: String,
timestamp: Date
});

const Message = mongoose.model(‘Message’, messageSchema);

module.exports = Message;

This code defines a new Mongoose model for messages, which will be used to store and retrieve messages from our database.

Step 4: Creating the Client-Side Code

In the client folder, create a new file called index.js. This file will contain our client-side code. Add the following code:
javascript
import React, { useState, useEffect } from ‘react’;
import ReactDOM from ‘react-dom’;
import io from ‘socket.io-client’;

const socket = io(‘http://localhost:3000‘);

function App() {
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState(”);
const [username, setUsername] = useState(”);

useEffect(() => {
socket.on(‘connect’, () => {
console.log(‘Connected to server’);
});

socket.on('message', (message) => {
setMessages((prevMessages) => [...prevMessages, message]);
});

}, []);

const handleSendMessage = () => {
socket.emit(‘message’, { text: newMessage, sender: username });
setNewMessage(”);
};

return (

setNewMessage(e.target.value)} />

    {messages.map((message, index) => (

  • {message.text}
  • ))}

);
}

ReactDOM.render(, document.getElementById(‘root’));

This code sets up a basic React app that connects to our server using Socket.IO. It also defines a few state variables to store the messages, new message, and username.

Step 5: Handling Socket Events

In the server folder, add the following code to index.js to handle socket events:
javascript
io.on(‘connection’, (socket) => {
console.log(‘Client connected’);

socket.on(‘message’, (message) => {
const newMessage = new Message(message);
newMessage.save((err) => {
if (err) {
console.error(err);
} else {
io.emit(‘message’, message);
}
});
});

socket.on(‘disconnect’, () => {
console.log(‘Client disconnected’);
});
});

This code handles the connection event, which is emitted when a client connects to the server. It also handles the message event, which is emitted when a client sends a message. When a message is received, it creates a new message document in the database and emits the message event to all connected clients.

Step 6: Running the Application

Start the server by running the following command:

node server/index.js

Open two or more browser windows and navigate to http://localhost:3000. You should see a basic chat interface where you can send and receive messages in real-time.

Conclusion

In this tutorial, we built a real-time chat application using the MERN stack. We set up a server using Express and Socket.IO, created a database model using Mongoose, and built a client-side interface using React. We also handled socket events to enable real-time communication between clients. This is just a basic example, and you can improve it by adding features like user authentication, message editing, and deletion.