Building a Real-Time Chat App with Next.js and Server-Sent Events

This time we will explore how to build a high-performance real-time chat application using Next.js + Server-Sent Events (SSE) while showcasing key best practices in modern web development, including real-time communication, immutable state management, type safety, and graceful error handling.


preview url

https://next-56vi69or7-hucks-projects.vercel.app

https://chat.huckdev.com/

Tech Stack Highlights

Server-Sent Events (SSE) for Real-Time Communication

  • Uses the native browser EventSource API to establish a persistent connection with the server.
  • Implements incremental streaming updates, allowing users to see messages as they arrive rather than waiting for the entire message.
  • Supports connection error handling, automatic reconnections, and graceful degradation.

Core Implementation

✅ Implementing Real-Time Message Streaming

This app uses Server-Sent Events (SSE) for one-way real-time message delivery, with key logic including:

  • Establishing a persistent SSE connection:

    1
    const eventSource = new EventSource("/api/chat/stream");
  • Receiving incremental message updates:

    1
    2
    3
    4
    eventSource.onmessage = (event) => {
    const newData = JSON.parse(event.data);
    setMessages((prev) => [...prev, newData]);
    };
  • Gracefully closing the connection:

    1
    2
    3
    return () => {
    eventSource.close();
    };

✅ Managing Message State

The app uses React’s immutable data pattern to manage the message list:

1
2
3
4
const [messages, setMessages] = useState<Message[]>([]);

// Update using immutable state management
setMessages((prev) => [...prev, newMessage]);

This ensures a clear, debuggable state and can be easily extended to use Zustand, Jotai, or other advanced state management libraries if needed.

✅ Error Handling and User Experience

A robust error handling mechanism ensures stability and a good user experience:

1
2
3
4
eventSource.onerror = (err) => {
console.error("EventSource error:", err);
setError("Connection lost, attempting to reconnect...");
};

Combined with loading indicators (skeletons or spinners), this approach significantly improves user experience, even in unstable network conditions.


EventSource

An EventSource instance opens a persistent connection to an HTTP server, which sends events in text/event-stream format. The connection remains open until closed by calling EventSource.close().

Read more:
https://developer.mozilla.org/en-US/docs/Web/API/EventSource

SSE

Generated image

  • SSE is a browser API: Server-Sent Events provide a native browser API to receive real-time updates from a server over a single, long-lived HTTP connection. The EventSource interface is the standard way for browsers to consume these events.

  • Next.js is a React framework: Next.js handles server-side rendering (SSR), static site generation (SSG), and API routes. While it can act as an SSE server by creating API routes that stream data, it relies on the browser’s native EventSource for receiving and handling events on the client.

  • Simplicity and Efficiency: Using EventSource is the most straightforward and efficient method for handling SSE in the browser. It automatically manages connection retries, last-event-ID tracking, and parsing of the event stream.


Conclusion

By combining Next.js, Server-Sent Events, and React Hooks, you can easily build a real-time chat application.

This technical approach is not limited to chat but is also applicable to building real-time comment streams, live market feeds, AI assistants, and other scenarios requiring real-time interaction, enabling your web applications to deliver highly interactive, competitive user experiences.