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:

Rust logo over black marble background.

Handling memory leaks in Rust

Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.

Ukeje Goodness
Nov 20, 2024 ⋅ 4 min read
Robot pretending to be a person.

Using curl-impersonate in Node.js to avoid blocks

Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.

Antonello Zanini
Nov 20, 2024 ⋅ 13 min read
Solving Eventual Consistency In Frontend

Solving eventual consistency in frontend

Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.

Kayode Adeniyi
Nov 19, 2024 ⋅ 6 min read
How To Use Lazy Initialization Pattern With Rust 1.80

How to use the lazy initialization pattern with Rust 1.80

Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.

Yashodhan Joshi
Nov 18, 2024 ⋅ 5 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