Hit The Ground Running With Vue.js And Firestore

Hit The Ground Running With Vue.js And Firestore

Hit The Ground Running With Vue.js And Firestore

Lukas van Driel

Google Firebase has a new data storage possibility called ‘Firestore’ (currently in beta stage) which builds on the success of the Firebase Realtime Database but adds some nifty features. In this article, we’ll set up the basics of a web app using Vue.js and Firestore.

Let’s say you have this great idea for a new product (e.g. the next Twitter, Facebook, or Instagram, because we can never have too much social, right?). To start off, you want to make a prototype or Minimum Viable Product (MVP) of this product. The goal is to build the core of the app as fast as possible so you can show it to users and get feedback and analyze usage. The emphasis is heavily on development speed and quick iterating.

But before we start building, our amazing product needs a name. Let’s call it “Amazeballs.” It’s going to be legen — wait for it — dary!

Here’s a shot of how I envision it:

Screenshot of Amazeballs app
The legendary Amazeballs app

Our Amazeballs app is — of course — all about sharing cheesy tidbits of your personal life with friends, in so-called Balls. At the top is a form for posting Balls, below that are your friends’ Balls.

When building an MVP, you’ll need tooling that gives you the power to quickly implement the key features as well as the flexibility to quickly add and change features later on. My choice falls on Vue.js as it’s a Javascript-rendering framework, backed by the Firebase suite (by Google) and its new real-time database called Firestore.

Firestore can directly be accessed using normal HTTP methods which makes it a full backend-as-a-service solution in which you don’t have to manage any of your own servers but still store data online.

Sounds powerful and daunting, but no sweat, I’ll guide you through the steps of creating and hosting this new web app. Notice how big the scrollbar is on this page; there’s not a huge amount of steps to it. Also, if you want to know where to put each of the code snippets in a code repository, you can see a fully running version of Amazeballs on github.

Let’s Start

We’re starting out with Vue.js. It’s great for Javascript beginners, as you start out with HTML and gradually add logic to it. But don’t underestimate; it packs a lot of powerful features. This combination makes it my first choice for a front-end framework.

Vue.js has a command-line interface (CLI) for scaffolding projects. We’ll use that to get the bare-bones set-up quickly. First, install the CLI, then use it to create a new project based on the “webpack-simple” template.

npm install -g vue-cli

vue init webpack-simple amazeballs

If you follow the steps on the screen (npm install and npm run dev) a browser will open with a big Vue.js logo.

Congrats! That was easy.

Next up, we need to create a Firebase project. Head on over to https://console.firebase.google.com/ and create a project. A project starts out in the free Spark plan, which gives you a limited database (1 GB data, 50K reads per day) and 1 GB of hosting. This is more than enough for our MVP, and easily upgradable when the app gains traction.

Click on the ‘Add Firebase to your web app’ to display the config that you need. We’ll use this config in our application, but in a nice Vue.js manner using shared state.

First npm install firebase, then create a file called src/store.js. This is the spot that we’re going to put the shared state in so that each Vue.js component can access it independently of the component tree. Below is the content of the file. The state only contains some placeholders for now.

import Vue from 'vue';
import firebase from 'firebase/app';
import 'firebase/firestore';

// Initialize Firebase, copy this from the cloud console
// Or use mine :)
var config = {
  apiKey: "AIzaSyDlRxHKYbuCOW25uCEN2mnAAgnholag8tU",
  authDomain: "amazeballs-by-q42.firebaseapp.com",
  databaseURL: "https://amazeballs-by-q42.firebaseio.com",
  projectId: "amazeballs-by-q42",
  storageBucket: "amazeballs-by-q42.appspot.com",
  messagingSenderId: "972553621573"

// The shared state object that any vue component can get access to. 
// Has some placeholders that we’ll use further on!
export const store = {
  ballsInFeed: null,
  currentUser: null,
  writeBall: (message) => console.log(message)

Now we’ll add the Firebase parts. One piece of code to get the data from the Firestore:

// a reference to the Balls collection
const ballsCollection = firebase.firestore()

// onSnapshot is executed every time the data
// in the underlying firestore collection changes
// It will get passed an array of references to 
// the documents that match your query
  .onSnapshot((ballsRef) => {
    const balls = [];
    ballsRef.forEach((doc) => {
      const ball = doc.data();
      ball.id = doc.id;
    store.ballsInFeed = balls;

And then replace the writeBall function with one that actually executes a write:

writeBall: (message) => ballsCollection.add({
  createdOn: new Date(),
  author: store.currentUser,

Notice how the two are completely decoupled. When you insert into a collection, the onSnapshot is triggered because you’ve inserted an item. This makes state management a lot easier.

Now you have a shared state object that any Vue.js component can easily get access to. Let’s put it to good use.

Post Stuff!

First, let’s find out who the current user is.

Firebase has authentication APIs that help you with the grunt of the work of getting to know your user. Enable the appropriate ones on the Firebase Console in AuthenticationSign In Method. For now, I’m going to use Google Login — with a very non-fancy button.

Screenshot of login page with Google authentication
Authentication with Google Login

Firebase doesn’t give you any interface help, so you’ll have to create your own “Login with Google/Facebook/Twitter” buttons, and/or username/password input fields. Your login component will probably look a bit like this:

Now there’s one more piece of the login puzzle, and that’s getting the currentUser variable in the store. Add these lines to your store.js:

// When a user logs in or out, save that in the store
firebase.auth().onAuthStateChanged((user) => {
  store.currentUser = user;

Due to these three lines, every time the currently-logged-in user changes (logs in or out), store.currentUser also changes. Let’s post some Balls!

Screenshot of logout option
Login state is stored in the store.js file

The input form is a separate Vue.js component that is hooked up to the writeBall function in our store, like this: