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.
- Create a Firebase Project:
- Go to the Firebase Console, click on “Add Project,” and follow the steps to create a new Firebase project.
- Install Firebase SDK:
In your Next.js project, install the Firebase SDK to connect with Firebase services:
npm install firebase
- Configure Firebase:
In your Firebase project settings, find your Firebase config details (API keys, project ID, etc.). Then, create a filefirebase.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.
- 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.
- 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();
};
- 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.
- 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();
};
- 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.
- 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
- 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' };
});
- 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.