2022-03-08
3482
#nextjs
Doğacan Bilgili
31576
Mar 8, 2022 ⋅ 12 min read

Building a full-stack app with Next.js and Firebase’s Cloud Firestore

Doğacan Bilgili A software developer who is also into 3D-modeling and animation.

Recent posts:

Master JavaScript Date And Time: From Moment.js To Temporal

Master JavaScript date and time: From Moment.js to Temporal

JavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.

Yan Sun
Dec 4, 2024 ⋅ 9 min read
Npm Vs. Npx: What’s The Difference?

npm vs. npx: What’s the difference?

Explore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.

Fimber Elemuwa
Dec 3, 2024 ⋅ 5 min read
How To Audit And Validate AI-Generated Code Output

How to audit and validate AI-generated code output

Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.

Boemo Mmopelwa
Dec 2, 2024 ⋅ 5 min read
Building A Background Remover With Vue And Transformers.js

Building a background remover with Vue and Transformers.js

Build a real-time image background remover in Vue using Transformers.js and WebGPU for client-side processing with privacy and efficiency.

Emmanuel John
Nov 29, 2024 ⋅ 9 min read
View all posts

14 Replies to "Building a full-stack app with Next.js and Firebase’s Cloud Firestore"

  1. pages/api/entries.js should be something like this:
    import db from “../../utils/db”;

    export default async (req, res) => {
    try {
    const ref = db.collection(“entries”);
    const collections = await ref
    .orderBy(‘created’)
    .get();
    const entriesData = [];
    collections.forEach(doc => {
    entriesData.push({ …doc.data(), id: doc.id });
    })
    res.status(200).json({ entriesData });
    } catch (_) {
    res.status(400).end();
    }
    };

  2. I appreciate you taking the time to post this. It is never easy to put something out there. I just wanted to make you aware of some issues. I tried to follow this guide and ran into a lot of issues.
    – Right out of the gate the site wouldn’t load because having no argument in the catch caused a syntax error. I would recommend to anyone doing this at home to name the argument and console.log it to help with troubleshooting.
    – With that tweak, you can create a record by navigating to the admin/post page. However, since you are using `collection(‘entries’).add` in `api/entry/index.js` each new record is being assigned a document name of a random string. This breaks the selection code in `api/entry/[id].js` since it is selecting the document by the slug value. Changing that code in `api/entry/index.js` to `collection(‘entries’).doc(slug).set`solves that issue.
    – Your api/entries.js file isn’t selecting all of the existing entries. In fact, it matches the [id].js so it is requiring an id, which the edit/index.js and posts.file is not providing. Seems like a copypasta issue.
    A couple of less important housekeeping items:
    – `db.collection(‘entries’)` is repeated a lot in your api files, I would recommend setting a collection const at the top of the file and reusing that below.
    – out of the box, for some reason, next cannot seem to find the favicon and also has a console warning stating that the static directory is being depreciated and to use the public directory. Moving everything from the static directory to public solves both issues.
    – When you get them working, the `admin/edit/index.js` and `posts/index.js` components are iterating over an array of posts/entries but have no key defined. The fragment shorthand, “, should not be used when iterating, since it doesn’t support keys. Since slug is unique in your app, it will work for the key. You just need import React and use the long “ version.

    I hope this all helps and thank you again for taking a first stab at this. Even though it didn’t work out of the box, it has been a fun challenge getting it to work.

  3. Hey Keith,
    Thanks for the feedback. There were a couple of broken code blocks due to c/p errors and these were causing the issues you’ve mentioned. Now the whole article is revised and a new version will be published soon.

  4. Nice little snippets! But it would be useful to have an overview what you are going to build/building, I assume it’s a blog admin interface. Then maybe a bit about the NextJS implementation. Do you use it client side or both client/server generated code?

  5. Hey my config doesn’t have a databaseURL entry. After a lot of googling I have no idea if that matters or not. Seems like the databaseURL matters more for realtime database vs firestore but I can’t confirm if that is true. I’m planning on using firestore though 😬

  6. You should not use an async callback inside useEffect because it can cause race conditions. Instead, create an aync function inside of useEffect.

  7. Did you even ran this code ?

    I think its a terrible idea to read each documents to see if the slug is unique, if your database grow up and have like 2000 documents in it, you will need to read 2000 documents just for writting ONE SINGLE DOCUMENT !
    It very dangerous to publish a tutorial were you, because some people will simple copy/paste the code, go in prod and get 2000$ of firestore fees.

    To check if a slug is unique, you can simply name your document with the slug. So you can just list all the document (in one single read) and with that you can read the documents id and check if the document id match with your slug.

    Here is my code to do that:

    pages/api/entry/index.js

    import dn from “../../../utils/db”;

    export default async (req,res) => {
    console.log(“executed”);
    try{
    const {slug} = req.body
    const posts = await db.collection(‘posts’).get();// change the name of the collection
    var exist = false;
    posts.forEach((post)=> {if(post.id == slug){exist = true}})// check if the slug exist

    if ( exist ){
    //console.log(“slug exist”);
    res.status(200);
    }else{
    const {id} = await db.collection(“posts”).doc(slug).set({// doc(slug) will name (set the id of the doc) with the slug
    …req.body,
    created: new Date().toISOString(),
    })
    res.status(200).json({id});
    }

    }catch(e){
    console.log(e);
    res.status(400).end();
    }
    }

  8. as good as this project sounds, not including a live demo or a snippet of what we’re looking to build is wrong.

  9. It looks to me like you are using service credentials to completely bypass user authentication, but Next.js API routes are publicly accessible. In a browser they are protected by CORS maybe, but the routes can still be called from a non-browser environment. So in other words, I think this example code has a huuuge vunerability.

Leave a Reply