Building a Full-Stack App with Next.js and Cloud Firestore

Getting Started with Cloud Firestore

Setting up databases has never been easier. With Firebase’s newest NoSQL database, Cloud Firestore, developers can have a database up and running in a matter of minutes. Like Firestore’s Realtime Database, Cloud Firestore is free and allows developers to store, edit, and sync data at a global scale for mobile and web applications. Combined with a web or mobile client, developers can create complete web solutions quickly and easily.

Choosing Between Firebase’s Realtime DB and Cloud Firestore

Firebase now offers two database solutions: Cloud Firestore and Realtime Database. While they seem similar, there are key differences. Choosing one over the other depends on your needs.

  • If you need a lightweight database with simple querying and know that your data will be accessed often, then go with Realtime Database.
  • If you need more advanced querying functionality along with more structure for your data, then Cloud Firestore is likely a better option.

Setting Up Cloud Firestore

To set up Cloud Firestore, start by creating a Firebase project. Then, click on Firestore Database and select Create database. Choose the production mode option and select the location closest to you to reduce data latency. Next, create credentials by generating a private key, which will be used to initialize and access the database in your Next.js app.

firebase projects:create my-project
firebase firestore:databases:create --project=my-project

Setting Up the Next.js App

Create a Next.js app and configure the database connections. Install the necessary dependencies, including firebase-admin, axios, and dashify.

npx create-next-app my-app
cd my-app
npm install firebase-admin axios dashify

Create a utility function to communicate with the database and copy the JSON file containing secret keys into the utils/db folder.

import admin from 'firebase-admin';

const db = admin.firestore();

export async function getEntries() {
  const entriesRef = db.collection('entries');
  const entries = await entriesRef.get();
  return entries.docs.map((doc) => doc.data());
}

Creating Endpoints

Create API endpoints using Next.js’s API routes solution. Create endpoints for POST, GET, PUT, and DELETE methods. Use the db object to establish communication with the database and create collections and documents.

import { NextApiRequest, NextApiResponse } from 'next';
import { db } from '../utils/db';

const entriesApi = async (req: NextApiRequest, res: NextApiResponse) => {
  switch (req.method) {
    case 'POST':
      const { title, content } = req.body;
      const entryRef = db.collection('entries').doc();
      await entryRef.set({ title, content });
      res.status(201).json({ message: 'Entry created successfully' });
      break;
    case 'GET':
      const entries = await getEntries();
      res.status(200).json(entries);
      break;
    default:
      res.status(405).json({ message: 'Method not allowed' });
  }
};

export default entriesApi;

Implementing Pages

Create pages for the /admin and /posts routes. Use dynamic routes to list all entries and navigate to specific entries. Implement the onSubmit and onDelete methods to send requests to the API endpoints.

import { useState } from 'eact';
import axios from 'axios';

const AdminPage = () => {
  const [entries, setEntries] = useState([]);
  const [newEntry, setNewEntry] = useState({ title: '', content: '' });

  const onSubmit = async (event) => {
    event.preventDefault();
    await axios.post('/api/entries', newEntry);
    setEntries([...entries, newEntry]);
    setNewEntry({ title: '', content: '' });
  };

  const onDelete = async (id) => {
    await axios.delete(`/api/entries/${id}`);
    setEntries(entries.filter((entry) => entry.id!== id));
  };

  return (

Admin Page

setNewEntry({…newEntry, title: event.target.value })} />

Leave a Reply