Building a Real-Time Chat App with Next.js & Firebase

Published: 1 July 2023

Introduction

Building a real-time chat app can be an exciting project to dive into, and using Next.js and Firebase is one of the most powerful combinations for quickly building such applications. Firebase offers real-time databases (like Firestore) and authentication features that integrate seamlessly with Next.js, making it an excellent choice for fast, scalable, and highly interactive apps.

In this tutorial, we’ll walk through the process of building a simple real-time chat application with Next.js and Firebase, leveraging Firebase for user authentication, real-time message updates with Firestore, and implementing basic message storage.


Why Choose Next.js & Firebase for a Real-Time Chat App?

  • Next.js: A powerful React framework for building fast, server-rendered apps with ease. It comes with features like API routes, SSR, SSG, and ISR, which make it an excellent choice for building web applications that need scalability and performance.
  • Firebase: Firebase provides easy-to-use services like Firestore, which is a NoSQL database that supports real-time data syncing across clients. It also offers authentication out of the box, making it ideal for quickly handling user login and security in your chat app.

Step-by-Step Guide to Building a Real-Time Chat App

Let’s dive into the steps to build our real-time chat application. In this app, we’ll focus on:

  1. Setting up Firebase for authentication and real-time messaging.
  2. Building the Next.js app to handle the frontend logic and real-time updates.

Step 1: Set Up Firebase Project

To get started, we’ll need to create a Firebase project.

  1. Go to Firebase Console: Head to Firebase Console and create a new project.
  2. Enable Firestore: In the Firebase console, go to Firestore Database and create a new Firestore database.
  3. Enable Firebase Authentication: Set up Firebase Authentication by going to the Authentication tab in the Firebase Console and enabling your preferred authentication method (e.g., Google, Email/Password).
  4. Install Firebase SDK: In your Next.js project, install the Firebase SDK.
npm install firebase

Step 2: Initialize Firebase in Your Project

Create a file for Firebase configuration and initialization. Typically, this file will contain the Firebase project details and initialize Firestore and Authentication.

Create a firebase.js file in the lib folder of your Next.js project.

// lib/firebase.js
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

const firebaseConfig = {
  apiKey: 'YOUR_API_KEY',
  authDomain: 'YOUR_AUTH_DOMAIN',
  projectId: 'YOUR_PROJECT_ID',
  storageBucket: 'YOUR_STORAGE_BUCKET',
  messagingSenderId: 'YOUR_MESSAGING_SENDER_ID',
  appId: 'YOUR_APP_ID',
};

// Initialize Firebase
if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
} else {
  firebase.app();
}

const auth = firebase.auth();
const firestore = firebase.firestore();

export { auth, firestore };

Step 3: Implement Firebase Authentication

Next, we need to allow users to sign in. Firebase provides various authentication methods, such as email/password and third-party authentication like Google. Here, we’ll use Google authentication as an example.

Create a Login component for the user to log in using Google.

// components/Login.js
import { auth } from '../lib/firebase';

const Login = () => {
  const handleLogin = async () => {
    const provider = new firebase.auth.GoogleAuthProvider();
    await auth.signInWithPopup(provider);
  };

  return (
    <div>
      <button onClick={handleLogin}>Log in with Google</button>
    </div>
  );
};

export default Login;

This will allow users to log in to the chat app with their Google account. Once authenticated, we will show them the chat interface.


Step 4: Build the Chat Interface

Create the Chat component that will allow authenticated users to send and receive messages in real-time.

// components/Chat.js
import { useState, useEffect } from 'react';
import { auth, firestore } from '../lib/firebase';

const Chat = () => {
  const [message, setMessage] = useState('');
  const [messages, setMessages] = useState([]);
  const [user, setUser] = useState(null);

  // Handle user authentication state
  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(setUser);
    return () => unsubscribe();
  }, []);

  // Fetch messages in real-time
  useEffect(() => {
    const unsubscribe = firestore
      .collection('messages')
      .orderBy('timestamp')
      .onSnapshot(snapshot => {
        setMessages(snapshot.docs.map(doc => doc.data()));
      });
    return () => unsubscribe();
  }, []);

  // Send a message to Firestore
  const sendMessage = async (e) => {
    e.preventDefault();
    if (message.trim()) {
      await firestore.collection('messages').add({
        text: message,
        uid: user.uid,
        displayName: user.displayName,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
      setMessage('');
    }
  };

  if (!user) return <Login />; // Show login if user is not authenticated

  return (
    <div>
      <div className="messages">
        {messages.map((msg, index) => (
          <div key={index}>
            <strong>{msg.displayName}</strong>: {msg.text}
          </div>
        ))}
      </div>

      <form onSubmit={sendMessage}>
        <input
          type="text"
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          placeholder="Type a message"
        />
        <button type="submit">Send</button>
      </form>
    </div>
  );
};

export default Chat;

Explanation:

  • Authentication State: The component listens for changes in the authentication state using onAuthStateChanged. If the user is not logged in, the login page is displayed.
  • Real-Time Messaging: We use Firestore’s real-time feature with onSnapshot() to listen for new messages. Whenever a message is added to Firestore, the component automatically updates the UI.
  • Sending Messages: When the user sends a message, it’s added to Firestore with their uid, displayName, and the message text. We also use Firestore’s server timestamp to order the messages.

Step 5: Displaying the Chat in a Next.js Page

Now, we need to display the Chat component in a page. Create a new page, for example pages/chat.js.

// pages/chat.js
import Chat from '../components/Chat';

const ChatPage = () => {
  return (
    <div>
      <h1>Chat</h1>
      <Chat />
    </div>
  );
};

export default ChatPage;

Step 6: Deploying to Vercel

After completing the app, you can deploy it to Vercel, the platform that integrates perfectly with Next.js.

  1. Push your project to a GitHub or GitLab repository.
  2. Go to Vercel and link your Git repository.
  3. Vercel will automatically deploy the app, and you’ll be able to access it with a unique URL.

Conclusion

In this guide, we’ve walked through building a real-time chat application with Next.js and Firebase. By integrating Firebase Authentication for user login and Firestore for real-time messaging, we’ve created a simple but powerful chat app that can scale as needed.

The combination of Next.js and Firebase allows for a fast, efficient, and easy-to-develop chat app, and by leveraging Firestore’s real-time updates, we can ensure smooth and seamless user interactions.

Feel free to extend this app by adding more features such as:

  • User profile management
  • Private messaging
  • Message persistence across devices

The possibilities are endless!

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *