- Published on
How to Build a Next.js 15 API with Firebase in 15 Minutes
To build a simple API (Application Programming Interface) with Next.js 15 and Firebase, you can create server-side functions called Route Handlers that interact with the Firestore database. By using the Firebase Admin SDK, you can set up a secure connection in under 15 minutes to perform CRUD (Create, Read, Update, Delete) operations. This setup allows your web application to store and retrieve data instantly without managing a traditional backend server.
What tools do you need to get started?
Before writing any code, you need to have a few basic tools installed on your computer. These tools provide the environment where your code runs and the libraries that handle the heavy lifting.
- Node.js 20 or higher: This is the runtime that allows you to run JavaScript outside of a web browser.
- A Code Editor: We recommend Visual Studio Code, which is the standard for most developers today.
- A Google Account: You need this to access the Firebase Console and create your database project.
- Terminal Knowledge: You should know how to open your computer's terminal (or command prompt) and type basic commands.
How do you create a new Next.js project?
Next.js is a framework (a collection of pre-made tools and rules) for building modern websites using React. To start, open your terminal and run the following command to create a fresh project.
npx create-next-app@latest my-firebase-api
During the setup, the terminal will ask you several questions. For this guide, choose "Yes" for TypeScript, "Yes" for ESLint, "Yes" for Tailwind CSS, and "Yes" for the App Router. The App Router is the modern way to handle pages and API routes in Next.js 15.
Once the installation finishes, move into your project folder by typing cd my-firebase-api. You can now open this folder in your code editor to begin the configuration.
How do you configure Firebase for your API?
Firebase is a platform by Google that provides a database called Firestore. Firestore is a NoSQL database, which means it stores data in "documents" rather than strict tables and rows.
Go to the Firebase Console and click "Add project." Give your project a name and click through the setup screens. You do not need Google Analytics for this simple project, so you can disable it if you prefer.
Once your project is ready, click the gear icon and select "Project settings." Navigate to the "Service accounts" tab and click "Generate new private key." This will download a JSON file containing your secret credentials.
Keep this file safe and never share it publicly. It acts like a master key to your database. We will use the information inside this file to connect your Next.js code to Firebase.
How do you connect Next.js to Firebase?
To make the connection work, you need to install the Firebase Admin SDK (Software Development Kit). The Admin SDK is a library that gives your server-side code full permission to talk to your database.
Run this command in your terminal:
npm install firebase-admin
Next, create a file named .env.local in the root of your project. Copy the values from your downloaded JSON service account file into this environment file like this:
FIREBASE_PROJECT_ID="your-project-id"
FIREBASE_CLIENT_EMAIL="your-client-email"
FIREBASE_PRIVATE_KEY="your-private-key-string"
Now, create a folder called lib inside your src directory and add a file named firebaseAdmin.ts. This file will act as the bridge between your app and Google's servers.
import admin from 'firebase-admin';
// This check prevents the app from creating multiple connections
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert({
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
// We replace escaped newlines to ensure the key reads correctly
privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
}),
});
}
const db = admin.firestore();
export { db };
How do you build your first API Route?
In Next.js, you create an API by creating a folder inside src/app/api. For example, if you want an endpoint at /api/users, you create a folder named users with a file inside called route.ts.
Let's write a "POST" handler to save a new user to our database. This function will take data sent by a user and write it into a Firestore collection.
import { NextResponse } from 'next/server';
import { db } from '@/lib/firebaseAdmin';
export async function POST(request: Request) {
try {
// We parse the incoming JSON data from the request
const body = await request.json();
// Add a new document to the "users" collection
const docRef = await db.collection('users').add({
name: body.name,
email: body.email,
createdAt: new Date().toISOString(),
});
// Return a success message with the new ID
return NextResponse.json({ id: docRef.id, message: "User created!" }, { status: 201 });
} catch (error) {
// If something goes wrong, we send back an error message
return NextResponse.json({ error: "Failed to create user" }, { status: 500 });
}
}
To test this, you can use a tool like Postman or the "Thunder Client" extension in VS Code. Send a JSON object with a name and email to http://localhost:3000/api/users. If everything is set up correctly, you will see a success message and a new entry in your Firebase Console.
How do you fetch data from the API?
Creating data is only half the battle; you also need to read it. We can add a "GET" handler to the same route.ts file to retrieve all users from the database.
Add this code below your POST function:
export async function GET() {
try {
// Get all documents from the "users" collection
const snapshot = await db.collection('users').get();
// Map through the documents to create a clean list
const users = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
return NextResponse.json(users, { status: 200 });
} catch (error) {
return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 });
}
}
Now, when you visit http://localhost:3000/api/users in your browser, you will see a list of all the users you have added. It's normal to feel a bit overwhelmed by the syntax at first, but the pattern of "Request -> Database -> Response" stays the same for almost every API you build.
What are some common gotchas to avoid?
When we first started building with these tools, we noticed a few recurring issues that beginners often face. Don't worry if you run into these; they are easy to fix once you know what to look for.
- Missing Environment Variables: If your API returns a 500 error immediately, double-check your
.env.localfile. Ensure the private key is exactly as it appears in the JSON file, including the "BEGIN PRIVATE KEY" and "END PRIVATE KEY" parts. - Firestore Permissions: When you create your database in the Firebase Console, make sure you start in "Test Mode" or set your rules to allow reads and writes. If rules are too strict, the Admin SDK can usually bypass them, but it's good practice to check your database tab.
- Cold Starts: If you are using a free hosting plan, your first API call might take a few seconds to wake up. This is normal behavior for "serverless" functions.
- Case Sensitivity: Next.js routing is case-sensitive. If your folder is named
api/users, callingapi/Userswill result in a 404 "Not Found" error.
Next Steps
Now that you have a working API, you can expand it by adding routes to delete or update users. You might also explore how to protect your API so only logged-in users can access it.
Experimenting with different data structures in Firestore is a great way to learn. Try adding a "posts" collection or a "comments" collection to see how the data relates to each other.
For more detailed information, check out these resources:
- Learn more about Next.js Route Handlers.
- Explore the Firebase Admin SDK documentation.
- For more guides, visit the official Next.Js documentation.