GitHub Repository: https://github.com/EnterFlash/online-store-nuxt3
In the past tutorial, we created a shopping cart that persists information in the browser's local storage. In case you didn't follow that tutorial, you can here:
https://enterflash.io/posts/how-to-create-a-shopping-cart---online-store-with-nuxt-3--firebase
However, products were hard-coded in the Vue component. We are now going to bring them from the Firestore Database.
Using Admin SDK instead of client-side Firestore
The main reason we are going to be using the Admin SDK to bring the data from Firestore DB, instead of using the client-side library, is because later when we implement authentication in our app, I'd prefer not to use Firebase Authentication with Nuxt.
The reason I don't want to use Firebase Auth with Nuxt.js 3 is that Firebase Auth is mainly a client-side library, while Nuxt.js is a server-side rendered framework. While Firebase Auth would be very easy to implement with a client-side framework like Vue.js, to use it in Nuxt means I'd have to do some extra work. Instead, I'll just be using some authentication package for Nuxt like @nuxt/auth
Setting up the Firestore DB
Let's start by creating our Firebase project using the Console here:
https://console.firebase.google.com/
Go ahead and hit Add Project, add any name you want, enable or disable analytics, and hit Create.
Then, visit the Firebase Firestore section and enable your database to select the location that best fits you.
Once you create your database, you're going to see some tabs in the top part. Visit the Rules tab and make sure you are denying all access to all documents and collections.
This section would be useful if we were using the Firestore client-side library where permissions in the backend matter. We are using the Firebase Admin SDK, though, so we are granted all permissions already.
Once you do this, go back to the Data section and add a new collection called "products".
In this collection, we are going to add four dummy products that we are going to use to test. Each product will contain a name, description, photoURL, and price just like you see in the picture below:
Then, we are going to generate the credentials that we are going to use to connect from our server in Nuxt.js to this database. To do this, click on the settings icon and select:
Project Settings > Service Accounts
And click on Generate new private key
This is going to download a JSON file that contains the credentials. Make sure you add it to your .gitignore file to not get pushed into your git version control.
Creating the products API route
Add a new folder in the root of your project called "server". Everything you put in here will be a new route. Then, we are going to add another folder called "api" inside. And finally, add a file called "products.ts". This will create a route with path /api/products where we are going to list the products that we got from Firestore in JSON format.
In our products.ts file, we'll be first initializing the Admin SDK in case it hasn't been initialized. To do this, we use the getApps( ) function.
Then, in our main function we'll be bringing all the documents from the "products" collection, and using a map( ) method we turn them into objects with a UUID.
// ~/server/api/products.tsimport { getFirestore } from 'firebase-admin/firestore'import { initializeApp, getApps, cert } from 'firebase-admin/app'const apps = getApps()if (!apps.length) { initializeApp({ credential: cert('./certs.json') // 👈 Path to your JSON Firebase certificate })}export default async (request, response) => { const db = getFirestore() const productsSnap = await db.collection('products').get() const productsData = productsSnap.docs.map(doc => { return { uuid: doc.id, ...doc.data() } }) return productsData}
Now the "productsData" constant contains an array of objects that will be returned to the front end. To see the results access the route http://localhost:3000/api/products after running this command:
$ npm run dev
Now that we have an API route that brings all the products from Firebase, we'll be putting this JSON into the frontend to list real products instead of the hard-coded ones.
To do this, go to the index.vue file in the pages folder and at the very top, insert a <script setup> tag where we are going to use the useFetch( ) function to request the products.
// ~/pages/index.vue<script setup>/* This brings the products from /api/products and saves them in the "data" constant 👇 */const { data } = await useFetch('/api/products')</script><template> ...
Once this is done, you can now use the "data" constant in your HTML inside the <template> tag. We'll be using it in the v-for that lists the products. (Remember this step was done in the previous tutorial)
...<template> <div class="container"> <div class="row"> <div v-for="(product, index) in data" :key="'product-' + index" class="col-md-4"> ...
Remember you can always reference the code in the GitHub repository:
https://github.com/EnterFlash/online-store-nuxt3/
In the next post, you'll be learning how to Dockerize this application to later create a CI/CD with GitHub actions so stay tuned for that.