Building a Full-Stack App with Next.js and Firebase

Published at: July 18, 2021

Building a full-stack application doesn’t have to be complex or require managing separate backend services. Next.js and Firebase make it easy to build a full-stack app with real-time features, authentication, and serverless functions — all in one place.

In this post, we’ll walk through how to build a full-stack app using Next.js for the frontend and Firebase for the backend. We’ll cover Firebase authentication, the Firebase real-time database, and Firebase serverless functions to handle business logic and data management.

Prerequisites

Before we dive in, here’s what you’ll need:

  • A Firebase account. You can create one for free at Firebase Console.
  • Basic knowledge of Next.js and React.
  • Firebase setup in your Next.js project.

Let’s get started!


1. Setting Up Firebase

To begin, you’ll need to create a Firebase project and configure it within your Next.js app.

  1. Create a Firebase Project:
  • Go to the Firebase Console, click on “Add Project,” and follow the steps to create a new Firebase project.
  1. Install Firebase SDK:
    In your Next.js project, install the Firebase SDK to connect with Firebase services:
   npm install firebase
  1. Configure Firebase:
    In your Firebase project settings, find your Firebase config details (API keys, project ID, etc.). Then, create a file firebase.js in your project to initialize Firebase:
   import firebase from 'firebase/app';
   import 'firebase/auth';
   import 'firebase/database';  // For real-time database

   // Firebase config from the Firebase Console
   const firebaseConfig = {
     apiKey: 'your-api-key',
     authDomain: 'your-auth-domain',
     databaseURL: 'your-database-url',
     projectId: 'your-project-id',
     storageBucket: 'your-storage-bucket',
     messagingSenderId: 'your-sender-id',
     appId: 'your-app-id',
   };

   if (!firebase.apps.length) {
     firebase.initializeApp(firebaseConfig);
   } else {
     firebase.app(); // If already initialized
   }

   export default firebase;

2. Setting Up Firebase Authentication

Firebase Authentication is a service that can help you easily set up user authentication. We’ll use it to manage user login and signup in our Next.js app.

  1. Enable Authentication Providers in Firebase:
  • Go to your Firebase Console > Authentication > Sign-In Method.
  • Enable Email/Password or any other method (like Google) that you want to use.
  1. Creating Auth Functions: In your firebase.js file, export authentication methods like signup and login:
   export const signup = async (email, password) => {
     try {
       await firebase.auth().createUserWithEmailAndPassword(email, password);
     } catch (error) {
       console.error('Error signing up: ', error);
     }
   };

   export const login = async (email, password) => {
     try {
       await firebase.auth().signInWithEmailAndPassword(email, password);
     } catch (error) {
       console.error('Error logging in: ', error);
     }
   };

   export const logout = () => {
     firebase.auth().signOut();
   };
  1. Using Authentication in Next.js Pages: For simplicity, we’ll create a signup page where users can sign up using their email and password.
   import { useState } from 'react';
   import { signup } from '../firebase';

   const Signup = () => {
     const [email, setEmail] = useState('');
     const [password, setPassword] = useState('');

     const handleSignup = async () => {
       await signup(email, password);
     };

     return (
       <div>
         <h1>Sign Up</h1>
         <input
           type="email"
           value={email}
           onChange={(e) => setEmail(e.target.value)}
           placeholder="Email"
         />
         <input
           type="password"
           value={password}
           onChange={(e) => setPassword(e.target.value)}
           placeholder="Password"
         />
         <button onClick={handleSignup}>Sign Up</button>
       </div>
     );
   };

   export default Signup;

3. Using Firebase Realtime Database

Firebase Realtime Database is a NoSQL cloud database that supports data syncing in real-time. It is perfect for building real-time apps, like chat apps, collaborative to-do lists, or anything that requires live updates.

  1. Storing Data in Firebase Realtime Database: To save and retrieve data from the Firebase Realtime Database, we can use the firebase.database() API. Example of saving data:
   export const saveData = (data) => {
     const databaseRef = firebase.database().ref('items');
     databaseRef.push(data);
   };

Example of fetching data:

   export const fetchData = async () => {
     const databaseRef = firebase.database().ref('items');
     const snapshot = await databaseRef.once('value');
     return snapshot.val();
   };
  1. Displaying Data in Next.js: Let’s build a page that fetches and displays real-time data from Firebase.
   import { useEffect, useState } from 'react';
   import { fetchData } from '../firebase';

   const ItemsList = () => {
     const [items, setItems] = useState([]);

     useEffect(() => {
       const getItems = async () => {
         const data = await fetchData();
         setItems(data);
       };
       getItems();
     }, []);

     return (
       <div>
         <h1>Items List</h1>
         <ul>
           {Object.values(items || {}).map((item, index) => (
             <li key={index}>{item.name}</li>
           ))}
         </ul>
       </div>
     );
   };

   export default ItemsList;

4. Creating Serverless Functions with Firebase

Firebase offers Cloud Functions that allow you to write server-side logic that gets executed in a serverless environment. These functions can be used for tasks like sending emails, interacting with third-party APIs, or complex data manipulation.

  1. Setting Up Firebase Functions: To get started with Firebase Functions, you need to install Firebase CLI and initialize Firebase functions:
   npm install -g firebase-tools
   firebase login
   firebase init functions
  1. Creating a Simple Cloud Function: Once Firebase Functions are initialized, create a file functions/index.js to add a simple function:
   const functions = require('firebase-functions');
   const admin = require('firebase-admin');
   admin.initializeApp();

   exports.addItem = functions.https.onCall(async (data, context) => {
     const newItem = data.item;
     const ref = admin.database().ref('items');
     await ref.push(newItem);
     return { message: 'Item added successfully' };
   });
  1. Calling the Cloud Function from Next.js: You can now call the Firebase function in your Next.js app to add an item to the database:
   import { useState } from 'react';
   import firebase from '../firebase';

   const AddItem = () => {
     const [itemName, setItemName] = useState('');

     const handleAddItem = async () => {
       const addItem = firebase.functions().httpsCallable('addItem');
       await addItem({ item: { name: itemName } });
     };

     return (
       <div>
         <input
           type="text"
           value={itemName}
           onChange={(e) => setItemName(e.target.value)}
           placeholder="Item Name"
         />
         <button onClick={handleAddItem}>Add Item</button>
       </div>
     );
   };

   export default AddItem;

Conclusion

By combining Next.js and Firebase, you can build a complete full-stack app that handles user authentication, real-time data updates, and backend business logic using serverless functions. This approach significantly reduces the complexity of building full-stack applications and allows you to focus on what matters most: delivering a great user experience.

With Next.js providing server-side rendering and static site generation, and Firebase offering powerful backend services, this combination is a great choice for building modern web applications in 2021.


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 *