Basic tips for your first Firebase project

Last updated

Antonio Ufano avatar

Antonio Ufano

A couple of weeks ago I decided that I wanted to build and launch a new project in a few days. To achieve that, I'd need to simplify as much as possible my tasks so I thought it was the perfect moment to learn Firebase and use it in a project for the first time. The project is still under development but so far I've learnt a few lessons I'd like to share.

Why should you use Firebase?

The main reason I had to use Firebase was curiosity. I've been wanting to try it for a while now and with the launch of AWS Amplify (which is pretty similar) my curiosity kicked in again. But other factors can make you decide to choose Firebase. For example:

  • Free plan: The free tier is good enough to build and run a small side project. It will give you 50k document reads, 20k document writes 20k document deletes, 1GB of stored data and 10GB of network. See free plan details

  • Fast developing experience: writing an app from scratch requires a lot of time if you're writing every single piece of code. Just all the authentication workflows can take you a week so having all that out of the box is a huge plus. With Firebase I just had to install a dependency in my front end, and forget about any back end code for authentication, APIs or data storage etc. The only thing I've had to write is Firestore rules (the ones used to control who can do what in your database) and those are super simple to use.

  • Documentation: the official docs are great and even include some Youtube video series like this one for Firestore. Also, there are tons of articles and videos on Youtube. My favourite is probably the Fireship.io channel.

  • Super simple deployments: With the Firebase CLO, deploying a Firebase project is as simple as running firebase deploy. No need to set up webhooks, clone your repo or anything like that. Just running a script and seeing your project live on a .web.app domain, even with SSL enabled is awesome.

My 8 tips when working with Firebase

I hope you find the reasons above enough compelling to try Firebase but before that, let me tell you a few tips that I think would make your project development event better:

Use the Firebase CLI and VSCode extensions

You can install the CLI running npm i firebase-tools -g and then authenticate running firebase login with your Google credentials (did I mentioned Firebase is owned by Google?). In addition, the two VSCode extensions I installed are Firebase Explorer and Firestore Rules.

Create two Firebase projects

In order to keep your develop and production environments completely isolated, I'd create two different projects in Firebase (for example myAwesomeApp and myAwesomeApp-dev). Each project will have its own database, hosting and, more important, its own quotas so all the tests you'll do will not affect your live environment. You can create the project using the Firebase CLI or, better, create them manually in the Firebase Console website.

Vuejs + Firebase project scaffold

As mentioned earlier, the project I'm creating is a web built with Vuejs so to start I ran vue create my-project-name. Then inside the project folder, run firebase init and selected the features you want, like Hosting or Firestore . Next, choose the development project you created in the previous step and finally, the CLI will ask you for the files where it'll define the Firestore rules and indexes. Once your project is scaffolded, you can do your first deployment!

Setup deployment scripts for each environment/project

Once your Firebase project is initialized, you can deploy it running firebase deploy. This is ok to deploy to the Firebase project you chose when you initialized the project, but as we want to target different projects (remember we have develop and production), I suggest to create different scripts in your package.json file. Here are the ones I have:

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "deploy-rules-dev": "firebase deploy --project myAwesomeApp-dev --only firestore:rules",
    "deploy-rules-production": "firebase deploy --project myAwesomeApp --only firestore:rules",
    "deploy-functions-dev": "firebase deploy --project myAwesomeApp-dev --only functions",
    "deploy-functions-production": "firebase deploy --project myAwesomeApp --only functions",
    "deploy-dev": "vue-cli-service build --mode development && firebase deploy --project myAwesomeApp-dev",
    "deploy-production": "vue-cli-service build --mode production && firebase deploy --project myAwesomeApp"
  },

As you can see the firebase CLI has different flags we can use:

  • --project is used to select our target project
  • --only is used to select which part of our project we want to deploy.

Use environment variables

This is very obvious but you should use environment variables to load you Firebase project keys or other variables that would be different in each environment. For example, initialise your app like this:

// ⛔️ DONT
const firebaseApp = firebase.initializeApp({
  apiKey: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  authDomain: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  databaseURL: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  projectId: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  storageBucket: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  messagingSenderId: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  appId: 'xxxXXXXXxxXXXXxxXXXXxxxx',
  measurementId: 'xxxXXXXXxxXXXXxxXXXXxxxx',
})
// ✅ DO
const firebaseApp = firebase.initializeApp({
  apiKey: process.env.VUE_APP_APIKEY,
  authDomain: process.env.VUE_APP_AUTHDOMAIN,
  databaseURL: process.env.VUE_APP_DATABASEURL,
  projectId: process.env.VUE_APP_PROJECTID,
  storageBucket: process.env.VUE_APP_STORAGEBUCKET,
  messagingSenderId: process.env.VUE_APP_MESSAGINGSENDERID,
  appId: process.env.VUE_APP_APPID,
  measurementId: process.env.VUE_APP_,
})

In my case, I'm using Vuejs so I just need to create two files named .env.development and .env.production locally and whenever I run npm run build, it will automatically replace the environment variables with the values from the correspondent file. You can read more about Vuejs environment variables here.

Think twice your data model and don't be afraid to duplicate

Before you start coding, think about how your app is going to look like, which data you are going to need in each page and which pages are going to be more used. This is pretty important because it will affect the way you'll store your data in Firestore (the noSQL database used in Firebase) or the Real Time Database.

As one of the limitations of the free tier is the number of documents your app reads and writes, consider doing it just when you need it.

One of the things that have made me save a ton of document reads is duplication of some fields. This is something not very common in relational databases (I'd say it's even forbidden 😅) where we use foreign keys and join queries but it's pretty normal in noSQL databases. You can read more about data modelling and view some videos in this section of the docs.

Create functions for your Firestore rules

Once you start defining Firestore rules, there are two functions that you'll use all the time:

  • validate if the request comes from a logged user
  • validate if the user accessing a document is the one who created it

For that, you can create the following functions in your firestore.rules file:

//**** Functions   ****//
function isLoggedIn() {
  return request.auth != null
}
function isOwner() {
  return request.auth.id == resource.data.uid
}

You can find more info about security rules here.

Paginate and limit your queries

This comes back to the limitations of the free tier. Just remember to add a limit(x) to your collection queries whenever you are going to access your data. You don't want to return 150 documents when on your page you can only display 20. Pagination is super simple to build thanks to the startAfter() method. Find below an example of how I'm doing pagination in my Vuejs app:

// part of store/index.js file

// global variable to store last paginated element
let paginationLast = null

// Vuex store action
getUpcomingTalks({ commit }, payload) {
  return new Promise((resolve, reject) => {
    talksCollection
      .orderBy('date', 'asc')
      .limit(payload.limit || 12)
      .startAfter(paginationLast)
      .get()
      .then((res) => {
        if (res.docs.length > 0) {
          // save last item for pagination
          paginationLast = res.docs[res.docs.length - 1]

          commit('GET_UPCOMING_TALKS', res.docs)
          return resolve()
        } else {
          reject({ hasMore: false })
        }
      })
      .catch((err) => {
        console.log('err in action :>> ', err)
        return reject()
      })
  })
},

Just remember:

  • limit will limit the number of documents returned, pretty straight forward
  • startAfter will tell Firestore what is the latest document you queried before. In my case, the first time I'll send it null, so it will start at the beginning of the collection. Then after each successful query, I update it with the last item so the following queries will start from it. Note that this has to be a document reference, not an id.

Conclusion

I still have a ton of things to learn about Firebase but I'd say these are the more important things I've learnt so far. Hope you find them useful.

If you enjoyed this article consider sharing it on social media or buying me a coffee ✌️

Oh! and don't forget to follow me on Twitter where I share tons of dev tips 🤙

Other articles that might help you

my projects

Apart from writing articles in this blog, I spent most of my time working on my personal projects.

lifeboard.app logo

theLIFEBOARD.app

theLIFEBOARD is a weekly planner that helps people achieve their goals, create new habits and avoid burnout. It encourages you to plan and review each week so you can easily identify ways to improve your productivity while keeping track of your progress.

Request early access
soliditytips.com logo

SolidityTips.com

I'm very interested in blockchain, smart contracts and all the possiblilities chains like Ethereum can bring to the web. SolidityTips is a blog in which I share everything I learn about Solidity and Web3 development.

Check it out if you want to learn Solidity
quicktalks.io logo

Quicktalks.io

Quicktalks is a place where indie hackers, makers, creators and entrepreneurs share their knowledge, ideas, lessons learned, failures and tactics they use to build successfull online products and businesses. It'll contain recorded short interviews with indie makers.

Message me to be part of it