AllTechnologyProgrammingWeb DevelopmentAI
    CODING IS POWERFUL!
    Back to Blog

    Building a Real-time Chat App with Next.js 15 and Socket.io

    16 min read
    May 5, 2025
    Building a Real-time Chat App with Next.js 15 and Socket.io

    Table of Contents

    • Get Started
    • Setup Next.js 15
    • Socket.io Server
    • Socket.io Client
    • Connect App
    • Send Messages
    • Receive Messages
    • Show Chat
    • Organize Code
    • Wrap Up
    • People Also Ask for

    Get Started

    Welcome! In this series, you'll learn how to build a real-time chat application from the ground up.

    We'll be using Next.js 15 for the frontend and backend API routes, and Socket.io to handle the real-time communication between users.

    This first section will help you prepare your development environment and create the initial project structure for our chat app. Let's dive in!


    Setup Next.js 15

    Before we dive into the real-time magic with Socket.io, we need a solid foundation. This section walks you through setting up a new Next.js 15 project, which will serve as the base for our chat application.

    Next.js provides an excellent developer experience and performance, making it a great choice for building modern web applications like ours. Follow these simple steps to get your project ready.

    First, open your terminal or command prompt and navigate to the directory where you want to create your project. Then, run the following command:

    npx create-next-app@latest chat-app # Replace 'chat-app' with your desired project name

    This command will start the setup process. You'll be prompted with a few questions about your project configuration. For this tutorial, we recommend the following choices:

    • Would you like to use TypeScript? No (or Yes, if you prefer TypeScript)
    • Would you like to use ESLint? Yes
    • Would you like to use Tailwind CSS? Yes
    • Would you like to use src/ directory? Yes
    • Would you like to use App Router? Yes
    • Would you like to customize the default import alias (@/*)? No

    Once the setup is complete, navigate into your new project directory:

    cd chat-app

    You now have a basic Next.js 15 project set up with Tailwind CSS and the App Router, ready for the next steps in building our real-time chat application.


    Socket.io Server

    Building a real-time chat application requires a server that can handle persistent connections with multiple clients simultaneously. This is where Socket.io comes in. It provides a robust and easy-to-use framework for building real-time features by enabling bidirectional communication between the server and clients.

    In the context of a Next.js application, you'll typically run the Socket.io server either alongside your Next.js server or as a separate process. For this chat application, we'll set up the Socket.io server to listen for connections and handle message broadcasting.

    Here's a basic outline of setting up the Socket.io server:

    • Install the necessary packages: socket.io and potentially socket.io-client (though the client is for the frontend).
    • Create an HTTP server (often using Node.js's built-in http module).
    • Attach Socket.io to the HTTP server.
    • Define event handlers for connection, disconnection, and receiving messages.
    • Broadcast received messages to all connected clients.

    Here's a simple example of initializing a Socket.io server:

    
    const http = require('http');
    const socketIo = require('socket.io');
    
    const server = http.createServer();
    const io = new socketIo(server);
    
    io.on('connection', (socket) => {
        // Handle new connections
        console.log('A user connected');
    
        socket.on('disconnect', () => {
            // Handle disconnections
            console.log('User disconnected');
        );
    
        socket.on('chat message', (msg) => {
            // Handle incoming messages
            console.log('message: ' + msg);
            io.emit('chat message', msg); // Broadcast message to all clients
        );
    );
    
    const PORT = 3001; // Or any available port
    server.listen(PORT, () => {
        console.log(`Socket.io server listening on port ${PORT}`);
    );
    

    This snippet sets up a basic server that listens for connections, logs connection/disconnection events, and broadcasts any received 'chat message' to all connected clients.

    In a real-world Next.js application, integrating this might involve setting up a custom server or using API routes, but the core logic remains similar. The key is establishing the server that the frontend clients can connect to for real-time communication.

    Setting up the server correctly is a critical step for enabling real-time features.


    Socket.io Client

    Now that our server is ready to handle connections and messages, we need to set up the client-side in our Next.js application. The Socket.io client library allows our front-end to connect to the server and interact with the real-time features.

    The first step is to install the client library in your Next.js project.

    npm install socket.io-client

    Once installed, you can import the library and establish a connection to your server. You'll typically do this when your component mounts.

    import { io } from 'socket.io-client';
    
    // Assuming your server is running on localhost:3001
    const socket = io('http://localhost:3001');
    
    // Example event listeners
    socket.on('connect', () => {
      console.log('Connected to server!');
    });
    
    socket.on('disconnect', (reason) => {
      console.log(`Disconnected: ${reason}`);
    });

    Remember to manage the socket connection properly, especially when the component unmounts, to avoid memory leaks. You can do this by disconnecting the socket in a cleanup function.


    Connect App

    Now that our Next.js 15 project is set up and we have a basic understanding of Socket.io, let's focus on how the client application will connect to our Socket.io server.

    Establishing the connection is the crucial first step for any real-time communication. The client needs to know where the server is located to initiate the handshake.

    Typically, you'll use the Socket.io client library in your Next.js front-end code. This library provides the necessary functions to connect to the server URL you specify.

    Once the connection is successfully established, the client and server can begin exchanging messages in real-time.

    We'll cover the specific code implementation details for both the server and client in later sections. For now, understand that the 'Connect App' phase involves the client reaching out to the server to open a persistent connection channel.


    Send Messages

    Now that your client is connected to the Socket.io server, the next crucial step is enabling users to actually send messages. This involves capturing the message input from the user interface and transmitting it to the server using Socket.io's capabilities.

    When a user types a message and initiates the send action (like clicking a button or pressing Enter), we need to grab the message content from the input field. This content will then be sent to the server via an event.

    Using the Socket.io client instance we set up earlier, we'll use the emit() method. This method allows us to send custom events from the client to the server. We'll define an event name, for instance, 'sendMessage', and include the message data as the payload for this event.

    It's important to include relevant data with the message, such as the message text itself and potentially information about the sender.

    On the server side, we'll have a corresponding listener for the 'sendMessage' event. When the server receives this event, it can then process the message and prepare it for distribution to other connected clients.


    Receive Messages

    Once your client is connected to the Socket.io server, the next crucial step is setting up a way to listen for incoming messages. This is how your app will know when other users have sent something new.

    In Socket.io, receiving messages is handled by setting up event listeners on the client-side socket instance. You specify the name of the event you want to listen for, and provide a callback function that will execute whenever that event occurs.

    For our chat application, we'll listen for an event that the server will emit when a new message is sent. Let's assume this event is called 'receive_message'. The server will include the message data as part of this event.

    Here's a simple example of how you might set up this listener in your Next.js component:

    
    // Assuming 'socket' is your connected Socket.io client instance
    
    useEffect(() => {
      // Listen for the 'receive_message' event
      socket.on('receive_message', (data) => {
        // 'data' will contain the message information sent from the server
        console.log('Message received:', data);
    
        // You'll typically update your state here to add the new message to your chat display
        // For example, if you have a 'messages' state array:
        // setMessages((prevMessages) => [...prevMessages, data]);
      });
    
      // Clean up the listener when the component unmounts
      return () => {
        socket.off('receive_message');
      };
    }, [socket]);
    

    Inside the callback function, you receive the message data. What you do with this data is up to your application's logic, but commonly you will update the state of your component to add the new message to the list displayed on the screen. Using React's state management (like useState) and immutability practices (like spreading previous messages [...prevMessages, data]) is key here.

    It's also very important to clean up the listener when the component unmounts. This prevents memory leaks and ensures the listener isn't active when it shouldn't be. The useEffect hook's cleanup function is perfect for this, using socket.off('receive_message').

    Receive Messages

    Once your client is connected to the Socket.io server, the next crucial step is setting up a way to listen for incoming messages. This is how your app will know when other users have sent something new.

    In Socket.io, receiving messages is handled by setting up event listeners on the client-side socket instance. You specify the name of the event you want to listen for, and provide a callback function that will execute whenever that event occurs.

    For our chat application, we'll listen for an event that the server will emit when a new message is sent. Let's assume this event is called 'receive_message'. The server will include the message data as part of this event.

    Here's a simple example of how you might set up this listener in your Next.js component:

    
    // Assuming 'socket' is your connected Socket.io client instance
    
    useEffect(() => {
      // Listen for the 'receive_message' event
      socket.on('receive_message', (data) => {
        // 'data' will contain the message information sent from the server
        console.log('Message received:', data);
    
        // You'll typically update your state here to add the new message to your chat display
        // For example, if you have a 'messages' state array:
        // setMessages((prevMessages) => [...prevMessages, data]);
      });
    
      // Clean up the listener when the component unmounts
      return () => {
        socket.off('receive_message');
      };
    }, [socket]);
    

    Inside the callback function, you receive the message data. What you do with this data is up to your application's logic, but commonly you will update the state of your component to add the new message to the list displayed on the screen. Using React's state management (like useState) and immutability practices (like spreading previous messages [...prevMessages, data]) is key here.

    It's also very important to clean up the listener when the component unmounts. This prevents memory leaks and ensures the listener isn't active when it shouldn't be. The useEffect hook's cleanup function is perfect for this, using socket.off('receive_message').


    Show Chat

    Once messages have been successfully sent and received, the next vital step is to present them clearly within the user interface. This segment focuses on taking the messages retrieved through Socket.io and rendering them effectively for the user to read.

    Upon receiving a new message event from the Socket.io server, our application needs to capture this message data. We will then typically store these incoming messages in the local state of our chat component. Using a state management mechanism like React's useState hook, we can maintain a dynamic list of all messages in the current conversation.

    To display these messages, we will iterate over the array of messages held in our state. Each message object usually contains details such as the sender's identifier and the actual message content. By mapping through this array, we can create a visual element for each message, such as a list item (<li>), which displays both the sender's identity and the message text.

    Ensuring a smooth user experience means keeping the most recent messages in view, especially in busy chat sessions. Implementing automatic scrolling functionality that moves the chat window to the bottom whenever a new message arrives helps users easily follow the ongoing conversation without manual scrolling.

    The core process involves updating the component's state with new messages, dynamically rendering them onto the screen, and managing the scroll position to always show the latest entries.


    Organize Code

    As your chat application grows, keeping the codebase neat is key. A well-organized structure makes it easier to manage, debug, and add new features.

    Here are a few ways to structure your project:

    • Separate server-side Socket.io code from Next.js front-end code.
    • Group components logically (e.g., chat messages, input forms).
    • Place utility functions in a dedicated folder.
    • Consider using aliases for easier imports.

    Consistency in file naming and folder structure across your project helps others (and your future self) understand the code quickly.


    Wrap Up

    We've reached the end of our journey building a real-time chat application. Over the course of this guide, we covered the essential steps to get your chat app running using Next.js 15 for the frontend and API, and Socket.io to handle the real-time communication.

    We started by setting up a new Next.js project, then dived into configuring both the Socket.io server and the client. Connecting the frontend and backend allowed us to implement the core features: sending and receiving messages instantly. We also looked at how to display the chat history and organize the code for better maintainability.

    Building a real-time application like this demonstrates the power of frameworks like Next.js combined with libraries designed for live communication. This project provides a solid foundation you can build upon. Consider adding features like user authentication, multiple chat rooms, or typing indicators to enhance your application.

    Thank you for following along! Hopefully, this guide has equipped you with the knowledge to start building your own real-time applications.


    People Also Ask

    • What is the best tech for a real-time chat app?

      Node.js and Socket.io are a popular combination for real-time chat applications due to their performance, scalability, and real-time capabilities.

    • How can I scale a real-time chat app with Node.js?

      Node.js is known for its scalability. You can use tools like Redis to manage WebSocket connections and scale your real-time chat app to handle many users.

    • How is real-time communication handled by Socket.io?

      Socket.io uses WebSockets for real-time communication. It also provides fallbacks for older browsers that may not support WebSockets directly.

    • What are alternatives to Socket.io for real-time apps with Next.js?

      Several alternatives exist for real-time features in Next.js apps, especially when hosted on platforms like Vercel that may not fully support WebSockets with the default Next.js server. Options include Pusher, Ably, Firebase, AnyCable+, Azure SignalR Service, PubNub, and Microsoft Azure Web PubSub.

    • How do you secure a real-time chat app?

      To secure a real-time chat app, implement authentication and encryption for user data. Also, sanitize user inputs to prevent attacks like Cross-Site Scripting (XSS).

    • Can I use Socket.io with Next.js API routes?

      Using Socket.io with Next.js API routes can be challenging due to the serverless nature of Vercel. A custom server might be needed, but this has implications for performance optimizations and Vercel deployment. Some developers opt for a separate server specifically for WebSocket connections.

    • How do I connect Socket.io to my Next.js client?

      You typically install the socket.io-client library on the client side. You then establish a connection using the io() function, often pointing to your Socket.io server URL. It's important to ensure the Socket.io client is excluded from server-side rendering in Next.js.


    Join Our Newsletter

    Launching soon - be among our first 500 subscribers!

    Suggested Posts

    AI - The New Frontier for the Human Mind
    AI

    AI - The New Frontier for the Human Mind

    AI's growing presence raises critical questions about its profound effects on human psychology and cognition. 🧠
    36 min read
    8/9/2025
    Read More
    AI's Unseen Influence - Reshaping the Human Mind
    AI

    AI's Unseen Influence - Reshaping the Human Mind

    AI's unseen influence: Experts warn on mental health, cognition, and critical thinking impacts.
    26 min read
    8/9/2025
    Read More
    AI's Psychological Impact - A Growing Concern
    AI

    AI's Psychological Impact - A Growing Concern

    AI's psychological impact raises alarms: risks to mental health & critical thinking. More research needed. 🧠
    20 min read
    8/9/2025
    Read More
    Developer X

    Muhammad Areeb (Developer X)

    Quick Links

    PortfolioBlog

    Get in Touch

    [email protected]+92 312 5362908

    Crafting digital experiences through code and creativity. Building the future of web, one pixel at a time.

    © 2025 Developer X. All rights reserved.