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:

Comparing Mutative Vs Immer Vs Reducers For Data Handling In React

Comparing React state tools: Mutative vs. Immer vs. reducers

Mutative processes data with better performance than both Immer and native reducers. Let’s compare these data handling options in React.

Rashedul Alam
Apr 26, 2024 ⋅ 7 min read
Radix Ui Adoption Guide Overview Examples And Alternatives

Radix UI adoption guide: Overview, examples, and alternatives

Radix UI is quickly rising in popularity and has become an excellent go-to solution for building modern design systems and websites.

Nefe Emadamerho-Atori
Apr 25, 2024 ⋅ 11 min read
Understanding The Css Revert Layer Keyword, Part Of Css Cascade Layers

Understanding the CSS revert-layer keyword

In this article, we’ll explore CSS cascade layers — and, specifically, the revert-layer keyword — to help you refine your styling strategy.

Chimezie Innocent
Apr 24, 2024 ⋅ 6 min read
Exploring Nushell, A Rust Powered, Cross Platform Shell

Exploring Nushell, a Rust-powered, cross-platform shell

Nushell is a modern, performant, extensible shell built with Rust. Explore its pros, cons, and how to install and get started with it.

Oduah Chigozie
Apr 23, 2024 ⋅ 6 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