In this codelab, you'll learn some of the basics of Firebase to easily create interactive web applications. We'll build and deploy an event RSVP and guestbook chat app using several Firebase products.

What you'll learn

What you'll need

In this codelab, we'll build and deploy our app using Stackblitz, an online editor that's integrated several Firebase workflows. It requires no software installation or special Stackblitz account.

Stackblitz lets you share projects with others. Other people who have your Stackblitz project URL can see your code and fork your project, but they cannot edit your Stackblitz project.

  1. Go to this URL for the starting code: https://stackblitz.com/edit/firebase-gtk-web-start.
  2. In the top left, click Fork:

You now have a copy of the starting code as your own Stackblitz project. Since you didn't sign in, your "account" is called @anonymous, but the project has a unique name, along with a unique URL. All your files and changes are saved in this Stackblitz project.

For this codelab, we've already provided some structure for the web app. For the HTML, we've added some stylesheets and created a couple HTML containers for the app. Later in this codelab, we'll hook up these containers to Firebase.

To get started, let's get a bit more familiar with the Stackblitz interface.

  1. In Stackblitz, open your index.html file.
  2. Locate the event-details-container and description-container, then try out editing some event details.

As you edit the text, the automatic page reload in Stackblitz displays the new event details! Cool, yeah?

index.html

<!-- ... -->

<div id="app">
  <img src="..." />

  <section id="event-details-container">
     <h1>Firebase Meetup</h1>

     <p><i class="material-icons">calendar_today</i> October 30</p>
     <p><i class="material-icons">location_city</i> San Francisco</p>

  </section>

  <hr>

  <section id="firebaseui-auth-container"></section>

  <section id="description-container">
     <h2>What we'll be doing</h2>
     <p>Join us for a day full of Firebase Workshops and Pizza!</p>
  </section>
</div>



<!-- ... -->

The preview of your app should look something like this:

App preview

Displaying the event info is great for our guests, but just showing the events isn't very useful for anybody. Let's add some dynamic functionality to this app! For this, we'll need to hook up Firebase to our app. To get started with Firebase, we'll need to create and set up a Firebase project.

Create a Firebase project

  1. Sign into Firebase.
  2. In the Firebase console, click Add Project, then name your Firebase project Firebase-Web-Codelab.
  3. Click though the project creation options. Accept the Firebase terms, but you can skip setting up Google Analytics because we're not using Analytics for this app.

To learn more about Firebase projects, visit Understand Firebase Projects.

The app that we're building uses several Firebase products that are available for web apps:

Some of these products need special configuration or need to be enabled using the Firebase console.

Enable Email sign-in for Firebase Auth

To allow users to sign into the web app, we'll use the Email/Password sign-in method for this codelab.

You'll need to enable Email/Password sign-in:

  1. In the Firebase console, locate the Develop section in the left nav, then click Authentication.
  2. At the top of the dashboard, click the Sign-in method tab.
  3. Enable the Email/Password Sign-in Provider, then click Save.

Firebase console

Enable Cloud Firestore

The web app uses Cloud Firestore to save chat messages and receive new chat messages.

You'll need to enable Cloud Firestore:

  1. In the Firebase console's Develop section, click Database in the left nav.
  2. Click Create database in the Cloud Firestore pane.
  1. Select the Start in test mode option. Read the disclaimer about the security rules. Test mode ensures that we can freely write to the database during development. Click Next.
  1. Select the location for your database. Note that this location cannot be changed later.
  2. Click Done.

Now that we have our Firebase project created and some services enabled, we need to tell our code that we want to use Firebase as well as which Firebase project to use.

Add the Firebase libraries

We need to add the Firebase libraries into the app. There are multiple ways to do this (as described in our documentation). For instance, you can add the libraries from our CDN. Or you can install them locally using npm, then package them in your app if you're using Browserify.

Stackblitz provides automatic bundling, so we can add the Firebase libraries using import statements.

To build this app, we're going to use the Firebase Auth, FirebaseUI, and Cloud Firestore libraries. For this codelab, we've already added the following lines for you at the top of the index.js file, but you can double-check that they are there.

index.js

// Import stylesheets
import "./style.css";

// Firebase App (the core Firebase SDK) is always required
// and must be listed first
import * as firebase from "firebase/app";

// Add the Firebase products that you want to use
import "firebase/auth";
import "firebase/firestore";

import * as firebaseui from "firebaseui";

Add a Firebase Web App to the project

  1. Back in the Firebase console, navigate to your project's overview page by clicking Project Overview in the top left.
  2. In the center of your project's overview page, click the web icon to create a new Firebase web app.
  3. Register the app with the nickname Web App.
  4. For this codelab, don't check the box next to 'Also set up Firebase Hosting for this app' (we're going to use Stackblitz's preview pane for now).
  5. Click Register app
  6. Copy the Firebase configuration object to your clipboard.
  7. Click Continue to the console.

Add your Firebase configuration object to your app:

  1. Back in Stackblitz, go to your index.js file.
  2. Locate the Add Firebase project configuration object here comment line, then paste your config snippet just below the comment.
  3. Add the initializeApp function call to set up Firebase using your unique Firebase project configuration.

index.js

// ...

// Add Firebase project configuration object here
const firebaseConfig = {
  apiKey: "random-unique-string",
  authDomain: "your-projectId.firebaseapp.com",
  databaseURL: "https://your-projectId.firebaseio.com",
  projectId: "your-projectId",
  storageBucket: "your-projectId.appspot.com",
  messagingSenderId: "random-unique-string",
  appId: "random-unique-string",
};

// Initialize Firebase
firebase.initializeApp(firebaseConfig);

Now that we've added Firebase to the app, we can set up an RSVP button that will register people using Firebase Auth.

Authenticate your users with Email Sign-In and FirebaseUI

We'll need an RSVP button that prompts the user to sign in with their email. We can do this by hooking up FirebaseUI to an RSVP button.

FirebaseUI requires a configuration (see all the options in the docs) that does two things:

  1. Tells FirebaseUI that we want to use Email/Password.
  2. Handles the callback for a successful sign-in, and returns false to avoid a redirect. We don't want the page to refresh because we're building a single-page web app.

First, let's initialize FirebaseUI:

  1. In Stackblitz, go to your index.js file.
  2. You'll notice that we already provided the FirebaseUI configuration.
  3. At the bottom of index.js, add the FirebaseUI initialization statement, like so:

index.js

// ...
// Initialize the FirebaseUI widget using Firebase
const ui = new firebaseui.auth.AuthUI(firebase.auth());

Next, let's add an RSVP button to our HTML:

  1. In Stackblitz, go to your index.html file.
  2. Add the HTML for an RSVP button inside the event-details-container as shown in the example below.

Be careful to use the same id values as shown below because, for this codelab, we've already added hooks for these specific IDs in the index.js file.

Note that in the index.html file, we have a container with the ID firebaseui-auth-container. This is the ID we'll pass to FirebaseUI to hold our login.

index.html

<!-- ... -->

<section id="event-details-container">
    <!-- ... -->
    <!-- ADD THE RSVP BUTTON HERE -->
    <button id="startRsvp">RSVP</button>
</section>
<hr>
<section id="firebaseui-auth-container"></section>
<!-- ... -->

App preview

  1. Finally, we'll set up a listener on the RSVP button and call the FirebaseUI start function. This tells FirebaseUI that we want to see the sign-in window.
  2. Add the following code to the bottom of index.js

index.js

// ... 
// At the bottom

// Listen to RSVP button clicks
startRsvpButton.addEventListener("click",
 () => {
      ui.start("#firebaseui-auth-container", uiConfig);
});

Test signing-in to the app

  1. In Stackblitz's preview window, click the RSVP button to sign into the app.
  1. Go to the Firebase console, then to the Authentication dashboard. In the Users tab, you should see the account info that you entered to sign into the app.

App preview

Firebase console

Add Auth state to the UI

Now let's make sure the UI reflects the fact that we're signed in.

  1. In Stackblitz, go to your index.js file.
  2. We'll use the Firebase Auth state listener callback, which gets notified whenever the user's sign-in status changes. If there is currently a user, we'll switch the RSVP button to a logout button.
  3. Add the following code at the bottom:

index.js

// ...
// Listen to the current Auth state
firebase.auth().onAuthStateChanged((user)=> {
  if (user) {
    startRsvpButton.innerText = "LOGOUT"
  }
  else {
    startRsvpButton.innerText = "RSVP"
  }
});
  1. Then, in our button listener, let's check if we have a current user and log them out.
  2. Replace the current startRsvpButton.addEventListener with the following:

index.js

// ...
// Called when the user clicks the RSVP button
startRsvpButton.addEventListener("click",
 () => {
    if (firebase.auth().currentUser) {
      // User is signed in; allows user to sign out
      firebase.auth().signOut();
    } else {
      // No user is signed in; allows user to sign in
      ui.start("#firebaseui-auth-container", uiConfig);
    }
});
  1. Now our button should show LOGOUT, and switch back to RSVP when we click it.

App preview

Knowing that our users are coming is great for us, but let's give our guests something else to do in our app. What if they could leave messages in a guestbook? They can share why they're excited to come or who they hope to meet.

To store the chat messages that users write in the app, we'll use Cloud Firestore.

Data Model

Cloud Firestore is a NoSQL database, and data stored in the database is split into collections, documents, fields, and subcollections. We will store each message of the chat as a document in a top-level collection called guestbook.

Add messages to Firestore

In this section, you'll add the functionality for users to write new messages to the database. We need to first add the HTML for the UI elements (message field and send button), then we'll add the code that hooks up these elements to our database.

To add the UI elements of a message field and a send button:

  1. In Stackblitz, go to your index.html file.
  2. Locate the guestbook-container, then add the following HTML to create a form with the message input field and the send button.

index.html

<!-- ... -->

 <section id="guestbook-container">
   <h2>Discussion</h2>

   <form id="leave-message">
     <label>Leave a message: </label>
     <input type="text" id="message">
     <button type="submit">
       <i class="material-icons">send</i>
       <span>SEND</span>
     </button>
   </form>

 </section>

<!-- ... -->

App preview

A user clicking the SEND button will trigger the code snippet below. It adds the contents of the message input field to the guestbook collection of your database. Specifically, the add() method adds the message content to a new document (with an automatically generated ID) to the guestbook collection.

  1. In Stackblitz, go to your index.js file.
  2. To the bottom of the file, add the following code.

Note that firebase.auth().currentUser.uid is a reference to the auto-generated unique ID that Firebase Auth gives us for all logged-in users.

index.js

// ..
// Listen to the form submission
form.addEventListener("submit", (e) => {
 // Prevent the default form redirect
 e.preventDefault();
 // Write a new message to the database collection "guestbook"
 firebase.firestore().collection("guestbook").add({
   text: input.value,
   timestamp: Date.now(),
   name: firebase.auth().currentUser.displayName,
   userId: firebase.auth().currentUser.uid
 })
 // clear message input field
 input.value = ""; 
 // Return false to avoid redirect
 return false;
});

Show the guestbook only to signed-in users

We don't want just anybody to see our guests' chat. One thing we can do to secure our chat is to allow only signed-in users to view the guestbook. That said, for your own apps, you'll want to also secure your database with Firebase Security Rules (more on security rules later in the codelab, too!)

  1. In Stackblitz, go to your index.js file.
  2. Edit your onAuthStateChanged listener to hide and show the guestbook.

index.js

// ...
// Listen to the current Auth state
firebase.auth().onAuthStateChanged((user) => {
 if (user){
   startRsvpButton.innerText = "LOGOUT";
   // Show guestbook to logged-in users
   guestbookContainer.style.display = "block";
 }
 else{
   startRsvpButton.innerText = "RSVP";
   // Hide guestbook for non-logged-in users
   guestbookContainer.style.display = "none";
 }
});

Test sending messages

  1. Make sure you're signed-in to the app.
  2. Enter a message such as "Hey there!", then click SEND.

This action writes the message to your Cloud Firestore database. However, you won't yet see the message in your actual web app because we still need to implement retrieving the data (we'll do that next).

But you can see the newly added message in the Firebase console.

  1. In the Firebase console, in your Database dashboard, you should see the guestbook collection with your newly added message. If you keep sending messages, your guestbook collection will contain many documents, like this:

Firebase console

Synchronize messages

Lovely that our guests can write messages to our database, but they can't see them in the app yet!

To display messages, we'll need to add listeners that trigger when data changes and then create a UI element that shows new messages.

We'll add code that listens for newly added messages from the app. First, let's add a section in the HTML to show messages:

  1. In Stackblitz, go to your index.html file.
  2. Within guestbook-container, add a new section with the ID of guestbook.

index.html

<!-- ... -->

  <section id="guestbook-container">
   <h2>Discussion</h2>

   <form><!-- ... --></form>

   <section id="guestbook"></section>

 </section>

<!-- ... -->

Next, we'll register the listener that listens for changes made to the data.

  1. In Stackblitz, go to your index.js file.
  2. At the bottom of the file, add the following code to loop through all the documents (guestbook messages) in the database.

index.js

// ...
// Create query for messages
firebase.firestore().collection("guestbook")
.orderBy("timestamp","desc")
.onSnapshot((snaps) => {
 // Reset page
 guestbook.innerHTML = "";
 // Loop through documents in database
 snaps.forEach((doc) => {
   // Create an HTML entry for each document and add it to the chat
   const entry = document.createElement("p");
   entry.textContent = doc.data().name + ": " + doc.data().text;
   guestbook.appendChild(entry);
 });
});

To listen to messages in the database, we create a query on a specific collection by using the .collection function. In the code above, we're listening to the changes within the guestbook collection, which is where the chat messages are stored. We're also ordering the messages by date using .orderBy('timestamp', 'desc') to display the newest messages at the top.

The .onSnapshot function takes one parameter: a callback function. The callback function will be triggered when there are any changes to documents that match the query. This could be if a message gets deleted, or modified, or added. You can read more about this in the Cloud Firestore documentation.

Test syncing messages

Cloud Firestore automatically and instantly syncs data with clients subscribed to the database.

  1. The messages that you created earlier in the database should be displayed in the app. Feel free to write new messages; they should appear instantly.
  2. If you open your workspace in multiple windows or tabs, messages will sync in real-time across tabs.
  3. (Optional) You can try manually deleting, modifying, or adding new messages directly in the Database section of the Firebase console; any changes should reflect in the UI.

Congratulations, you are reading Cloud Firestore documents in your app!

App preview

We initially set up Cloud Firestore to use test mode, meaning our database was open for reads and writes. However, we should only use test mode during very early stages of development. As a best practice, you should set up security rules for your database as you develop your app -- security should be integral to your app's structure and behavior.

We can write security rules for Cloud Firestore right in the Firebase console:

  1. In the Firebase console's Develop section, click Database, then select the Rules tab (or click here to go directly there).
  2. You should see the following default security rules, along with a warning about the rules being public.

Security Rules allow you to control access to documents and collections in your database. The flexible rules syntax allows you to create rules that match anything, from all writes to the entire database to operations on a specific document.

Firebase Console

Identify collections

First off, in our rules, we need to identify the collections to which our app writes data.

Within match /databases/{database}/documents, start replacing the test mode rules by identifying the collection that you want to secure:

Rules tab in console

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
     // You'll add rules here in the next step.
  }
}

Add security rules

For the guestbook, since we used the Auth UID as a field in each guestbook document, we can grab it and verify that anyone attempting to write to the document has a matching Auth UID.

Add the following read and write rules to your ruleset:

Rules tab in console

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow write:
        if request.auth.uid == request.resource.data.userId;
    }
  }
}

Now, for our guestbook, only signed-in users can read messages (any message!), but only a message's author can edit a message.

Add validation rules

Let's add data validation to make sure that all the fields we expect are present in the document.

Rules tab in console

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow write:
      if request.auth.uid == request.resource.data.userId
          && "name" in request.resource.data
          && "text" in request.resource.data
          && "timestamp" in request.resource.data;
    }
  }
}

Reset listeners

Since our app now only allows authenticated users to login, we'll want to move our guestbook firestore query inside the Auth listener. Otherwise, we'll get permission errors and be disconnected when the user logs out.

  1. First, pull out the the guestbook collection onSnapshot listener into a new function called subscribeGuestbook. Also assign the results of the onSnapshot function to the guestbookListener variable.

The Firestore onSnapshot listener returns an unsubscribe function that we'll be able to use to cancel the snapshot listener later.

index.js

// ...
// Listen to guestbook updates
function subscribeGuestbook(){
   // Create query for messages
 guestbookListener = firebase.firestore().collection("guestbook")
 .orderBy("timestamp","desc")
 .onSnapshot((snaps) => {
   // Reset page
   guestbook.innerHTML = "";
   // Loop through documents in database
   snaps.forEach((doc) => {
     // Create an HTML entry for each document and add it to the chat
     const entry = document.createElement("p");
     entry.textContent = doc.data().name + ": " + doc.data().text;
     guestbook.appendChild(entry);
   });
 });
};
  1. Then, add a new function underneath called unsubscribeGuestbook. We'll check if the guestbookListener variable is not null, then call the function to cancel the listener.

index.js

// ...
// Unsubscribe from guestbook updates
function unsubscribeGuestbook(){
 if (guestbookListener != null)
 {
   guestbookListener();
   guestbookListener = null;
 }
};
  1. Finally, we'll add our new functions to the onAuthStateChanged callback.
  1. Add subscribeGuestbook() at the bottom of if (user)
  2. Add unsubscribeGuestbook() at the bottom of the else statement

index.js

// ...
firebase.auth().onAuthStateChanged((user) => {
if (user){
  startRsvpButton.innerText = "LOGOUT";
  // Show guestbook to logged-in users
  guestbookContainer.style.display = "block";

  // Subscribe to the guestbook collection
  subscribeGuestbook();
}
else{
  startRsvpButton.innerText = "RSVP";
  // Hide guestbook for non-logged-in users
  guestbookContainer.style.display = "none";

  // Unsubscribe from the guestbook collection
  unsubscribeGuestbook();
}
});

Firebase offers a hosting service to serve your web app's assets. You can deploy your files and hosting configuration to Firebase Hosting using the Firebase CLI in your command line or terminal. But for this codelab, we're using Stackblitz, and they've integrated the Firebase CLI into the Stackblitz workspace!

We can use Stackblitz's Firebase integration to tell Stackblitz to which Firebase project we'd like to deploy assets:

  1. If you haven't already signed in with Github in Stackblitz, click Sign in in the top right, then enter your Github account credentials.
    Stackblitz
  1. There should now be a Firebase icon in the left-nav.
    Stackblitz
  2. Click Sign in to Google.
    Sign in using the same email that you used to sign into Firebase.
  3. From the list of Firebase projects, select your Firebase-Web-Codelab project.

Deploying to Firebase Hosting with Stackblitz is literally a one-click operation:

  1. In the Stackblitz workspace, click Deploy in the left-nav.

Yep, that's it, one step!

Stackblitz

Visit the documentation to learn more about how Firebase Hosting works.

Go to your project's Firebase console Hosting section to view useful hosting information and tools, including the history of your deploys, the functionality to roll back to previous versions of your app, and the workflow to set up a custom domain.

Record an attendee's RSVP status

Right now, our app just allows people to start chatting if they're interested in the event. Also, the only way we know if someone's coming is if they post it in the chat. Let's get organized and let people know how many people are coming!

We'll add a toggle to register people who want to attend the event, then collect a count of how many people are coming.

  1. In Stackblitz, go to your index.html file.
  2. Within guestbook-container, add a set of RSVP buttons for YES and NO, like so:

index.html

<!-- ... -->
  <section id="guestbook-container">
   <h2>Are you attending?</h2>
     <button id="rsvp-yes">YES</button>
     <button id="rsvp-no">NO</button>

   <h2>Discussion</h2>

   <!-- ... -->

 </section>
<!-- ... -->

App Preview

Next, we'll register the listener for button clicks. If the user clicks YES, then we'll use their Auth UID to save the RSVP to our database.

  1. In Stackblitz, go to your index.js file.
  2. At the bottom of the file, add the following code to listen to the RSVP status:

index.js

// ...

// Listen to RSVP responses
rsvpYes.onclick = () => {
}
rsvpNo.onclick = () => {
}
  1. Create a new collection called attendees, then register a document reference if either RSVP button is clicked.
  2. Set that reference to true or false depending on which button is clicked.

First, for rsvpYes:

index.js

// ...

// Listen to RSVP responses
rsvpYes.onclick = () => {
 // Get a reference to the user's document in the attendees collection
 const userDoc = firebase.firestore().collection('attendees').doc(firebase.auth().currentUser.uid);

 // If they RSVP'd yes, save a document with attending: true
 userDoc.set({
   attending: true
 }).catch(console.error)
}

Then, the same for rsvpNo, but with the value false:

index.js

rsvpNo.onclick = () => {
 // Get a reference to the user's document in the attendees collection
 const userDoc = firebase.firestore().collection('attendees').doc(firebase.auth().currentUser.uid);

 // If they RSVP'd yes, save a document with attending: true
 userDoc.set({
   attending: false
 }).catch(console.error)
}

Add rules

Since we already have some rules setup, the new data we're adding with the buttons is going to get rejected. We'll need to update the rules to allow adding to the attendees collection.

For the attendees collection, since we used the Auth UID as the document name, we can grab it and verify the submitter's uid is the same as the document they are writing. We'll allow everyone to read the attendees list (since there is no private data there), but only the creator should be able to update it.

Rules tab in the console

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId;
    }
  }
}

Add validation rules

Let's add data validation to make sure that all the fields we expect are present in the document.

Rules tab in the console

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId
          && "attending" in request.resource.data;

    }
  }
}

(Optional) You can now view the results of clicking the buttons - go to your Cloud Firestore dashboard in the Firebase console.

Read RSVP status

Now that we've recorded our RSVPs, let's see who's coming and reflect it in the UI!

  1. In Stackblitz, go to your index.html file.
  2. Within description-container, add a new element with the ID of number-attending.

index.html

<!-- ... -->

 <section id="description-container">
     <!-- ... -->
     <p id="number-attending"></p>
 </section>

<!-- ... -->

Next, we'll register the listener for the attendees collection and count the number of YES RSVPs:

  1. In Stackblitz, go to your index.js file.
  2. At the bottom of the file, add the following code to listen to the RSVP status and count YES clicks.

index.js

// ...
// Listen for attendee list
firebase.firestore()
.collection('attendees')
.where("attending", "==", true)
.onSnapshot(snap => {
 const newAttendeeCount = snap.docs.length;

 numberAttending.innerHTML = newAttendeeCount+' people going'; 
})
  1. Finally, let's highlight the button corresponding to our current status. We'll check if our current Auth UID has an entry in the attendees collection, then set the class to clicked.

index.js

// ...
// Listen for attendee list
function subscribeCurrentRSVP(user){
 rsvpListener = firebase.firestore()
 .collection('attendees')
 .doc(user.uid)
 .onSnapshot((doc) => {
   if (doc && doc.data()){
     const attendingResponse = doc.data().attending;

     // Update css classes for buttons
     if (attendingResponse){
       rsvpYes.className="clicked";
       rsvpNo.className="";
     }
     else{
       rsvpYes.className="";
       rsvpNo.className="clicked";
     }
   }
 });
}
  1. Also, let's make a function to unsubscribe. We'll use this when the user logs out.

index.js

// ...

function unsubscribeCurrentRSVP(){
 if (rsvpListener != null)
 {
   rsvpListener();
   rsvpListener = null;
 }
 rsvpYes.className="";
 rsvpNo.className="";
}
  1. Call the functions from the Auth listener.

index.js

// ...

// Listen to the current Auth state
firebase.auth().onAuthStateChanged((user) => {
if (user){
  startRsvpButton.innerText = "LOGOUT";
  // Show guestbook to logged-in users
  guestbookContainer.style.display = "block";

  // Subscribe to the guestbook collection
  subscribeGuestbook();
  // Subscribe to the guestbook collection
  subscribeCurrentRSVP(user);
}
else{
  startRsvpButton.innerText = "RSVP";
  // Hide guestbook for non-logged-in users
  guestbookContainer.style.display = "none";

  // Unsubscribe from the guestbook collection
  unsubscribeGuestbook();
  // Unsubscribe from the guestbook collection
  unsubscribeCurrentRSVP();

}
});
  1. Try logging in as multiple users and see the count increase with each additional YES button click.

App Preview

You've used Firebase to build an interactive, real-time web application!

What we've covered

Next steps

Learn more

How did it go?

We would love your feedback! Please fill out a (very) short form here.