Start codelab

Codelab Flow

What you will learn

L F Firebase Cloud Firestore

In this codelab, we're going to learn how to add Firebase to your web app and serve content from the Firebase Cloud Firestore database and make your Web App work offline as well. Cloud Firestore is magical and good for PWAs because of its offline capability!

Get Source code

Fork this Project from GitHub and open the work folder

Setting up

We shall be using Firebase in this codelab. Make sure you install firebase tools as in this guide here before we begin. Just install and leave it there.

Create a Cloud Firestore Project

Open the Firebase Console and create a new project. Click the web icon a.k.a </> to setup a web app, ignore Google Analytics if prompted.

Select Test mode for your Cloud Firestore Security Rules

To get started with the Web, select test mode and click Enable. Test Mode is good for getting started with the mobile and web client libraries, but allows anyone to read and overwrite your data. Make sure to see how to secure in cloud firestore.

Hands on

Copy the work folder in the cloud-firestore-master folder and paste it outside this folder.

The default index.html page in our work folder is already set ready to build our project for Firebase use. At the bottom of our page, we have added the Firebase and Cloud Firestore libraries we need to set up.

We also have service-worker.js in our project that allows us to add Progressive Web App offline feature with Workbox! But you could explore this doc too.

Adding Firebase to our Web app

Go to your firebase console here and select your project. Click Settings icon on the top left side just beside Project Overview and select Project Settings. Scroll down the view and click config tab. Do not close the browser tab. tab.

Make sure you are in the work folder. Open the app folder. Here we have App.css which styles up our web app and a few empty javascript files; App.js, Firestore.js and Data.js. We have a ./components/ folder where we're going to create our render component!

Open Firestore.js and copy the code snippet below to it. Replace the firebase data values with the ones in the firebase console tab you left open above.

// Initialize Cloud Firestore through Firebase
firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  databaseURL: "### DATABASE URL ###",
  projectId: '### CLOUD FIRESTORE PROJECT ID ###'
});

const db = firebase.firestore();

Enable offline data

This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline.

This code snippet does that for us. Copy and add it below the code above in firestore.js file

This code snippet does that for us. Copy and add it below the code above in firestore.js file

  // enable offline persistence
db.enablePersistence().catch(err => {
  if (err.code == "failed-precondition") {
    // Multiple tabs open, persistence can only be enabled
    // in one tab at a a time.
    // ...
  } else if (err.code == "unimplemented") {
    // The current browser does not support all of the
    // features required to enable persistence
    // ...
  }
});

  

Adding Mock data to Cloud Firestore, Data.js

Cloud Firestore stores data in Documents, which are stored in Collections. Cloud Firestore creates collections and documents implicitly the first time we add data to the collection.

The code snippet below (has short comments) allows us to create an events collection and add mock data to it on a button click. We have an array with the mock data that we send to Cloud Firestore.

NOTE In our ./index.html, we have a Button with a class name, add-data. Once clicked, ./Data.js creates a collection and adds demo data to it!

<button class="add-data">Add Demo Data</button>
This code snippet is commented to help you understand it! Read through! Copy and paste it to Data.js and save!

// a summits array of objects
let summits = [
  {
    title: "Web Summit Africa",
    description:
      "Meet passionate Students, Professionals, Designers, Developers and Educators shaping the Web in Africa!",
    rsvp: "https://pwafire.org/events"
  },
  {
    title: "Mobile Summit Africa",
    description:
      "Meet passionate Students, Professionals, Designers, Developers and Educators shaping the Web in Africa!",
    rsvp: "https://pwafire.org/events"
  },
  {
    title: "AI Summit Africa",
    description:
      "Meet passionate Students, Professionals, Designers, Developers and Educators shaping the Web in Africa!",
    rsvp: "https://pwafire.org/events"
  },
  {
    title: "Jenga Summit Africa",
    description:
      "Meet passionate Students, Professionals, Designers, Developers and Educators shaping the Web in Africa!",
    rsvp: "https://pwafire.org/events"
  }
];

// get the "add mock data" button
const add = document.querySelector(".add-data");

// post data on click
add.addEventListener("click", event => {
event.preventDefault();
 
  let result = confirm(
    "Click OK if ONLY you've updated Data.js with new data to prevent duplicates!"
  );

  // if Ok, add data!
  if (result) {
    // loop to get each summit from Data.json fetch
    for (let summit of summits) {
      // add a new document with a generated id.
      db.collection("events")
        .add({
          title: summit.title,
          description: summit.description,
          rsvp: summit.rsvp,
         timestamp: firebase.firestore.FieldValue.serverTimestamp()
        })
        .then(doc => {
          console.log("Document written with ID: ", doc.id);
        })
        .catch(error => {
          console.error("Error adding document: ", error);
        });
    }
  }
});

Creating the render Component!

Go to the ./components/Event.js file in your editor! Here is where we're going to create the Render Component.

This App is entirely Vanilla es6 App and makes use of es6 Modules. So we'll create and expose our Component globally via export which is then imported for use in ./App js

Learn more about JavaScript Modules in es6 in this doc by Maye

In the ./app/components folder, open Event.js file and copy the code snippet below to it.

export const Event = doc => {
  // return component
  const event = document.createElement("section");

  event.innerHTML = `
    <div class="event">
      <a href="${doc.data().rsvp}">
         <h2 class="title">${doc.data().title}
       </a>
        <p>${doc.data().description}

</div> `; return event; };

Importing Render Component!

Go to the ./App.js file in your editor! Here is where we're going to import the Render Component and have the App running!

This App is entirely Vanilla es6 App and makes use of es6 Modules. So we now import our Component using import which is then available for rendering in ./App js

Learn more about JavaScript Modules in es6 in this doc by Maye

In the ./app folder, open App.js file and copy the code snippet below to it.

import { Event } from "./components/Event.js";

const App = document.querySelector(".app");

// rendering components
const Render = doc => {
  /* add the render components or could import a render functional 
  component and pass "doc as the argument" */
  // to get a particular value of a document, use "doc.data().value"
  App.appendChild(Event(doc));
};

// get all firestore documents
db.collection("events")
  .orderBy("timestamp", "desc")
  .get()
  .then(querySnapshot => {
    // loop through each document
    querySnapshot.forEach(doc => {
      // call the "Render" function and pass "doc" as the argument
      Render(doc);
    });
  })
  .catch(error => {
    // do something with the error
    console.log("Error getting documents: ", error);
  });

Preview Demo App

You're done! Now you can deploy and host with Firebase hosting as in this guide. or if you have Firebase tools installed, run firebase serve

Preview the final App here

If you are using Chrome browser, open Dev Tools and while in the Application panel, select Service Worker and enable offline. Refresh your web app. Celebrate! Aren't you a nerd already?

Work on Glitch

You can also take this codelab on Glitch without having to setup the project on your local machine!

What's next?

You got any bug? report it here for support.

FORK ON GITHUB