Code Monkey home page Code Monkey logo

pair-partners's Introduction

pair-partners

A web app that helps people find study partners for virtual pair programming and collaboration

pair-partners's People

Contributors

kammitama5 avatar learningnerd avatar mendavia avatar naoever avatar r7uaz0n avatar ssiarules avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pair-partners's Issues

Online status

Implement a feature that displays to other users when another user is online that appears next to their username or user profile.

For Rick: Add Login with GitHub feature using Firebase Authentication

So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!

πŸ“š Prerequisites: First complete "Challenge: Practice displaying Firebase data"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development and testing with a local server

  • First make sure you're in the pair-partners project folder, and make sure you're on the master branch (use git checkout master if you need to switch).

  • Download the latest working version of our project code from GitHub with git pull -- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work!

  • If you haven't already, make a new local branch called something like gh-login-lk (with your initials at the end) for this new feature.

    Note: it's important that we create this new branch from the master branch, because we want this new branch to start out as a copy of the master branch, with the latest agreed-upon version of our project!

  • Install the http-server package from npm by running this code in your command line: npm install http-server -g (If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)

  • Make sure you're inside the pair-partners/firebase-test folder (if not, use cd to navigate there via command line), and then start your local server by running the http-server command. (Just literally type http-server into your command line, no other words needed!)

    http-server

  • View your app from the local server by going to http://localhost:8080 in your web browser. You should see everything working just like before!

  • Any time you want to turn off your local server, press Ctrl + C on your keyboard. Then run the http-server command again from inside the pair-partners/firebase-test folder each time you want to restart the server.

    Suggestion: If you want to use the command line while running the server, you can open two command line windows at the same time: one to keep the server running, and one to run commands as usual!

Why we need to use a local server

From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!

The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with file:// -- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!

GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like http://localhost:8080 -- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)

2. Create buttons and event listeners for login and logout

  • In your firebase-test/index.html file, add another paragraph that says "Not currently logged in." and give it an ID of "userinfo".

  • Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!

    Remember: all your IDs and variable names should be specific and descriptive (but also relatively short, if possible). There is an art to this! A good rule of thumb is: just by glancing at its name, can you immediately tell how this element is different from all the other elements of your app?

  • In your firebasetest.js file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)

  • Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either "User clicked LOGIN" or "User clicked LOGOUT"

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/26e3996aebf800225145c33e512c0d07

3. Register a new GitHub OAuth application

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript and Registering OAuth Apps on GitHub

OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!

When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password --
never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)

  • First, click here to register a new OAuth app on GitHub.

  • For "Application name", enter something like Pair Partners (Local Test Version)

  • For Homepage URL and "Authorization callback URL", enter http://localhost:8080

    Note: We're going to change the callback URL later to point to Firebase's server. The callback URL is where GitHub will redirect users after they've successfully logged in with GitHub and given permission for our app to access their GitHub account.

  • Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.

4. Set up GitHub authentication in the Firebase console

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript

  • In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab.
    Shortcut: Click on this link and then choose your project.

  • Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).

  • From the bottom of that page, copy the authorization callback URL (it should look something like https://fir-test-c7763.firebaseapp.com/__/auth/handler) and click the blue "Save" button to save your changes in Firebase.

  • Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the http://localhost:8080 link that was there before), and then click the green "Update application" button to save your changes in GitHub.

Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.

5. Add Firebase Authentication functions to your JavaScript

πŸ† The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript (the section titled "Handle the sign-in flow with the Firebase SDK") and Manage Users in Firebase

  • In your firebasetest.js file, create an instance of Firebase's GitHub provider object: var provider = new firebase.auth.GithubAuthProvider();

    Note: It doesn't really matter where you put this in your JavaScript file, as long as you define the provider object before any code that uses it. To keep things organized, it might be best to define this object immediately after you initialize your Firebase app.

  • Change your login button's event listener so that the following code runs every time the user clicks the login button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signInWithPopup(provider).catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signInWithPopup method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)

If you like, you can switch out the signInWithPopup method with the signInWithRedirect method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)

  • Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signOut().catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signOut method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).

  • Add the Firebase onAuthStateChanged event listener method with the following code:

    // When user logs in or logs out:
    firebase.auth().onAuthStateChanged(function(user){
      // If user is now logged in:
      if (user) {
    
        console.log('User successfully logged in to Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display user's GitHub username and GitHub profile photo!
    
      // Otherwise, if no user currently logged in:
      } else {
    
        console.log('User successfully logged OUT from Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display the message "Not currently logged in."
    
      }
    });

The Firebase onAuthStateChanged method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameter user), which contains a bunch of information about the user!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

6. Access Firebase user profile information

First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.

  • Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.

  • In your firebasetest.js file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the // HERE comment -- create one variable for the user's name and one variable for the user's profile photo URL.

    Hint: Remember that you can use dot notation to access properties of JavaScript objects. In this case, the user parameter is our object, and we want to access some properties inside of it!

7. Display the user's profile information on the web page

For the next step, we're going to use a new DOM element property called innerHTML! It's very similar to the textContent property, but the main difference is that innerHTML will render HTML elements in your string as actual HTML elements on the page!

  • First, try a quick test with the textContent property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:

    document.getElementById("userinfo").textContent = 'The <strong>username</strong> will go here and the profile photo will go here: <img src="#">';

You should see that message with the literal HTML tags show up as code on your web page! That's because the textContent property does not render HTML.

  • Next, run the same code as before, but replace textContent with innerHTML, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message!

  • Back in your firebasetest.js file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use its innerHTML property to display the user's name and their actual profile photo!

    Hint: Remember that you can combine variables with literal strings in JavaScript using the + operator, often called the string concatenation operator! For example: "Hello, " + yourNameHere + "! Nice to meet you!"

  • In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the textContent of the "userinfo" paragraph to contain the message "Not currently logged in" so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.

    Note: We can just use textContent this time, because our simple message doesn't contain any HTML tags. It's best to use textContent for simple things like this, because it actually runs much faster in the browser compared to innerHTML!

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

8. Test the app with your local server

Now we're finally ready to see if the app works! Let's try logging in with GitHub!

  • Remember to first start up your local server with the firebase-test folder as the root! (So in command line, first cd into that folder if you aren't already there.) Then run http-server and navigate to http://localhost:8080 in your web browser.

  • Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!

    Debugging tip: If your web app isn't updating as expected after making changes to your code, try these instructions to do a "hard refresh" and clear your web browser's cache!

πŸ† Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!

9. Create a pull request to share your code with us

You know the drill! If you need to review the detailed instructions, see the bottom of the previous challenge ("Practice displaying Firebase data"). Here's a less detailed, quick recap:

  • Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.

  • Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.

  • After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Up for grabs: Create a sample Firebase app that updates penguins' names

We've created a Firebase app, practiced using arrays and objects for more complex data structures, and we've even done some data modeling with penguins! Now let's take that example penguin app and make it into a real, functional Firebase app!

πŸ“š Prerequisites: First complete the following challenges:

  1. "Practice with JavaScript objects and arrays"
  2. "Create a data model for our app"
  3. "Create an example of the Firebase child() method"
  4. "Create an example of the Firebase set() method"

βœ”οΈ To complete this challenge: Fork your own copy of this CodePen, write code to finish the sample app, save it, and then post a comment at the bottom of this page with a link to your CodePen!

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

Review of the penguin data model

Remember our fictional penguins from the previous challenge? We used JavaScript objects to model each fictional penguin, using properties to contain each piece of information that we wanted to track for them!

Here's the example code that was provided at the end of that challenge, leaving out the methods (like sayHello) and instead only including the properties that we want to track for our penguins:

var gunter = {
  name: "Gunter",
  origin: "Adventure Time",
  canFly: false,
};

var ramon = {
  name: "RamΓ³n",
  origin: "Happy Feet",
  canFly: true,
};

var fred = {
  name: "Fred",
  origin: "Sitting Ducks",
  canFly: false,
};

Then we created an array to contain a list of our three penguins: var penguins = [gunter, ramon, fred];

This sample CodePen uses a working Firebase database that contains a list of those penguins! Here's what the above penguin data looks like inside the Firebase console for this sample app:

firebase-penguins

Remember: Firebase only stores objects, strings, numbers, and Boolean values -- it actually doesn't have any native support for arrays! So to get around that, we stored the list of penguins as nested objects (objects inside of other objects). Now instead of using array indexes to uniquely identify each penguin, we're assigning each penguin object to a property that serves as a unique ID number -- just like a social security number!

Challenge: Finish the sample app to update penguins' names!

πŸ† The goal: Add a couple lines of code to this sample CodePen to make a working app that updates the name of a specified penguin based on the user's input.

πŸ’‘ Hint: if you haven't already, first take a look at the challenges for "Create an example of the Firebase child() method" and "Create an example of the Firebase set() method", and read all the solutions posted in the comments for both of those challenges!

βœ”οΈ To complete this challenge: Fork your own copy of the sample CodePen, write code to get it working, save it, and then post a comment at the bottom of this page with a link to your CodePen!

Up for grabs: Create an example of the Firebase remove() method

⭐️ This challenge is up for grabs! Claim it by clicking "assign yourself" on the right, under the "Assignees" section for this GitHub issue! You can work on this by yourself or in pairs.

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with some instructions and sample code, so the rest of our team can learn how to use this new Firebase method by reading your comment!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

About the Firebase remove method

πŸ“š Official documentation: Firebase API section on the remove method

The remove method deletes data at the specified location in the database. If that database location contains any children (nested objects), they will all be deleted as well.

Your challenge

πŸ† The goal: learn how this method works, test it out for yourself, and then post a comment at the bottom of this page with some instructions and sample code to help teach the rest of our team!

Questions to keep in mind:

  • What does the official documentation say about this method?
  • When would we need to use this method? What are some example use cases? (Write some sample code for us, please!)
  • When should we not use this method? Can you think of any scenarios where using this method would cause errors or unintended side effects?
  • How many inputs does this method require, if any? What data types can the inputs be?
  • What does this method return as an output, if any? What data type is returned?
  • If there are different options for inputs, how does this method behave differently depending on the different possible input(s)?

Online notification.

As a learner of JavaScript, I would be interested in having a feature that displays users who are logged in and available to collaborate for pair programming as well as a feature which links to projects a user is working so that the pair can continue working on it. Perhaps a link to a Git repository of a project.

Up for grabs: Create an example of the Firebase "parent" property

⭐️ This challenge is up for grabs! Claim it by clicking "assign yourself" on the right, under the "Assignees" section for this GitHub issue! You can work on this by yourself or in pairs.

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with some instructions and sample code, so the rest of our team can learn how to use this new Firebase property by reading your comment!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

About the Firebase parent property

πŸ“š Official documentation: Firebase API section on the parent property

Every database Reference object in Firebase has a parent, except for the root of the database.

Your challenge

πŸ† The goal: learn how this property works, test it out for yourself, and then post a comment at the bottom of this page with some instructions and sample code to help teach the rest of our team!

Questions to keep in mind:

  • What does the official documentation say about this property ?
  • When would we need to use this property ? What are some example use cases? (Write some sample code for us, please!)
  • When should we not use this property ? Can you think of any scenarios where using this property would cause errors or unintended side effects?
  • What data types can be stored as values of this property?

For Krystal: Create your first Firebase app!

Firebase is a set of tools (now owned by Google) that help software developers build web and mobile apps more quickly and easily. We'll be using their real-time database platform as the backend for our app, so we don't have to worry about setting up or maintaining our own server! It's a great beginner-friendly way to start learning about databases, and these "Backend as a Service" (BaaS) tools are a huge trend in the tech industry right now!

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

1. Set up for local development on your computer

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • Switch to the master branch (if you aren't already on it) with the git checkout master command.

  • Get the latest changes from GitHub with the git pull command.

  • Create a new local branch with git checkout -b BRANCH-NAME, replacing BRANCH-NAME with an all-lowercase name for this new feature followed by your initials (for example, firebase-test-lk).

Great! Now any commits you make will be part of this new branch that you just created and switched to.

Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

2. Create new files and folders for your Firebase test app

  • Inside the pair-partners project directory, create a new directory called firebase-test.

    Remember you can create new directories from the command line with the mkdir command, as in mkdir firebase-test.

  • Navigate into the new firebase-test directory and create two new files: index.html and firebasetest.js.

    Remember you can create new files from the command line with the touch command, as in touch index.html firebasetest.js to create both files at the same time!

  • Copy this HTML boilerplate code and paste it into your firebase-test/index.html file (in other words, into your new index.html file inside the firebase-test directory).

  • Change the <title> to something like "Testing Firebase!" or similar.

  • Inside the <body> element, create the following elements:

    • An <h1> heading element that contains the same text as the title, something like "Testing Firebase!" or similar.

    • A empty paragraph with the id of "message", as in <p id="message"></p>.

    • A <script> element to import the Firebase JavaScript library into your web page. The source URL of the Firebase JavaScript file (hosted on Google's servers for our convenience!) is "https://www.gstatic.com/firebasejs/4.1.2/firebase.js". So your code for this step should be:
      <script src="https://www.gstatic.com/firebasejs/4.1.2/firebase.js"></script>.

    • Another <script> element to import your firebasetest.js file, as in:
      <script src="firebasetest.js"></script>.

Awesome! Now that you have your files set up and the Firebase library imported into your web page, you're ready to set up your first Firebase app! If you haven't already, now is a good time to make a Git commit to save your progress!

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/dee22d9806d213aedfa151ed5898bb17

Please don't look at the solutions until after you've checked and double-checked your code for each part of this challenge. No cheating! haha :)

3. Set up your Firebase project

  • Open the Firebase console (which is just a web page that lets you manage your app) and log in using your Google account.

  • Click "Add New Project" and give your project a name like "Firebase Test":
    firebase-add-project

  • Click "Add Firebase to your web app":
    firebase-web-app

  • Copy and paste the JavaScript part of the initialization code into your firebasetest.js file, starting from // Initialize Firebase until before the closing </script> tag:
    firebase-code-snippet

  • In the Firebase console, navigate to the "Database" page and then to the "Rules" tab.
    Shortcut: Click on this link and then choose your project to get to the page quickly!

  • Double click the code where it says "auth !== null" and type to replace it with true so that the code says ".read": true, ".write": true for the rules. Note: Don't use quote marks around true!
    firebase-rules-publish

  • Click the "Publish" button right above the rules to save your changes. You should now see a warning that your security rules are defined as public and anyone can read or write to your database:
    firebase-rules-public-warning

That's exactly what we want right now; while we're testing this first version of our app, we want it to work without requiring users to sign in first. Later we'll change the rules again to add security as needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/288df7eff9f78e9a44ab9215f8858355

Congrats, you now have a Firebase app! If you haven't already, be sure to make another Git commit to save your progress. Next, let's test out the app and make sure it works!

4. Add JavaScript code to display Firebase data on your web page

  • Create a JavaScript object named 'messageBox' for the HTML element that has an id of "message".

  • Create another JavaScript object called dbRef. This object will be our reference to the "greeting" row of our Firebase database. Use this chain of built-in Firebase methods:
    var dbRef = firebase.database().ref().child("greeting");

  • Last but not least, we'll use another built-in Firebase function to create an event listener that will display our data on the web page any time our database is updated:
    dbRef.on("value", function(dataSnapshot) { messageBox.textContent = dataSnapshot.val(); });

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/43b7edeaa40e3e61b6017c035c07670f

We'll learn more about all of these Firebase functions in the next challenges, but first let's test the app and make sure that our code is working!

5. Add sample data with the Firebase Console and test your app

  • In the Firebase Console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the text that looks similar to fir-test-c7763: null and then click on the green plus sign that appears:
    firebase-add-1

  • In the two text boxes that pop up, type "greeting" for the name and "Hi from Firebase!" for the value. Then click the blue "Add" button when you're ready to save your new data:
    firebase-add-2

  • Now let's test our new app! Open up your firebase-test/index.html file with your web browser and you should now see your message "Hi from Firebase!" appear on the page!

  • Next, navigate back to the "Data" tab of the "Database" page in the Firebase Console, click on your "Hi from Firebase!" message, type in the box to change the value to something else like "I changed this data in Firebase!", and then press the Enter key to save your changes:
    firebase-edit

  • If you switch back to your index.html page in your web browser again, you should see the data change!

πŸ† Congratulations, your first Firebase app is working! The coolest thing about Firebase is that it updates the data in real time so you don't even need to refresh the page to see the changes. Behind the scenes, it's using a WebSocket connection just like our SocketIO chatroom app did! Cool stuff, right?

βœ”οΈ If you haven't already, be sure to make another Git commit. And while you're at it, be sure to check off all the checkboxes in these instructions for every step that you've completed -- that way the rest of our team can easily see your progress!

6. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Create your first Firebase app!" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

calendar/schedule

Implement a feature where a user can display their schedule to plan future meetings with other users. Scope of a booking system. When a user books another user, each user gets notified via email and within the web application.

For Nao: Create your first Firebase app!

Firebase is a set of tools (now owned by Google) that help software developers build web and mobile apps more quickly and easily. We'll be using their real-time database platform as the backend for our app, so we don't have to worry about setting up or maintaining our own server! It's a great beginner-friendly way to start learning about databases, and these "Backend as a Service" (BaaS) tools are a huge trend in the tech industry right now!

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

1. Set up for local development on your computer

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • Switch to the master branch (if you aren't already on it) with the git checkout master command.

  • Get the latest changes from GitHub with the git pull command.

  • Create a new local branch with git checkout -b BRANCH-NAME, replacing BRANCH-NAME with an all-lowercase name for this new feature followed by your initials (for example, firebase-test-lk).

Great! Now any commits you make will be part of this new branch that you just created and switched to.

Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

2. Create new files and folders for your Firebase test app

  • Inside the pair-partners project directory, create a new directory called firebase-test.

    Remember you can create new directories from the command line with the mkdir command, as in mkdir firebase-test.

  • Navigate into the new firebase-test directory and create two new files: index.html and firebasetest.js.

    Remember you can create new files from the command line with the touch command, as in touch index.html firebasetest.js to create both files at the same time!

  • Copy this HTML boilerplate code and paste it into your firebase-test/index.html file (in other words, into your new index.html file inside the firebase-test directory).

  • Change the <title> to something like "Testing Firebase!" or similar.

  • Inside the <body> element, create the following elements:

    • An <h1> heading element that contains the same text as the title, something like "Testing Firebase!" or similar.

    • A empty paragraph with the id of "message", as in <p id="message"></p>.

    • A <script> element to import the Firebase JavaScript library into your web page. The source URL of the Firebase JavaScript file (hosted on Google's servers for our convenience!) is "https://www.gstatic.com/firebasejs/4.1.2/firebase.js". So your code for this step should be:
      <script src="https://www.gstatic.com/firebasejs/4.1.2/firebase.js"></script>.

    • Another <script> element to import your firebasetest.js file, as in:
      <script src="firebasetest.js"></script>.

Awesome! Now that you have your files set up and the Firebase library imported into your web page, you're ready to set up your first Firebase app! If you haven't already, now is a good time to make a Git commit to save your progress!

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/dee22d9806d213aedfa151ed5898bb17

Please don't look at the solutions until after you've checked and double-checked your code for each part of this challenge. No cheating! haha :)

3. Set up your Firebase project

  • Open the Firebase console (which is just a web page that lets you manage your app) and log in using your Google account.

  • Click "Add New Project" and give your project a name like "Firebase Test":
    firebase-add-project

  • Click "Add Firebase to your web app":
    firebase-web-app

  • Copy ONLY the JavaScript code from the initialization code snippet (only the part outlined in red in the screenshot below). Then paste that code into your firebasetest.js file:
    firebase-code-snippet

  • In the Firebase console, navigate to the "Database" page and then to the "Rules" tab.
    Shortcut: Click on this link and then choose your project to get to the page quickly!

  • Double click the code where it says "auth !== null" and type to replace it with true so that the code says ".read": true, ".write": true for the rules. Note: Don't use quote marks around true!
    firebase-rules-publish

  • Click the "Publish" button right above the rules to save your changes. You should now see a warning that your security rules are defined as public and anyone can read or write to your database:
    firebase-rules-public-warning

That's exactly what we want right now; while we're testing this first version of our app, we want it to work without requiring users to sign in first. Later we'll change the rules again to add security as needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/288df7eff9f78e9a44ab9215f8858355

Congrats, you now have a Firebase app! If you haven't already, be sure to make another Git commit to save your progress. Next, let's test out the app and make sure it works!

4. Add JavaScript code to display Firebase data on your web page

  • Create a JavaScript object named 'messageBox' for the HTML element that has an id of "message".

  • Create another JavaScript object called dbRef. This object will be our reference to the "greeting" row of our Firebase database. Use this chain of built-in Firebase methods:
    var dbRef = firebase.database().ref().child("greeting");

  • Last but not least, we'll use another built-in Firebase function to create an event listener that will display our data on the web page any time our database is updated:
    dbRef.on("value", function(dataSnapshot) { messageBox.textContent = dataSnapshot.val(); });

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/43b7edeaa40e3e61b6017c035c07670f

We'll learn more about all of these Firebase functions in the next challenges, but first let's test the app and make sure that our code is working!

5. Add sample data with the Firebase Console and test your app

  • In the Firebase Console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the text that looks similar to fir-test-c7763: null and then click on the green plus sign that appears:
    firebase-add-1

  • In the two text boxes that pop up, type "greeting" for the name and "Hi from Firebase!" for the value. Then click the blue "Add" button when you're ready to save your new data:
    firebase-add-2

  • Now let's test our new app! Open up your firebase-test/index.html file with your web browser and you should now see your message "Hi from Firebase!" appear on the page!

  • Next, navigate back to the "Data" tab of the "Database" page in the Firebase Console, click on your "Hi from Firebase!" message, type in the box to change the value to something else like "I changed this data in Firebase!", and then press the Enter key to save your changes:
    firebase-edit

  • If you switch back to your index.html page in your web browser again, you should see the data change!

πŸ† Congratulations, your first Firebase app is working! The coolest thing about Firebase is that it updates the data in real time so you don't even need to refresh the page to see the changes. Behind the scenes, it's using a WebSocket connection just like our SocketIO chatroom app did! Cool stuff, right?

βœ”οΈ If you haven't already, be sure to make another Git commit. And while you're at it, be sure to check off all the checkboxes in these instructions for every step that you've completed -- that way the rest of our team can easily see your progress!

6. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Create your first Firebase app!" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For Johnson: Add Login with GitHub feature using Firebase Authentication

So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!

πŸ“š Prerequisites: First complete "Challenge: Practice displaying Firebase data"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development and testing with a local server

Reminder for Johnson: Click "Run" and "Preview" > "Preview Running Application" to test your code in Cloud9 (instead of running a local server), and remember to add /firebase-test/ to the end of the URL for your app's website in Cloud9 (for example, it would look similar to https://pairpartners-learningnerd.c9users.io/firebase-test/).

  • First make sure you're in the pair-partners project folder, and make sure you're on the master branch (use git checkout master if you need to switch).

  • Download the latest working version of our project code from GitHub with git pull -- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work!

  • If you haven't already, make a new local branch called something like gh-login-lk (with your initials at the end) for this new feature.

    Note: it's important that we create this new branch from the master branch, because we want this new branch to start out as a copy of the master branch, with the latest agreed-upon version of our project!

  • Install the http-server package from npm by running this code in your command line: npm install http-server -g (If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)

  • Make sure you're inside the pair-partners/firebase-test folder (if not, use cd to navigate there via command line), and then start your local server by running the http-server command. (Just literally type http-server into your command line, no other words needed!)

    http-server

  • View your app from the local server by going to http://localhost:8080 in your web browser. You should see everything working just like before!

  • Any time you want to turn off your local server, press Ctrl + C on your keyboard. Then run the http-server command again from inside the pair-partners/firebase-test folder each time you want to restart the server.

    Suggestion: If you want to use the command line while running the server, you can open two command line windows at the same time: one to keep the server running, and one to run commands as usual!

Why we need to use a local server

From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!

The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with file:// -- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!

GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like http://localhost:8080 -- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)

2. Create buttons and event listeners for login and logout

  • In your firebase-test/index.html file, add another paragraph that says "Not currently logged in." and give it an ID of "userinfo".

  • Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!

    Remember: all your IDs and variable names should be specific and descriptive (but also relatively short, if possible). There is an art to this! A good rule of thumb is: just by glancing at its name, can you immediately tell how this element is different from all the other elements of your app?

  • In your firebasetest.js file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)

  • Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either "User clicked LOGIN" or "User clicked LOGOUT"

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/26e3996aebf800225145c33e512c0d07

3. Register a new GitHub OAuth application

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript and Registering OAuth Apps on GitHub

OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!

When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password --
never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)

  • First, click here to register a new OAuth app on GitHub.

  • For "Application name", enter something like Pair Partners (Local Test Version)

  • For Homepage URL and "Authorization callback URL", enter http://localhost:8080

    Note: We're going to change the callback URL later to point to Firebase's server. The callback URL is where GitHub will redirect users after they've successfully logged in with GitHub and given permission for our app to access their GitHub account.

  • Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.

4. Set up GitHub authentication in the Firebase console

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript

  • In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab.
    Shortcut: Click on this link and then choose your project.

  • Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).

  • From the bottom of that page, copy the authorization callback URL (it should look something like https://fir-test-c7763.firebaseapp.com/__/auth/handler) and click the blue "Save" button to save your changes in Firebase.

  • Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the http://localhost:8080 link that was there before), and then click the green "Update application" button to save your changes in GitHub.

Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.

5. Add Firebase Authentication functions to your JavaScript

πŸ† The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript (the section titled "Handle the sign-in flow with the Firebase SDK") and Manage Users in Firebase

  • In your firebasetest.js file, create an instance of Firebase's GitHub provider object: var provider = new firebase.auth.GithubAuthProvider();

    Note: It doesn't really matter where you put this in your JavaScript file, as long as you define the provider object before any code that uses it. To keep things organized, it might be best to define this object immediately after you initialize your Firebase app.

  • Change your login button's event listener so that the following code runs every time the user clicks the login button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signInWithPopup(provider).catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signInWithPopup method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)

If you like, you can switch out the signInWithPopup method with the signInWithRedirect method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)

  • Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signOut().catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signOut method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).

  • Add the Firebase onAuthStateChanged event listener method with the following code:

    // When user logs in or logs out:
    firebase.auth().onAuthStateChanged(function(user){
      // If user is now logged in:
      if (user) {
    
        console.log('User successfully logged in to Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display user's GitHub username and GitHub profile photo!
    
      // Otherwise, if no user currently logged in:
      } else {
    
        console.log('User successfully logged OUT from Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display the message "Not currently logged in."
    
      }
    });

The Firebase onAuthStateChanged method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameter user), which contains a bunch of information about the user!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

6. Access Firebase user profile information

First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.

  • Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.

  • In your firebasetest.js file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the // HERE comment -- create one variable for the user's name and one variable for the user's profile photo URL.

    Hint: Remember that you can use dot notation to access properties of JavaScript objects. In this case, the user parameter is our object, and we want to access some properties inside of it!

7. Display the user's profile information on the web page

For the next step, we're going to use a new DOM element property called innerHTML! It's very similar to the textContent property, but the main difference is that innerHTML will render HTML elements in your string as actual HTML elements on the page!

  • First, try a quick test with the textContent property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:

    document.getElementById("userinfo").textContent = 'The <strong>username</strong> will go here and the profile photo will go here: <img src="#">';

You should see that message with the literal HTML tags show up as code on your web page! That's because the textContent property does not render HTML.

  • Next, run the same code as before, but replace textContent with innerHTML, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message!

  • Back in your firebasetest.js file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use its innerHTML property to display the user's name and their actual profile photo!

    Hint: Remember that you can combine variables with literal strings in JavaScript using the + operator, often called the string concatenation operator! For example: "Hello, " + yourNameHere + "! Nice to meet you!"

  • In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the textContent of the "userinfo" paragraph to contain the message "Not currently logged in" so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.

    Note: We can just use textContent this time, because our simple message doesn't contain any HTML tags. It's best to use textContent for simple things like this, because it actually runs much faster in the browser compared to innerHTML!

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

8. Test the app with your local server

Now we're finally ready to see if the app works! Let's try logging in with GitHub!

  • Remember to first start up your local server with the firebase-test folder as the root! (So in command line, first cd into that folder if you aren't already there.) Then run http-server and navigate to http://localhost:8080 in your web browser.

  • Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!

    Debugging tip: If your web app isn't updating as expected after making changes to your code, try these instructions to do a "hard refresh" and clear your web browser's cache!

πŸ† Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!

9. Create a pull request to share your code with us

You know the drill! If you need to review the detailed instructions, see the bottom of the previous challenge ("Practice displaying Firebase data"). Here's a less detailed, quick recap:

  • Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.

  • Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.

  • After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Up for grabs: Create an example of the Firebase push() method

⭐️ This challenge is up for grabs! Claim it by clicking "assign yourself" on the right, under the "Assignees" section for this GitHub issue! You can work on this by yourself or in pairs.

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with some instructions and sample code, so the rest of our team can learn how to use this new Firebase method by reading your comment!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

About the Firebase push method

πŸ“š Official documentation: Firebase API section on the push method

The push method appends data to a list, creating a new child (nested object) inside the specific database location with an automatically-generated unique ID as its key (or property, in object terms!) so that you can easily add items to a list and later access them by their unique IDs.

Your challenge

πŸ† The goal: learn how this method works, test it out for yourself, and then post a comment at the bottom of this page with some instructions and sample code to help teach the rest of our team!

Questions to keep in mind:

  • What does the official documentation say about this method?
  • When would we need to use this method? What are some example use cases? (Write some sample code for us, please!)
  • When should we not use this method? Can you think of any scenarios where using this method would cause errors or unintended side effects?
  • How many inputs does this method require, if any? What data types can the inputs be?
  • What does this method return as an output, if any? What data type is returned?
  • If there are different options for inputs, how does this method behave differently depending on the different possible input(s)?

A progress meter so you can see the work you completed with your team each time you connect!

https://cloud.githubusercontent.com/assets/22872740/26659934/809e98fe-4629-11e7-9f71-129c7e364615.png

With this progress meter it would include days, months, so you can always go back to see your progress and the amount of work you and your team completed.

Tasks that needs to be done or work on will be inputted prior to meeting up and everytime is completed it will be seen on the progress meter! Good way to keep yourself and team accountable

For Johnson: Practice displaying Firebase data

So you've built your first Firebase app, and with just a few lines of JavaScript code, you already know how to take information from your database and display it on your web page! Woohoo! Now here's some more practice to help you check your understanding of the Firebase functions we used to make it happen.

πŸ“š Prerequisites: First complete "Challenge: Create your first Firebase app!"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • If you're not already on it, switch to the local branch that you created in the previous challenge. (For example, Liz's branch was named firebase-test-lk)

    Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

Great! Now any commits you make will be saved to this branch and kept separate from other versions of our project.

2. Create another row in your Firebase database

  • In the Firebase console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the name of your database at the top (probably similar to fir-test-c7763), and then click on the green plus sign that appears:
    firebase-add-row-1

  • In the two text boxes that pop up, type "myname" for the name and enter your actual name for the value. Then click the blue "Add" button to save your new data:
    firebase-add-row-2

3. Edit your JavaScript and HTML to display the new data

πŸ† The goal: Let's change our app to display our two pieces of data in two separate paragraphs that both update in real time when the data changes!

  • In your firebasetest.js file, find and change one word in your code to make your app display your name instead of the previous message.

    Hint: it's a string, and it matches something you typed into the Firebase console earlier.
    To test your app: open up your firebase-test/index.html file with your web browser.

  • Once you got that working, save your work and make a Git commit! Make sure your commit message describes what you changed. For example: "Display myname from Firebase."

  • In your firebase-test/index.html file, create another empty paragraph with the id of "username" and put it above the existing paragraph. This is where we'll display your name!

  • In your firebasetest.js file, turn that new paragraph into a JavaScript object named usernameBox.

    Hint: copy from your existing code for the messageBox object if needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/d886a3c64e9da6121992f63191e1c70a

4. Create more Firebase reference objects

In Firebase, a reference object represents a specific location in your database. Firebase organizes data in a hierarchy or tree structure, just like your computer's file system or the web browser's Document Object Model (which organizes elements of a web page into a hierarchy, with the document object as the root of the entire tree).

So now that we want to access two sections of our database, we're first going to create a reference to the root of our database, and then we'll use the root reference to create two more reference objects: one for "myname" and one for "greeting".

  • Locate the line where you defined the dbRef object, and delete the child() method from the end of that line. So now that line of code should look like: var dbRef = firebase.database().ref();

    Now the dbRef object points to the root of our Firebase database, instead of pointing to the "myname" section of the database.

  • Create two more variables named dbGreeting and dbUsername, set them both equal to dbRef.child(), and remember to give each child() method a string input matching the locations in your database!

    For example: if my database had a row called "color", I'd create a new variable called dbColor and set it equal to dbRef.child("color") to get access to that section of my database.

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/f7a3851bf7fbd6c56890546bb21b5719

5. Review event listeners in JavaScript

πŸ“š Reference link: Review these slides on event listeners from our previous JavaScript slideshow!

Remember JavaScript's built-in addEventListener() method? It took two inputs: a string representing the name of the event and a function to run when the event occurs. For example, if you wanted to run the sayHello function each time the user clicks the submitButton on your web page, your code might look like this: submitButton.addEventListener("click", sayHello);

  • Where is the event happening? On the submitButton
  • Which event are we listening for? The "click" event
  • What should happen when the event occurs? Run the sayHello function

Remember also that your function can receive an input from the event listener, which contains information about the event that just occurred! For example, the event parameter in the code below will be replaced by a MouseEvent object containing lots of information about your mouse clicks:

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}
  • Challenge: Try running the code above, either directly in your browser console or in a CodePen. Click somewhere on the web page, and then look inside the console. Do you see the MouseEvent objects show up in your console? It should look like this:
    console-expand-object

    If that worked, mark the checkbox above to show you completed this step! If not, ask us for help on Slack!

6. Review anonymous functions

Anonymous functions are just functions defined without a name, which is a common practice in JavaScript when you know you're only going to use the function in one place. Let's compare the previous code sample with a version that uses an anonymous function to do the exact same thing:

Example 1: Named function

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}

Example 2: Anonymous function

window.addEventListener("click", function (event) {
  console.log(event);
});

See how the second version is shorter because of the way we defined that anonymous function? This is a pattern you will see again and again in JavaScript; in fact, the code at the end of your firebasetest.js file is using an anonymous function right now! Let's take a closer look.

7. Create another Firebase event listener

If you know how to use event listeners in JavaScript, you already know how to use event listeners in Firebase! The Firebase event listener is a method named on(), and it's the main way to read data from your database. Right now, the end of your JavaScript file should already contain this code:

dbRef.on("value", function(dataSnapshot) {		
  messageBox.textContent = dataSnapshot.val();
});
  • Where is the event happening? On the dbRef object, which now points to the root of our Firebase database!
  • Which event are we listening for? The "value" event, which is triggered any time a value changes inside this database location.
  • What should happen when the event occurs? Run an anonymous function that will display the value of the new data inside the messageBox element on our web page.

Notice that the dataSnapshot parameter works exactly the same as the event parameter in section 5 above; it's given to us by the event listener, and it gets replaced with an object that contains lots of information about the event that just occurred! With Firebase, we don't need to use the entire dataSnapshot object, so instead the convention is to use a special method called val() to extract the data. So when we call dataSnapshot.val(), we're getting the new data from our database and none of the other Firebase information (which we don't need to worry about).

  • Add console.log( dataSnapshot.val() ); into your code so that it will log the new Firebase data to your browser's console any time the Firebase data changes.

  • Open firebase-test/index.html in your web browser again to test it, and look inside your browser console. You should see all your data, formatted as a JavaScript object!

    Try refreshing the page in your web browser if it didn't work. And try changing the values of your data inside the Firebase Console, and see it change on your web page in real-time!

There's just one problem: even though you can see your data in the console, your web page is displaying [object Object] instead of showing your name or your greeting message! Why is that? Because we're using the Firebase event listener on the root of our database, which contains our entire database: {greeting: "Hi from Firebase!", myname: "Liz"}

Notice the format of that data: it's a JavaScript object! We don't want to display the entire database inside one paragraph, though; we want to display a string, one in each paragraph.

  • In your firebasetest.js file, look inside the Firebase event listener code and replace dbRef with dbGreeting so that your code will now only listen for changes to the "greeting" section of your database!

    So now dataSnapshot.val() with return the value of "greeting" in your database, which is a string -- that's what we want!

  • Test it in your web browser again, and you should see your "greeting" message show up on the web page again! Try changing the value of "greeting" from inside the Firebase Console and it should update in real time!

  • Copy all of the Firebase event listener code, and paste a duplicate of it at the end of your firebasetest.js file.

  • Inside the second copy of your Firebase event listener code, replace one variable to display the data inside the other paragraph on your web page.

    Hint: Earlier you created two JavaScript variables for your two paragraphs. What were they named?

  • Now replace one more variable in that same section to tell the Firebase event listener to only listen for updates to the other section of your database.

    Hint: Earlier you created three Firebase reference objects. You should be using two of them for your two Firebase event listeners!

βœ”οΈ SOLUTION for Part 7: https://gist.github.com/LearningNerd/d088d03deff297e6121068788d136eb6

8. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Practice displaying Firebase data" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For Johnson: Create your first Firebase app!

Firebase is a set of tools (now owned by Google) that help software developers build web and mobile apps more quickly and easily. We'll be using their real-time database platform as the backend for our app, so we don't have to worry about setting up or maintaining our own server! It's a great beginner-friendly way to start learning about databases, and these "Backend as a Service" (BaaS) tools are a huge trend in the tech industry right now!

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

1. Set up for local development on your computer

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • Switch to the master branch (if you aren't already on it) with the git checkout master command.

  • Get the latest changes from GitHub with the git pull command.

  • Create a new local branch with git checkout -b BRANCH-NAME, replacing BRANCH-NAME with an all-lowercase name for this new feature followed by your initials (for example, firebase-test-lk).

Great! Now any commits you make will be part of this new branch that you just created and switched to.

Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

2. Create new files and folders for your Firebase test app

  • Inside the pair-partners project directory, create a new directory called firebase-test.

    Remember you can create new directories from the command line with the mkdir command, as in mkdir firebase-test.

  • Navigate into the new firebase-test directory and create two new files: index.html and firebasetest.js.

    Remember you can create new files from the command line with the touch command, as in touch index.html firebasetest.js to create both files at the same time!

  • Copy this HTML boilerplate code and paste it into your firebase-test/index.html file (in other words, into your new index.html file inside the firebase-test directory).

  • Change the <title> to something like "Testing Firebase!" or similar.

  • Inside the <body> element, create the following elements:

    • An <h1> heading element that contains the same text as the title, something like "Testing Firebase!" or similar.

    • A empty paragraph with the id of "message", as in <p id="message"></p>.

    • A <script> element to import the Firebase JavaScript library into your web page. The source URL of the Firebase JavaScript file (hosted on Google's servers for our convenience!) is "https://www.gstatic.com/firebasejs/4.1.2/firebase.js". So your code for this step should be:
      <script src="https://www.gstatic.com/firebasejs/4.1.2/firebase.js"></script>.

    • Another <script> element to import your firebasetest.js file, as in:
      <script src="firebasetest.js"></script>.

Awesome! Now that you have your files set up and the Firebase library imported into your web page, you're ready to set up your first Firebase app! If you haven't already, now is a good time to make a Git commit to save your progress!

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/dee22d9806d213aedfa151ed5898bb17

Please don't look at the solutions until after you've checked and double-checked your code for each part of this challenge. No cheating! haha :)

3. Set up your Firebase project

  • Open the Firebase console (which is just a web page that lets you manage your app) and log in using your Google account.

  • Click "Add New Project" and give your project a name like "Firebase Test":
    firebase-add-project

  • Click "Add Firebase to your web app":
    firebase-web-app

  • Copy and paste the JavaScript part of the initialization code into your firebasetest.js file, starting from // Initialize Firebase until before the closing </script> tag:
    firebase-code-snippet

  • In the Firebase console, navigate to the "Database" page and then to the "Rules" tab.
    Shortcut: Click on this link and then choose your project to get to the page quickly!

  • Double click the code where it says "auth !== null" and type to replace it with true so that the code says ".read": true, ".write": true for the rules. Note: Don't use quote marks around true!
    firebase-rules-publish

  • Click the "Publish" button right above the rules to save your changes. You should now see a warning that your security rules are defined as public and anyone can read or write to your database:
    firebase-rules-public-warning

That's exactly what we want right now; while we're testing this first version of our app, we want it to work without requiring users to sign in first. Later we'll change the rules again to add security as needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/288df7eff9f78e9a44ab9215f8858355

Congrats, you now have a Firebase app! If you haven't already, be sure to make another Git commit to save your progress. Next, let's test out the app and make sure it works!

4. Add JavaScript code to display Firebase data on your web page

  • Create a JavaScript object named 'messageBox' for the HTML element that has an id of "message".

  • Create another JavaScript object called dbRef. This object will be our reference to the "greeting" row of our Firebase database. Use this chain of built-in Firebase methods:
    var dbRef = firebase.database().ref().child("greeting");

  • Last but not least, we'll use another built-in Firebase function to create an event listener that will display our data on the web page any time our database is updated:
    dbRef.on("value", function(dataSnapshot) { messageBox.textContent = dataSnapshot.val(); });

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/43b7edeaa40e3e61b6017c035c07670f

We'll learn more about all of these Firebase functions in the next challenges, but first let's test the app and make sure that our code is working!

5. Add sample data with the Firebase Console and test your app

  • In the Firebase Console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the text that looks similar to fir-test-c7763: null and then click on the green plus sign that appears:
    firebase-add-1

  • In the two text boxes that pop up, type "greeting" for the name and "Hi from Firebase!" for the value. Then click the blue "Add" button when you're ready to save your new data:
    firebase-add-2

  • Now let's test our new app! Open up your firebase-test/index.html file with your web browser and you should now see your message "Hi from Firebase!" appear on the page!

  • Next, navigate back to the "Data" tab of the "Database" page in the Firebase Console, click on your "Hi from Firebase!" message, type in the box to change the value to something else like "I changed this data in Firebase!", and then press the Enter key to save your changes:
    firebase-edit

  • If you switch back to your index.html page in your web browser again, you should see the data change!

πŸ† Congratulations, your first Firebase app is working! The coolest thing about Firebase is that it updates the data in real time so you don't even need to refresh the page to see the changes. Behind the scenes, it's using a WebSocket connection just like our SocketIO chatroom app did! Cool stuff, right?

βœ”οΈ If you haven't already, be sure to make another Git commit. And while you're at it, be sure to check off all the checkboxes in these instructions for every step that you've completed -- that way the rest of our team can easily see your progress!

6. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Create your first Firebase app!" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For Rick: Create your first Firebase app!

Firebase is a set of tools (now owned by Google) that help software developers build web and mobile apps more quickly and easily. We'll be using their real-time database platform as the backend for our app, so we don't have to worry about setting up or maintaining our own server! It's a great beginner-friendly way to start learning about databases, and these "Backend as a Service" (BaaS) tools are a huge trend in the tech industry right now!

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

1. Set up for local development on your computer

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • Switch to the master branch (if you aren't already on it) with the git checkout master command.

  • Get the latest changes from GitHub with the git pull command.

  • Create a new local branch with git checkout -b BRANCH-NAME, replacing BRANCH-NAME with an all-lowercase name for this new feature followed by your initials (for example, firebase-test-lk).

Great! Now any commits you make will be part of this new branch that you just created and switched to.

Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

2. Create new files and folders for your Firebase test app

  • Inside the pair-partners project directory, create a new directory called firebase-test.

    Remember you can create new directories from the command line with the mkdir command, as in mkdir firebase-test.

  • Navigate into the new firebase-test directory and create two new files: index.html and firebasetest.js.

    Remember you can create new files from the command line with the touch command, as in touch index.html firebasetest.js to create both files at the same time!

  • Copy this HTML boilerplate code and paste it into your firebase-test/index.html file (in other words, into your new index.html file inside the firebase-test directory).

  • Change the <title> to something like "Testing Firebase!" or similar.

  • Inside the <body> element, create the following elements:

    • An <h1> heading element that contains the same text as the title, something like "Testing Firebase!" or similar.

    • A empty paragraph with the id of "message", as in <p id="message"></p>.

    • A <script> element to import the Firebase JavaScript library into your web page. The source URL of the Firebase JavaScript file (hosted on Google's servers for our convenience!) is "https://www.gstatic.com/firebasejs/4.1.2/firebase.js". So your code for this step should be:
      <script src="https://www.gstatic.com/firebasejs/4.1.2/firebase.js"></script>.

    • Another <script> element to import your firebasetest.js file, as in:
      <script src="firebasetest.js"></script>.

Awesome! Now that you have your files set up and the Firebase library imported into your web page, you're ready to set up your first Firebase app! If you haven't already, now is a good time to make a Git commit to save your progress!

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/dee22d9806d213aedfa151ed5898bb17

Please don't look at the solutions until after you've checked and double-checked your code for each part of this challenge. No cheating! haha :)

3. Set up your Firebase project

  • Open the Firebase console (which is just a web page that lets you manage your app) and log in using your Google account.

  • Click "Add New Project" and give your project a name like "Firebase Test":
    firebase-add-project

  • Click "Add Firebase to your web app":
    firebase-web-app

  • Copy ONLY the JavaScript code from the initialization code snippet (only the part outlined in red in the screenshot below). Then paste that code into your firebasetest.js file:
    firebase-code-snippet

  • In the Firebase console, navigate to the "Database" page and then to the "Rules" tab.
    Shortcut: Click on this link and then choose your project to get to the page quickly!

  • Double click the code where it says "auth !== null" and type to replace it with true so that the code says ".read": true, ".write": true for the rules. Note: Don't use quote marks around true!
    firebase-rules-publish

  • Click the "Publish" button right above the rules to save your changes. You should now see a warning that your security rules are defined as public and anyone can read or write to your database:
    firebase-rules-public-warning

That's exactly what we want right now; while we're testing this first version of our app, we want it to work without requiring users to sign in first. Later we'll change the rules again to add security as needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/288df7eff9f78e9a44ab9215f8858355

Congrats, you now have a Firebase app! If you haven't already, be sure to make another Git commit to save your progress. Next, let's test out the app and make sure it works!

4. Add JavaScript code to display Firebase data on your web page

  • Create a JavaScript object named 'messageBox' for the HTML element that has an id of "message".

  • Create another JavaScript object called dbRef. This object will be our reference to the "greeting" row of our Firebase database. Use this chain of built-in Firebase methods:
    var dbRef = firebase.database().ref().child("greeting");

  • Last but not least, we'll use another built-in Firebase function to create an event listener that will display our data on the web page any time our database is updated:
    dbRef.on("value", function(dataSnapshot) { messageBox.textContent = dataSnapshot.val(); });

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/43b7edeaa40e3e61b6017c035c07670f

We'll learn more about all of these Firebase functions in the next challenges, but first let's test the app and make sure that our code is working!

5. Add sample data with the Firebase Console and test your app

  • In the two text boxes that pop up, type "greeting" for the name and "Hi from Firebase!" for the value. Then click the blue "Add" button when you're ready to save your new data:
    firebase-add-2

  • In the Firebase Console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the text that looks similar to fir-test-c7763: null and then click on the green plus sign that appears:
    firebase-add-1

  • Now let's test our new app! Open up your firebase-test/index.html file with your web browser and you should now see your message "Hi from Firebase!" appear on the page!

    • Next, navigate back to the "Data" tab of the "Database" page in the Firebase Console, click on your "Hi from Firebase!" message, type in the box to change the value to something else like "I changed this data in Firebase!", and then press the Enter key to save your changes:
      firebase-edit

    • If you switch back to your index.html page in your web browser again, you should see the data change!

πŸ† Congratulations, your first Firebase app is working! The coolest thing about Firebase is that it updates the data in real time so you don't even need to refresh the page to see the changes. Behind the scenes, it's using a WebSocket connection just like our SocketIO chatroom app did! Cool stuff, right?

βœ”οΈ If you haven't already, be sure to make another Git commit. And while you're at it, be sure to check off all the checkboxes in these instructions for every step that you've completed -- that way the rest of our team can easily see your progress!

6. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Create your first Firebase app!" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For everyone: Create a data model for our app

Before we can build our study partner matchmaking app, we need to decide on a clear model for our data! A data model is just a way to organize different pieces of information and define how they all relate to each other. We'll review a couple examples of data modeling both by writing code and drawing diagrams, and then your challenge will be to create one possible data model for our group project!

πŸ“š Prerequisites: First complete the following challenges:

  1. "Create your first Firebase app!"
  2. "Practice displaying Firebase data"
  3. "Practice with JavaScript objects and arrays"

βœ”οΈ To complete this challenge: Review the examples below, and then post a comment at the bottom of this page with your proposed data model for our group project!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

1. Data modeling example with penguins

Remember our fictional penguins from the previous challenge? We used JavaScript objects to model each fictional penguin, using properties to contain each piece of information that we wanted to track for them!

Here's the example code that was provided at the end of that challenge, leaving out the methods (like sayHello) and instead only including the properties that we want to track for our penguins:

var gunter = {
  name: "Gunter",
  origin: "Adventure Time",
  canFly: false,
};

var ramon = {
  name: "RamΓ³n",
  origin: "Happy Feet",
  canFly: true,
};

var fred = {
  name: "Fred",
  origin: "Sitting Ducks",
  canFly: false,
};

Then we created an array to contain a list of our three penguins: var penguins = [gunter, ramon, fred];

Now imagine that we want to build a Firebase app for our penguins, to keep a database that organizes each penguin's information! Here's what that same data might look like inside our Firebase console:

firebase-penguins

Firebase only stores objects, strings, numbers, and Boolean values -- it actually doesn't have any native support for arrays! So to get around that, we stored the list of penguins as nested objects (objects inside of other objects). Now instead of using array indexes to uniquely identify each penguin, we're assigning each penguin object to a property that serves as a unique ID number -- just like a social security number!

We can visualize the hierarchy of this data model by drawing a simple diagram:

penguin-data-model-diagram1

Notice all three penguin objects are inside the penguins object, just as the penguins object is inside the penguinDatabase object! These are still key-value pairs, but here the values are entire objects! If we were to export our data from Firebase, this is what our data structure would look like as JavaScript code:

var penguinDatabase = {

  "penguins": {

    "1152": {
      "canFly": false,
      "name": "Gunter",
      "origin": "Adventure Time"
    },
    "1153": {
      "canFly": true,
      "name": "RamΓ³n",
      "origin": "Happy Feet"
    },
    "7344": {
      "canFly": false,
      "name": "Fred",
      "origin": "Sitting Ducks"
    }

  }

};

2. This is not only a JavaScript object, but valid JSON as well!

JSON stands for JavaScript Object Notation, and it's just a data format that uses JavaScript syntax. JSON can contain strings, numbers, objects and arrays -- the only thing you can't have in JSON data are methods (since by definition, data doesn't really do anything on its own; it just sits there, waiting for some software program to do something with it).

There's even a JSON.stringify() method built into JavaScript that lets you easily convert a JavaScript object into a JSON-formatted string! Test it out for yourself by copying the code above to define your own penguinDatabase object, and then run this code afterwards to see a nicely formatted string appear in your browser console:

console.log( JSON.stringify(penguinDatabase, null, '\t') );

Try it with other objects too! You can also convert JSON strings back into working JavaScript objects again using the built-in JSON.parse() method, too!

3. Read about best practices for structuring Firebase data

Take some time to read "Structure Your Database" in the official Firebase documentation. Take notes on any new vocabulary you find in that article, look closely at their examples, and pay extra attention to their suggestions for best practices.

  • Notice how they describe Firebase as nothing but a tree (or hierarchy) of JSON data!

  • They suggest that you avoid deeply nested data and instead "keep your data structure as flat as possible", because that makes it easier to download only the data you need, instead of inefficiently downloading all of it just to get one tiny section.

  • For two-way relationships in your data, for example between users and groups, it's actually more efficient to duplicate some of your data. In Firebase (and other similar types of databases), a little redundancy can actually be a good thing!

4. Review examples of more complex Firebase data models

OK, so JSON is pretty fun and useful for converting a data model into actual code and vice versa, but the real challenge in data modeling is deciding what data to include and how to organize relationships between difference pieces of data in an efficient and logical way!

First take a look at the Firepad demo, a collaborative text editor very similar to Google Docs that was built with Firebase!

  • Try out their app and take a moment to think about what types of data need to be saved in order to make it work.

Next, take a look at the outline of Firepad's data model.

  • Notice that they track a list of users, a list of revisions, and both of those objects each have a unique ID number.
  • Notice also that each revision is linked to a user by including the user's ID as a property of each revision object!
  • Take a moment to think about how this data model would look if you drew a diagram for it, and also how it would look in JavaScript code as a collection of nested objects.

Finally, take a look at the Firechat demo, a chatroom built with Firebase!

5. Challenge: Create a data model for our group project!

πŸ† The goal: based on what you learned from all the examples above, create a proposal for one possible data model to use for our study partner matchmaking app!

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with the following three things:

  1. An outline of your proposed data model, detailing the objects we should have and the properties we should include for each of those objects. (Follow the format used in Firepad's data model outline.)

  2. A drawing to diagram the relationship of all the objects in your proposed data model, similar to the penguin example above.

  3. A JavaScript code snippet defining a collection of nested objects the way they would look if exported from a Firebase database, following the penguin example above.

Remember, there's no right answer! This is an open-ended challenge to serve as practice and as a conversation-starter for our next brainstorming/design session.

For Krystal: Practice displaying Firebase data

So you've built your first Firebase app, and with just a few lines of JavaScript code, you already know how to take information from your database and display it on your web page! Woohoo! Now here's some more practice to help you check your understanding of the Firebase functions we used to make it happen.

πŸ“š Prerequisites: First complete "Challenge: Create your first Firebase app!"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • If you're not already on it, switch to the local branch that you created in the previous challenge. (For example, Liz's branch was named firebase-test-lk)

    Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

Great! Now any commits you make will be saved to this branch and kept separate from other versions of our project.

2. Create another row in your Firebase database

  • In the Firebase console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the name of your database at the top (probably similar to fir-test-c7763), and then click on the green plus sign that appears:
    firebase-add-row-1

  • In the two text boxes that pop up, type "myname" for the name and enter your actual name for the value. Then click the blue "Add" button to save your new data:
    firebase-add-row-2

3. Edit your JavaScript and HTML to display the new data

πŸ† The goal: Let's change our app to display our two pieces of data in two separate paragraphs that both update in real time when the data changes!

  • In your firebasetest.js file, find and change one word in your code to make your app display your name instead of the previous message.

    Hint: it's a string, and it matches something you typed into the Firebase console earlier.
    To test your app: open up your firebase-test/index.html file with your web browser.

  • Once you got that working, save your work and make a Git commit! Make sure your commit message describes what you changed. For example: "Display myname from Firebase."

  • In your firebase-test/index.html file, create another empty paragraph with the id of "username" and put it above the existing paragraph. This is where we'll display your name!

  • In your firebasetest.js file, turn that new paragraph into a JavaScript object named usernameBox.

    Hint: copy from your existing code for the messageBox object if needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/d886a3c64e9da6121992f63191e1c70a

4. Create more Firebase reference objects

In Firebase, a reference object represents a specific location in your database. Firebase organizes data in a hierarchy or tree structure, just like your computer's file system or the web browser's Document Object Model (which organizes elements of a web page into a hierarchy, with the document object as the root of the entire tree).

So now that we want to access two sections of our database, we're first going to create a reference to the root of our database, and then we'll use the root reference to create two more reference objects: one for "myname" and one for "greeting".

  • Locate the line where you defined the dbRef object, and delete the child() method from the end of that line. So now that line of code should look like: var dbRef = firebase.database().ref();

    Now the dbRef object points to the root of our Firebase database, instead of pointing to the "myname" section of the database.

  • Create two more variables named dbGreeting and dbUsername, set them both equal to dbRef.child(), and remember to give each child() method a string input matching the locations in your database!

    For example: if my database had a row called "color", I'd create a new variable called dbColor and set it equal to dbRef.child("color") to get access to that section of my database.

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/f7a3851bf7fbd6c56890546bb21b5719

5. Review event listeners in JavaScript

πŸ“š Reference link: Review these slides on event listeners from our previous JavaScript slideshow!

Remember JavaScript's built-in addEventListener() method? It took two inputs: a string representing the name of the event and a function to run when the event occurs. For example, if you wanted to run the sayHello function each time the user clicks the submitButton on your web page, your code might look like this: submitButton.addEventListener("click", sayHello);

  • Where is the event happening? On the submitButton
  • Which event are we listening for? The "click" event
  • What should happen when the event occurs? Run the sayHello function

Remember also that your function can receive an input from the event listener, which contains information about the event that just occurred! For example, the event parameter in the code below will be replaced by a MouseEvent object containing lots of information about your mouse clicks:

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}
  • Challenge: Try running the code above, either directly in your browser console or in a CodePen. Click somewhere on the web page, and then look inside the console. Do you see the MouseEvent objects show up in your console? It should look like this:
    console-expand-object

    If that worked, mark the checkbox above to show you completed this step! If not, ask us for help on Slack!

6. Review anonymous functions

Anonymous functions are just functions defined without a name, which is a common practice in JavaScript when you know you're only going to use the function in one place. Let's compare the previous code sample with a version that uses an anonymous function to do the exact same thing:

Example 1: Named function

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}

Example 2: Anonymous function

window.addEventListener("click", function (event) {
  console.log(event);
});

See how the second version is shorter because of the way we defined that anonymous function? This is a pattern you will see again and again in JavaScript; in fact, the code at the end of your firebasetest.js file is using an anonymous function right now! Let's take a closer look.

7. Create another Firebase event listener

If you know how to use event listeners in JavaScript, you already know how to use event listeners in Firebase! The Firebase event listener is a method named on(), and it's the main way to read data from your database. Right now, the end of your JavaScript file should already contain this code:

dbRef.on("value", function(dataSnapshot) {		
  messageBox.textContent = dataSnapshot.val();
});
  • Where is the event happening? On the dbRef object, which now points to the root of our Firebase database!
  • Which event are we listening for? The "value" event, which is triggered any time a value changes inside this database location.
  • What should happen when the event occurs? Run an anonymous function that will display the value of the new data inside the messageBox element on our web page.

Notice that the dataSnapshot parameter works exactly the same as the event parameter in section 5 above; it's given to us by the event listener, and it gets replaced with an object that contains lots of information about the event that just occurred! With Firebase, we don't need to use the entire dataSnapshot object, so instead the convention is to use a special method called val() to extract the data. So when we call dataSnapshot.val(), we're getting the new data from our database and none of the other Firebase information (which we don't need to worry about).

  • Add console.log( dataSnapshot.val() ); into your code so that it will log the new Firebase data to your browser's console any time the Firebase data changes.

  • Open firebase-test/index.html in your web browser again to test it, and look inside your browser console. You should see all your data, formatted as a JavaScript object!

    Try refreshing the page in your web browser if it didn't work. And try changing the values of your data inside the Firebase Console, and see it change on your web page in real-time!

There's just one problem: even though you can see your data in the console, your web page is displaying [object Object] instead of showing your name or your greeting message! Why is that? Because we're using the Firebase event listener on the root of our database, which contains our entire database: {greeting: "Hi from Firebase!", myname: "Liz"}

Notice the format of that data: it's a JavaScript object! We don't want to display the entire database inside one paragraph, though; we want to display a string, one in each paragraph.

  • In your firebasetest.js file, look inside the Firebase event listener code and replace dbRef with dbGreeting so that your code will now only listen for changes to the "greeting" section of your database!

    So now dataSnapshot.val() with return the value of "greeting" in your database, which is a string -- that's what we want!

  • Test it in your web browser again, and you should see your "greeting" message show up on the web page again! Try changing the value of "greeting" from inside the Firebase Console and it should update in real time!

  • Copy all of the Firebase event listener code, and paste a duplicate of it at the end of your firebasetest.js file.

  • Inside the second copy of your Firebase event listener code, replace one variable to display the data inside the other paragraph on your web page.

    Hint: Earlier you created two JavaScript variables for your two paragraphs. What were they named?

  • Now replace one more variable in that same section to tell the Firebase event listener to only listen for updates to the other section of your database.

    Hint: Earlier you created three Firebase reference objects. You should be using two of them for your two Firebase event listeners!

βœ”οΈ SOLUTION for Part 7: https://gist.github.com/LearningNerd/d088d03deff297e6121068788d136eb6

8. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Practice displaying Firebase data" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For Krystal: Add Login with GitHub feature using Firebase Authentication

So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!

πŸ“š Prerequisites: First complete "Challenge: Practice displaying Firebase data"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development and testing with a local server

  • First make sure you're in the pair-partners project folder, and make sure you're on the master branch (use git checkout master if you need to switch).

  • Download the latest working version of our project code from GitHub with git pull -- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work!

  • If you haven't already, make a new local branch called something like gh-login-lk (with your initials at the end) for this new feature.

    Note: it's important that we create this new branch from the master branch, because we want this new branch to start out as a copy of the master branch, with the latest agreed-upon version of our project!

  • Install the http-server package from npm by running this code in your command line: npm install http-server -g (If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)

  • Make sure you're inside the pair-partners/firebase-test folder (if not, use cd to navigate there via command line), and then start your local server by running the http-server command. (Just literally type http-server into your command line, no other words needed!)

    http-server

  • View your app from the local server by going to http://localhost:8080 in your web browser. You should see everything working just like before!

  • Any time you want to turn off your local server, press Ctrl + C on your keyboard. Then run the http-server command again from inside the pair-partners/firebase-test folder each time you want to restart the server.

    Suggestion: If you want to use the command line while running the server, you can open two command line windows at the same time: one to keep the server running, and one to run commands as usual!

Why we need to use a local server

From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!

The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with file:// -- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!

GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like http://localhost:8080 -- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)

2. Create buttons and event listeners for login and logout

  • In your firebase-test/index.html file, add another paragraph that says "Not currently logged in." and give it an ID of "userinfo".

  • Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!

    Remember: all your IDs and variable names should be specific and descriptive (but also relatively short, if possible). There is an art to this! A good rule of thumb is: just by glancing at its name, can you immediately tell how this element is different from all the other elements of your app?

  • In your firebasetest.js file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)

  • Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either "User clicked LOGIN" or "User clicked LOGOUT"

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/26e3996aebf800225145c33e512c0d07

3. Register a new GitHub OAuth application

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript and Registering OAuth Apps on GitHub

OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!

When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password --
never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)

  • First, click here to register a new OAuth app on GitHub.

  • For "Application name", enter something like Pair Partners (Local Test Version)

  • For Homepage URL and "Authorization callback URL", enter http://localhost:8080

    Note: We're going to change the callback URL later to point to Firebase's server. The callback URL is where GitHub will redirect users after they've successfully logged in with GitHub and given permission for our app to access their GitHub account.

  • Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.

4. Set up GitHub authentication in the Firebase console

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript

  • In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab.
    Shortcut: Click on this link and then choose your project.

  • Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).

  • From the bottom of that page, copy the authorization callback URL (it should look something like https://fir-test-c7763.firebaseapp.com/__/auth/handler) and click the blue "Save" button to save your changes in Firebase.

  • Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the http://localhost:8080 link that was there before), and then click the green "Update application" button to save your changes in GitHub.

Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.

5. Add Firebase Authentication functions to your JavaScript

πŸ† The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript (the section titled "Handle the sign-in flow with the Firebase SDK") and Manage Users in Firebase

  • In your firebasetest.js file, create an instance of Firebase's GitHub provider object: var provider = new firebase.auth.GithubAuthProvider();

    Note: It doesn't really matter where you put this in your JavaScript file, as long as you define the provider object before any code that uses it. To keep things organized, it might be best to define this object immediately after you initialize your Firebase app.

  • Change your login button's event listener so that the following code runs every time the user clicks the login button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signInWithPopup(provider).catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signInWithPopup method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)

If you like, you can switch out the signInWithPopup method with the signInWithRedirect method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)

  • Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signOut().catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signOut method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).

  • Add the Firebase onAuthStateChanged event listener method with the following code:

    // When user logs in or logs out:
    firebase.auth().onAuthStateChanged(function(user){
      // If user is now logged in:
      if (user) {
    
        console.log('User successfully logged in to Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display user's GitHub username and GitHub profile photo!
    
      // Otherwise, if no user currently logged in:
      } else {
    
        console.log('User successfully logged OUT from Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display the message "Not currently logged in."
    
      }
    });

The Firebase onAuthStateChanged method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameter user), which contains a bunch of information about the user!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

6. Access Firebase user profile information

First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.

  • Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.

  • In your firebasetest.js file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the // HERE comment -- create one variable for the user's name and one variable for the user's profile photo URL.

    Hint: Remember that you can use dot notation to access properties of JavaScript objects. In this case, the user parameter is our object, and we want to access some properties inside of it!

7. Display the user's profile information on the web page

For the next step, we're going to use a new DOM element property called innerHTML! It's very similar to the textContent property, but the main difference is that innerHTML will render HTML elements in your string as actual HTML elements on the page!

  • First, try a quick test with the textContent property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:

    document.getElementById("userinfo").textContent = 'The <strong>username</strong> will go here and the profile photo will go here: <img src="#">';

You should see that message with the literal HTML tags show up as code on your web page! That's because the textContent property does not render HTML.

  • Next, run the same code as before, but replace textContent with innerHTML, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message!

  • Back in your firebasetest.js file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use its innerHTML property to display the user's name and their actual profile photo!

    Hint: Remember that you can combine variables with literal strings in JavaScript using the + operator, often called the string concatenation operator! For example: "Hello, " + yourNameHere + "! Nice to meet you!"

  • In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the textContent of the "userinfo" paragraph to contain the message "Not currently logged in" so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.

    Note: We can just use textContent this time, because our simple message doesn't contain any HTML tags. It's best to use textContent for simple things like this, because it actually runs much faster in the browser compared to innerHTML!

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

8. Test the app with your local server

Now we're finally ready to see if the app works! Let's try logging in with GitHub!

  • Remember to first start up your local server with the firebase-test folder as the root! (So in command line, first cd into that folder if you aren't already there.) Then run http-server and navigate to http://localhost:8080 in your web browser.

  • Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!

    Debugging tip: If your web app isn't updating as expected after making changes to your code, try these instructions to do a "hard refresh" and clear your web browser's cache!

πŸ† Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!

9. Create a pull request to share your code with us

You know the drill! If you need to review the detailed instructions, see the bottom of the previous challenge ("Practice displaying Firebase data"). Here's a less detailed, quick recap:

  • Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.

  • Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.

  • After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For Rick: Practice displaying Firebase data

So you've built your first Firebase app, and with just a few lines of JavaScript code, you already know how to take information from your database and display it on your web page! Woohoo! Now here's some more practice to help you check your understanding of the Firebase functions we used to make it happen.

πŸ“š Prerequisites: First complete "Challenge: Create your first Firebase app!"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • If you're not already on it, switch to the local branch that you created in the previous challenge. (For example, Liz's branch was named firebase-test-lk)

    Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

Great! Now any commits you make will be saved to this branch and kept separate from other versions of our project.

2. Create another row in your Firebase database

  • In the Firebase console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the name of your database at the top (probably similar to fir-test-c7763), and then click on the green plus sign that appears:
    firebase-add-row-1

  • In the two text boxes that pop up, type "myname" for the name and enter your actual name for the value. Then click the blue "Add" button to save your new data:
    firebase-add-row-2

3. Edit your JavaScript and HTML to display the new data

πŸ† The goal: Let's change our app to display our two pieces of data in two separate paragraphs that both update in real time when the data changes!

  • In your firebasetest.js file, find and change one word in your code to make your app display your name instead of the previous message.

    Hint: it's a string, and it matches something you typed into the Firebase console earlier.
    To test your app: open up your firebase-test/index.html file with your web browser.

  • Once you got that working, save your work and make a Git commit! Make sure your commit message describes what you changed. For example: "Display myname from Firebase."

  • In your firebase-test/index.html file, create another empty paragraph with the id of "username" and put it above the existing paragraph. This is where we'll display your name!

  • In your firebasetest.js file, turn that new paragraph into a JavaScript object named usernameBox.

    Hint: copy from your existing code for the messageBox object if needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/d886a3c64e9da6121992f63191e1c70a

4. Create more Firebase reference objects

In Firebase, a reference object represents a specific location in your database. Firebase organizes data in a hierarchy or tree structure, just like your computer's file system or the web browser's Document Object Model (which organizes elements of a web page into a hierarchy, with the document object as the root of the entire tree).

So now that we want to access two sections of our database, we're first going to create a reference to the root of our database, and then we'll use the root reference to create two more reference objects: one for "myname" and one for "greeting".

  • Locate the line where you defined the dbRef object, and delete the child() method from the end of that line. So now that line of code should look like: var dbRef = firebase.database().ref();

    Now the dbRef object points to the root of our Firebase database, instead of pointing to the "myname" section of the database.

  • Create two more variables named dbGreeting and dbUsername, set them both equal to dbRef.child(), and remember to give each child() method a string input matching the locations in your database!

    For example: if my database had a row called "color", I'd create a new variable called dbColor and set it equal to dbRef.child("color") to get access to that section of my database.

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/f7a3851bf7fbd6c56890546bb21b5719

5. Review event listeners in JavaScript

πŸ“š Reference link: Review these slides on event listeners from our previous JavaScript slideshow!

Remember JavaScript's built-in addEventListener() method? It took two inputs: a string representing the name of the event and a function to run when the event occurs. For example, if you wanted to run the sayHello function each time the user clicks the submitButton on your web page, your code might look like this: submitButton.addEventListener("click", sayHello);

  • Where is the event happening? On the submitButton
  • Which event are we listening for? The "click" event
  • What should happen when the event occurs? Run the sayHello function

Remember also that your function can receive an input from the event listener, which contains information about the event that just occurred! For example, the event parameter in the code below will be replaced by a MouseEvent object containing lots of information about your mouse clicks:

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}
  • Challenge: Try running the code above, either directly in your browser console or in a CodePen. Click somewhere on the web page, and then look inside the console. Do you see the MouseEvent objects show up in your console? It should look like this:
    console-expand-object

    If that worked, mark the checkbox above to show you completed this step! If not, ask us for help on Slack!

6. Review anonymous functions

Anonymous functions are just functions defined without a name, which is a common practice in JavaScript when you know you're only going to use the function in one place. Let's compare the previous code sample with a version that uses an anonymous function to do the exact same thing:

Example 1: Named function

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}

Example 2: Anonymous function

window.addEventListener("click", function (event) {
  console.log(event);
});

See how the second version is shorter because of the way we defined that anonymous function? This is a pattern you will see again and again in JavaScript; in fact, the code at the end of your firebasetest.js file is using an anonymous function right now! Let's take a closer look.

7. Create another Firebase event listener

If you know how to use event listeners in JavaScript, you already know how to use event listeners in Firebase! The Firebase event listener is a method named on(), and it's the main way to read data from your database. Right now, the end of your JavaScript file should already contain this code:

dbRef.on("value", function(dataSnapshot) {		
  messageBox.textContent = dataSnapshot.val();
});
  • Where is the event happening? On the dbRef object, which now points to the root of our Firebase database!
  • Which event are we listening for? The "value" event, which is triggered any time a value changes inside this database location.
  • What should happen when the event occurs? Run an anonymous function that will display the value of the new data inside the messageBox element on our web page.

Notice that the dataSnapshot parameter works exactly the same as the event parameter in section 5 above; it's given to us by the event listener, and it gets replaced with an object that contains lots of information about the event that just occurred! With Firebase, we don't need to use the entire dataSnapshot object, so instead the convention is to use a special method called val() to extract the data. So when we call dataSnapshot.val(), we're getting the new data from our database and none of the other Firebase information (which we don't need to worry about).

  • Add console.log( dataSnapshot.val() ); into your code so that it will log the new Firebase data to your browser's console any time the Firebase data changes.

  • Open firebase-test/index.html in your web browser again to test it, and look inside your browser console. You should see all your data, formatted as a JavaScript object!

    Try refreshing the page in your web browser if it didn't work. And try changing the values of your data inside the Firebase Console, and see it change on your web page in real-time!

There's just one problem: even though you can see your data in the console, your web page is displaying [object Object] instead of showing your name or your greeting message! Why is that? Because we're using the Firebase event listener on the root of our database, which contains our entire database: {greeting: "Hi from Firebase!", myname: "Liz"}

Notice the format of that data: it's a JavaScript object! We don't want to display the entire database inside one paragraph, though; we want to display a string, one in each paragraph.

  • In your firebasetest.js file, look inside the Firebase event listener code and replace dbRef with dbGreeting so that your code will now only listen for changes to the "greeting" section of your database!

    So now dataSnapshot.val() with return the value of "greeting" in your database, which is a string -- that's what we want!

  • Test it in your web browser again, and you should see your "greeting" message show up on the web page again! Try changing the value of "greeting" from inside the Firebase Console and it should update in real time!

  • Copy all of the Firebase event listener code, and paste a duplicate of it at the end of your firebasetest.js file.

  • Inside the second copy of your Firebase event listener code, replace one variable to display the data inside the other paragraph on your web page.

    Hint: Earlier you created two JavaScript variables for your two paragraphs. What were they named?

  • Now replace one more variable in that same section to tell the Firebase event listener to only listen for updates to the other section of your database.

    Hint: Earlier you created three Firebase reference objects. You should be using two of them for your two Firebase event listeners!

βœ”οΈ SOLUTION for Part 7: https://gist.github.com/LearningNerd/d088d03deff297e6121068788d136eb6

8. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Practice displaying Firebase data" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Up for grabs: Create an example of the Firebase "key" property

⭐️ This challenge is up for grabs! Claim it by clicking "assign yourself" on the right, under the "Assignees" section for this GitHub issue! You can work on this by yourself or in pairs.

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with some instructions and sample code, so the rest of our team can learn how to use this new Firebase property by reading your comment!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

About the Firebase key property

πŸ“š Official documentation: Firebase API section on the key property

Every database Reference object in Firebase has a key, except for the root of the database.

Your challenge

πŸ† The goal: learn how this property works, test it out for yourself, and then post a comment at the bottom of this page with some instructions and sample code to help teach the rest of our team!

Questions to keep in mind:

  • What does the official documentation say about this property ?
  • When would we need to use this property ? What are some example use cases? (Write some sample code for us, please!)
  • When should we not use this property ? Can you think of any scenarios where using this property would cause errors or unintended side effects?
  • What data types can be stored as values of this property?

Up for grabs: Create a sample Firebase app that removes penguins from the database

We've created a Firebase app, practiced using arrays and objects for more complex data structures, and we've even done some data modeling with penguins! Now let's take that example penguin app and make it into a real, functional Firebase app!

πŸ“š Prerequisites: First complete the following challenges:

  1. "Practice with JavaScript objects and arrays"
  2. "Create a data model for our app"
  3. "Create an example of the Firebase child() method"
  4. "Create an example of the Firebase remove() method"

βœ”οΈ To complete this challenge: Fork your own copy of this CodePen, write code to finish the sample app, save it, and then post a comment at the bottom of this page with a link to your CodePen!

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

Review of the penguin data model

Remember our fictional penguins from the previous challenge? We used JavaScript objects to model each fictional penguin, using properties to contain each piece of information that we wanted to track for them!

Here's the example code that was provided at the end of that challenge, leaving out the methods (like sayHello) and instead only including the properties that we want to track for our penguins:

var gunter = {
  name: "Gunter",
  origin: "Adventure Time",
  canFly: false,
};

var ramon = {
  name: "RamΓ³n",
  origin: "Happy Feet",
  canFly: true,
};

var fred = {
  name: "Fred",
  origin: "Sitting Ducks",
  canFly: false,
};

Then we created an array to contain a list of our three penguins: var penguins = [gunter, ramon, fred];

This sample CodePen uses a working Firebase database that contains a list of those penguins! Here's what the above penguin data looks like inside the Firebase console for this sample app:

firebase-penguins

Remember: Firebase only stores objects, strings, numbers, and Boolean values -- it actually doesn't have any native support for arrays! So to get around that, we stored the list of penguins as nested objects (objects inside of other objects). Now instead of using array indexes to uniquely identify each penguin, we're assigning each penguin object to a property that serves as a unique ID number -- just like a social security number!

Challenge: Finish the sample app to add penguins to the database!

πŸ† The goal: Add a couple lines of code to this sample CodePen to make a working app that removes a specified penguin from the database based on the user's input.

  1. "Create an example of the Firebase child() method"
  2. "Create an example of the Firebase remove() method"

πŸ’‘ Hint: if you haven't already, first take a look at the challenges for "Create an example of the Firebase child() method" and "Create an example of the Firebase remove() method", and read all the solutions posted in the comments for both of those challenges!

βœ”οΈ To complete this challenge: Fork your own copy of the sample CodePen, write code to get it working, save it, and then post a comment at the bottom of this page with a link to your CodePen!

For Melanie: Practice displaying Firebase data

So you've built your first Firebase app, and with just a few lines of JavaScript code, you already know how to take information from your database and display it on your web page! Woohoo! Now here's some more practice to help you check your understanding of the Firebase functions we used to make it happen.

πŸ“š Prerequisites: First complete "Challenge: Create your first Firebase app!"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • If you're not already on it, switch to the local branch that you created in the previous challenge. (For example, Liz's branch was named firebase-test-lk)

    Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

Great! Now any commits you make will be saved to this branch and kept separate from other versions of our project.

2. Create another row in your Firebase database

  • In the Firebase console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the name of your database at the top (probably similar to fir-test-c7763), and then click on the green plus sign that appears:
    firebase-add-row-1

  • In the two text boxes that pop up, type "myname" for the name and enter your actual name for the value. Then click the blue "Add" button to save your new data:
    firebase-add-row-2

3. Edit your JavaScript and HTML to display the new data

πŸ† The goal: Let's change our app to display our two pieces of data in two separate paragraphs that both update in real time when the data changes!

  • In your firebasetest.js file, find and change one word in your code to make your app display your name instead of the previous message.

    Hint: it's a string, and it matches something you typed into the Firebase console earlier.
    To test your app: open up your firebase-test/index.html file with your web browser.

  • Once you got that working, save your work and make a Git commit! Make sure your commit message describes what you changed. For example: "Display myname from Firebase."

  • In your firebase-test/index.html file, create another empty paragraph with the id of "username" and put it above the existing paragraph. This is where we'll display your name!

  • In your firebasetest.js file, turn that new paragraph into a JavaScript object named usernameBox.

    Hint: copy from your existing code for the messageBox object if needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/d886a3c64e9da6121992f63191e1c70a

4. Create more Firebase reference objects

In Firebase, a reference object represents a specific location in your database. Firebase organizes data in a hierarchy or tree structure, just like your computer's file system or the web browser's Document Object Model (which organizes elements of a web page into a hierarchy, with the document object as the root of the entire tree).

So now that we want to access two sections of our database, we're first going to create a reference to the root of our database, and then we'll use the root reference to create two more reference objects: one for "myname" and one for "greeting".

  • Locate the line where you defined the dbRef object, and delete the child() method from the end of that line. So now that line of code should look like: var dbRef = firebase.database().ref();

    Now the dbRef object points to the root of our Firebase database, instead of pointing to the "myname" section of the database.

  • Create two more variables named dbGreeting and dbUsername, set them both equal to dbRef.child(), and remember to give each child() method a string input matching the locations in your database!

    For example: if my database had a row called "color", I'd create a new variable called dbColor and set it equal to dbRef.child("color") to get access to that section of my database.

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/f7a3851bf7fbd6c56890546bb21b5719

5. Review event listeners in JavaScript

πŸ“š Reference link: Review these slides on event listeners from our previous JavaScript slideshow!

Remember JavaScript's built-in addEventListener() method? It took two inputs: a string representing the name of the event and a function to run when the event occurs. For example, if you wanted to run the sayHello function each time the user clicks the submitButton on your web page, your code might look like this: submitButton.addEventListener("click", sayHello);

  • Where is the event happening? On the submitButton
  • Which event are we listening for? The "click" event
  • What should happen when the event occurs? Run the sayHello function

Remember also that your function can receive an input from the event listener, which contains information about the event that just occurred! For example, the event parameter in the code below will be replaced by a MouseEvent object containing lots of information about your mouse clicks:

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}
  • Challenge: Try running the code above, either directly in your browser console or in a CodePen. Click somewhere on the web page, and then look inside the console. Do you see the MouseEvent objects show up in your console? It should look like this:
    console-expand-object

    If that worked, mark the checkbox above to show you completed this step! If not, ask us for help on Slack!

6. Review anonymous functions

Anonymous functions are just functions defined without a name, which is a common practice in JavaScript when you know you're only going to use the function in one place. Let's compare the previous code sample with a version that uses an anonymous function to do the exact same thing:

Example 1: Named function

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}

Example 2: Anonymous function

window.addEventListener("click", function (event) {
  console.log(event);
});

See how the second version is shorter because of the way we defined that anonymous function? This is a pattern you will see again and again in JavaScript; in fact, the code at the end of your firebasetest.js file is using an anonymous function right now! Let's take a closer look.

7. Create another Firebase event listener

If you know how to use event listeners in JavaScript, you already know how to use event listeners in Firebase! The Firebase event listener is a method named on(), and it's the main way to read data from your database. Right now, the end of your JavaScript file should already contain this code:

dbRef.on("value", function(dataSnapshot) {		
  messageBox.textContent = dataSnapshot.val();
});
  • Where is the event happening? On the dbRef object, which now points to the root of our Firebase database!
  • Which event are we listening for? The "value" event, which is triggered any time a value changes inside this database location.
  • What should happen when the event occurs? Run an anonymous function that will display the value of the new data inside the messageBox element on our web page.

Notice that the dataSnapshot parameter works exactly the same as the event parameter in section 5 above; it's given to us by the event listener, and it gets replaced with an object that contains lots of information about the event that just occurred! With Firebase, we don't need to use the entire dataSnapshot object, so instead the convention is to use a special method called val() to extract the data. So when we call dataSnapshot.val(), we're getting the new data from our database and none of the other Firebase information (which we don't need to worry about).

  • Add console.log( dataSnapshot.val() ); into your code so that it will log the new Firebase data to your browser's console any time the Firebase data changes.

  • Open firebase-test/index.html in your web browser again to test it, and look inside your browser console. You should see all your data, formatted as a JavaScript object!

    Try refreshing the page in your web browser if it didn't work. And try changing the values of your data inside the Firebase Console, and see it change on your web page in real-time!

There's just one problem: even though you can see your data in the console, your web page is displaying [object Object] instead of showing your name or your greeting message! Why is that? Because we're using the Firebase event listener on the root of our database, which contains our entire database: {greeting: "Hi from Firebase!", myname: "Liz"}

Notice the format of that data: it's a JavaScript object! We don't want to display the entire database inside one paragraph, though; we want to display a string, one in each paragraph.

  • In your firebasetest.js file, look inside the Firebase event listener code and replace dbRef with dbGreeting so that your code will now only listen for changes to the "greeting" section of your database!

    So now dataSnapshot.val() with return the value of "greeting" in your database, which is a string -- that's what we want!

  • Test it in your web browser again, and you should see your "greeting" message show up on the web page again! Try changing the value of "greeting" from inside the Firebase Console and it should update in real time!

  • Copy all of the Firebase event listener code, and paste a duplicate of it at the end of your firebasetest.js file.

  • Inside the second copy of your Firebase event listener code, replace one variable to display the data inside the other paragraph on your web page.

    Hint: Earlier you created two JavaScript variables for your two paragraphs. What were they named?

  • Now replace one more variable in that same section to tell the Firebase event listener to only listen for updates to the other section of your database.

    Hint: Earlier you created three Firebase reference objects. You should be using two of them for your two Firebase event listeners!

βœ”οΈ SOLUTION for Part 7: https://gist.github.com/LearningNerd/d088d03deff297e6121068788d136eb6

8. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Practice displaying Firebase data" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

For Nao: Add Login with GitHub feature using Firebase Authentication

So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!

πŸ“š Prerequisites: First complete "Challenge: Practice displaying Firebase data"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development and testing with a local server

  • First make sure you're in the pair-partners project folder, and make sure you're on the master branch (use git checkout master if you need to switch).

  • Download the latest working version of our project code from GitHub with git pull -- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work!

  • If you haven't already, make a new local branch called something like gh-login-lk (with your initials at the end) for this new feature.

    Note: it's important that we create this new branch from the master branch, because we want this new branch to start out as a copy of the master branch, with the latest agreed-upon version of our project!

  • Install the http-server package from npm by running this code in your command line: npm install http-server -g (If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)

  • Make sure you're inside the pair-partners/firebase-test folder (if not, use cd to navigate there via command line), and then start your local server by running the http-server command. (Just literally type http-server into your command line, no other words needed!)

    http-server

  • View your app from the local server by going to http://localhost:8080 in your web browser. You should see everything working just like before!

  • Any time you want to turn off your local server, press Ctrl + C on your keyboard. Then run the http-server command again from inside the pair-partners/firebase-test folder each time you want to restart the server.

    Suggestion: If you want to use the command line while running the server, you can open two command line windows at the same time: one to keep the server running, and one to run commands as usual!

Why we need to use a local server

From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!

The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with file:// -- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!

GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like http://localhost:8080 -- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)

2. Create buttons and event listeners for login and logout

  • In your firebase-test/index.html file, add another paragraph that says "Not currently logged in." and give it an ID of "userinfo".

  • Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!

    Remember: all your IDs and variable names should be specific and descriptive (but also relatively short, if possible). There is an art to this! A good rule of thumb is: just by glancing at its name, can you immediately tell how this element is different from all the other elements of your app?

  • In your firebasetest.js file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)

  • Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either "User clicked LOGIN" or "User clicked LOGOUT"

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/26e3996aebf800225145c33e512c0d07

3. Register a new GitHub OAuth application

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript and Registering OAuth Apps on GitHub

OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!

When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password --
never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)

  • First, click here to register a new OAuth app on GitHub.

  • For "Application name", enter something like Pair Partners (Local Test Version)

  • For Homepage URL and "Authorization callback URL", enter http://localhost:8080

    Note: We're going to change the callback URL later to point to Firebase's server. The callback URL is where GitHub will redirect users after they've successfully logged in with GitHub and given permission for our app to access their GitHub account.

  • Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.

4. Set up GitHub authentication in the Firebase console

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript

  • In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab.
    Shortcut: Click on this link and then choose your project.

  • Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).

  • From the bottom of that page, copy the authorization callback URL (it should look something like https://fir-test-c7763.firebaseapp.com/__/auth/handler) and click the blue "Save" button to save your changes in Firebase.

  • Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the http://localhost:8080 link that was there before), and then click the green "Update application" button to save your changes in GitHub.

Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.

5. Add Firebase Authentication functions to your JavaScript

πŸ† The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript (the section titled "Handle the sign-in flow with the Firebase SDK") and Manage Users in Firebase

  • In your firebasetest.js file, create an instance of Firebase's GitHub provider object: var provider = new firebase.auth.GithubAuthProvider();

    Note: It doesn't really matter where you put this in your JavaScript file, as long as you define the provider object before any code that uses it. To keep things organized, it might be best to define this object immediately after you initialize your Firebase app.

  • Change your login button's event listener so that the following code runs every time the user clicks the login button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signInWithPopup(provider).catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signInWithPopup method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)

If you like, you can switch out the signInWithPopup method with the signInWithRedirect method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)

  • Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signOut().catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signOut method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).

  • Add the Firebase onAuthStateChanged event listener method with the following code:

    // When user logs in or logs out:
    firebase.auth().onAuthStateChanged(function(user){
      // If user is now logged in:
      if (user) {
    
        console.log('User successfully logged in to Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display user's GitHub username and GitHub profile photo!
    
      // Otherwise, if no user currently logged in:
      } else {
    
        console.log('User successfully logged OUT from Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display the message "Not currently logged in."
    
      }
    });

The Firebase onAuthStateChanged method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameter user), which contains a bunch of information about the user!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

6. Access Firebase user profile information

First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.

  • Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.

  • In your firebasetest.js file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the // HERE comment -- create one variable for the user's name and one variable for the user's profile photo URL.

    Hint: Remember that you can use dot notation to access properties of JavaScript objects. In this case, the user parameter is our object, and we want to access some properties inside of it!

7. Display the user's profile information on the web page

For the next step, we're going to use a new DOM element property called innerHTML! It's very similar to the textContent property, but the main difference is that innerHTML will render HTML elements in your string as actual HTML elements on the page!

  • First, try a quick test with the textContent property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:

    document.getElementById("userinfo").textContent = 'The <strong>username</strong> will go here and the profile photo will go here: <img src="#">';

You should see that message with the literal HTML tags show up as code on your web page! That's because the textContent property does not render HTML.

  • Next, run the same code as before, but replace textContent with innerHTML, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message!

  • Back in your firebasetest.js file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use its innerHTML property to display the user's name and their actual profile photo!

    Hint: Remember that you can combine variables with literal strings in JavaScript using the + operator, often called the string concatenation operator! For example: "Hello, " + yourNameHere + "! Nice to meet you!"

  • In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the textContent of the "userinfo" paragraph to contain the message "Not currently logged in" so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.

    Note: We can just use textContent this time, because our simple message doesn't contain any HTML tags. It's best to use textContent for simple things like this, because it actually runs much faster in the browser compared to innerHTML!

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

8. Test the app with your local server

Now we're finally ready to see if the app works! Let's try logging in with GitHub!

  • Remember to first start up your local server with the firebase-test folder as the root! (So in command line, first cd into that folder if you aren't already there.) Then run http-server and navigate to http://localhost:8080 in your web browser.

  • Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!

    Debugging tip: If your web app isn't updating as expected after making changes to your code, try these instructions to do a "hard refresh" and clear your web browser's cache!

πŸ† Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!

9. Create a pull request to share your code with us

You know the drill! If you need to review the detailed instructions, see the bottom of the previous challenge ("Practice displaying Firebase data"). Here's a less detailed, quick recap:

  • Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.

  • Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.

  • After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Up for grabs: Create an example of the Firebase child() method

⭐️ This challenge is up for grabs! Claim it by clicking "assign yourself" on the right, under the "Assignees" section for this GitHub issue! You can work on this by yourself or in pairs.

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with some instructions and sample code, so the rest of our team can learn how to use this new Firebase method by reading your comment!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

About the Firebase child method

πŸ“š Official documentation: Firebase API section on the child method

The child method lets you access a location in a Firebase database, relative to another location in the database! It's often used along with the remove method -- see "Create an example of the Firebase remove() method".

Your challenge

πŸ† The goal: learn how this method works, test it out for yourself, and then post a comment at the bottom of this page with some instructions and sample code to help teach the rest of our team!

Questions to keep in mind:

  • What does the official documentation say about this method?
  • When would we need to use this method? What are some example use cases? (Write some sample code for us, please!)
  • When should we not use this method? Can you think of any scenarios where using this method would cause errors or unintended side effects?
  • How many inputs does this method require, if any? What data types can the inputs be?
  • What does this method return as an output, if any? What data type is returned?
  • If there are different options for inputs, how does this method behave differently depending on the different possible input(s)?

For Nao: Practice displaying Firebase data

So you've built your first Firebase app, and with just a few lines of JavaScript code, you already know how to take information from your database and display it on your web page! Woohoo! Now here's some more practice to help you check your understanding of the Firebase functions we used to make it happen.

πŸ“š Prerequisites: First complete "Challenge: Create your first Firebase app!"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • If you're not already on it, switch to the local branch that you created in the previous challenge. (For example, Liz's branch was named firebase-test-lk)

    Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

Great! Now any commits you make will be saved to this branch and kept separate from other versions of our project.

2. Create another row in your Firebase database

  • In the Firebase console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the name of your database at the top (probably similar to fir-test-c7763), and then click on the green plus sign that appears:
    firebase-add-row-1

  • In the two text boxes that pop up, type "myname" for the name and enter your actual name for the value. Then click the blue "Add" button to save your new data:
    firebase-add-row-2

3. Edit your JavaScript and HTML to display the new data

πŸ† The goal: Let's change our app to display our two pieces of data in two separate paragraphs that both update in real time when the data changes!

  • In your firebasetest.js file, find and change one word in your code to make your app display your name instead of the previous message.

    Hint: it's a string, and it matches something you typed into the Firebase console earlier.
    To test your app: open up your firebase-test/index.html file with your web browser.

  • Once you got that working, save your work and make a Git commit! Make sure your commit message describes what you changed. For example: "Display myname from Firebase."

  • In your firebase-test/index.html file, create another empty paragraph with the id of "username" and put it above the existing paragraph. This is where we'll display your name!

  • In your firebasetest.js file, turn that new paragraph into a JavaScript object named usernameBox.

    Hint: copy from your existing code for the messageBox object if needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/d886a3c64e9da6121992f63191e1c70a

4. Create more Firebase reference objects

In Firebase, a reference object represents a specific location in your database. Firebase organizes data in a hierarchy or tree structure, just like your computer's file system or the web browser's Document Object Model (which organizes elements of a web page into a hierarchy, with the document object as the root of the entire tree).

So now that we want to access two sections of our database, we're first going to create a reference to the root of our database, and then we'll use the root reference to create two more reference objects: one for "myname" and one for "greeting".

  • Locate the line where you defined the dbRef object, and delete the child() method from the end of that line. So now that line of code should look like: var dbRef = firebase.database().ref();

    Now the dbRef object points to the root of our Firebase database, instead of pointing to the "myname" section of the database.

  • Create two more variables named dbGreeting and dbUsername, set them both equal to dbRef.child(), and remember to give each child() method a string input matching the locations in your database!

    For example: if my database had a row called "color", I'd create a new variable called dbColor and set it equal to dbRef.child("color") to get access to that section of my database.

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/f7a3851bf7fbd6c56890546bb21b5719

5. Review event listeners in JavaScript

πŸ“š Reference link: Review these slides on event listeners from our previous JavaScript slideshow!

Remember JavaScript's built-in addEventListener() method? It took two inputs: a string representing the name of the event and a function to run when the event occurs. For example, if you wanted to run the sayHello function each time the user clicks the submitButton on your web page, your code might look like this: submitButton.addEventListener("click", sayHello);

  • Where is the event happening? On the submitButton
  • Which event are we listening for? The "click" event
  • What should happen when the event occurs? Run the sayHello function

Remember also that your function can receive an input from the event listener, which contains information about the event that just occurred! For example, the event parameter in the code below will be replaced by a MouseEvent object containing lots of information about your mouse clicks:

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}
  • Challenge: Try running the code above, either directly in your browser console or in a CodePen. Click somewhere on the web page, and then look inside the console. Do you see the MouseEvent objects show up in your console? It should look like this:
    console-expand-object

    If that worked, mark the checkbox above to show you completed this step! If not, ask us for help on Slack!

6. Review anonymous functions

Anonymous functions are just functions defined without a name, which is a common practice in JavaScript when you know you're only going to use the function in one place. Let's compare the previous code sample with a version that uses an anonymous function to do the exact same thing:

Example 1: Named function

window.addEventListener("click", logMouseEvent);

function logMouseEvent (event) {
  console.log(event);
}

Example 2: Anonymous function

window.addEventListener("click", function (event) {
  console.log(event);
});

See how the second version is shorter because of the way we defined that anonymous function? This is a pattern you will see again and again in JavaScript; in fact, the code at the end of your firebasetest.js file is using an anonymous function right now! Let's take a closer look.

7. Create another Firebase event listener

If you know how to use event listeners in JavaScript, you already know how to use event listeners in Firebase! The Firebase event listener is a method named on(), and it's the main way to read data from your database. Right now, the end of your JavaScript file should already contain this code:

dbRef.on("value", function(dataSnapshot) {		
  messageBox.textContent = dataSnapshot.val();
});
  • Where is the event happening? On the dbRef object, which now points to the root of our Firebase database!
  • Which event are we listening for? The "value" event, which is triggered any time a value changes inside this database location.
  • What should happen when the event occurs? Run an anonymous function that will display the value of the new data inside the messageBox element on our web page.

Notice that the dataSnapshot parameter works exactly the same as the event parameter in section 5 above; it's given to us by the event listener, and it gets replaced with an object that contains lots of information about the event that just occurred! With Firebase, we don't need to use the entire dataSnapshot object, so instead the convention is to use a special method called val() to extract the data. So when we call dataSnapshot.val(), we're getting the new data from our database and none of the other Firebase information (which we don't need to worry about).

  • Add console.log( dataSnapshot.val() ); into your code so that it will log the new Firebase data to your browser's console any time the Firebase data changes.

  • Open firebase-test/index.html in your web browser again to test it, and look inside your browser console. You should see all your data, formatted as a JavaScript object!

    Try refreshing the page in your web browser if it didn't work. And try changing the values of your data inside the Firebase Console, and see it change on your web page in real-time!

There's just one problem: even though you can see your data in the console, your web page is displaying [object Object] instead of showing your name or your greeting message! Why is that? Because we're using the Firebase event listener on the root of our database, which contains our entire database: {greeting: "Hi from Firebase!", myname: "Liz"}

Notice the format of that data: it's a JavaScript object! We don't want to display the entire database inside one paragraph, though; we want to display a string, one in each paragraph.

  • In your firebasetest.js file, look inside the Firebase event listener code and replace dbRef with dbGreeting so that your code will now only listen for changes to the "greeting" section of your database!

    So now dataSnapshot.val() with return the value of "greeting" in your database, which is a string -- that's what we want!

  • Test it in your web browser again, and you should see your "greeting" message show up on the web page again! Try changing the value of "greeting" from inside the Firebase Console and it should update in real time!

  • Copy all of the Firebase event listener code, and paste a duplicate of it at the end of your firebasetest.js file.

  • Inside the second copy of your Firebase event listener code, replace one variable to display the data inside the other paragraph on your web page.

    Hint: Earlier you created two JavaScript variables for your two paragraphs. What were they named?

  • Now replace one more variable in that same section to tell the Firebase event listener to only listen for updates to the other section of your database.

    Hint: Earlier you created three Firebase reference objects. You should be using two of them for your two Firebase event listeners!

βœ”οΈ SOLUTION for Part 7: https://gist.github.com/LearningNerd/d088d03deff297e6121068788d136eb6

8. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Practice displaying Firebase data" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Up for grabs: Create a sample Firebase app that adds penguins to the database!

We've created a Firebase app, practiced using arrays and objects for more complex data structures, and we've even done some data modeling with penguins! Now let's take that example penguin app and make it into a real, functional Firebase app!

πŸ“š Prerequisites: First complete the following challenges:

  1. "Practice with JavaScript objects and arrays"
  2. "Create a data model for our app"
  3. "Create an example of the Firebase push() method"

βœ”οΈ To complete this challenge: Fork your own copy of this CodePen, write code to finish the sample app, save it, and then post a comment at the bottom of this page with a link to your CodePen!

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

Review of the penguin data model

Remember our fictional penguins from the previous challenge? We used JavaScript objects to model each fictional penguin, using properties to contain each piece of information that we wanted to track for them!

Here's the example code that was provided at the end of that challenge, leaving out the methods (like sayHello) and instead only including the properties that we want to track for our penguins:

var gunter = {
  name: "Gunter",
  origin: "Adventure Time",
  canFly: false,
};

var ramon = {
  name: "RamΓ³n",
  origin: "Happy Feet",
  canFly: true,
};

var fred = {
  name: "Fred",
  origin: "Sitting Ducks",
  canFly: false,
};

Then we created an array to contain a list of our three penguins: var penguins = [gunter, ramon, fred];

This sample CodePen uses a working Firebase database that contains a list of those penguins! Here's what the above penguin data looks like inside the Firebase console for this sample app:

firebase-penguins

Remember: Firebase only stores objects, strings, numbers, and Boolean values -- it actually doesn't have any native support for arrays! So to get around that, we stored the list of penguins as nested objects (objects inside of other objects). Now instead of using array indexes to uniquely identify each penguin, we're assigning each penguin object to a property that serves as a unique ID number -- just like a social security number!

Challenge: Finish the sample app to add penguins to the database!

πŸ† The goal: Add a couple lines of code to this sample CodePen to make a working app that adds a penguin to the database every time the user clicks the button.

πŸ’‘ Hint: if you haven't already, first take a look at the challenge to "Create an example of the Firebase push() method" and read all the solutions posted in the comments at the bottom of that page!

βœ”οΈ To complete this challenge: Fork your own copy of the sample CodePen, write code to get it working, save it, and then post a comment at the bottom of this page with a link to your CodePen!

For everyone: Practice with JavaScript objects and arrays

βœ”οΈ To complete this challenge: Write and test your code in the provided REPL.it links below (remember to click Save to save your work!), and copy the links to your solutions and paste them into a comment on the bottom of this page.

You can edit your comment at any point to update your answers, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

πŸ“ Solutions and more practice problems will be posted soon!

Reviewing the big picture!

For these first few questions, write a few sentences to explain your answers and post those directly in your comment at the bottom of this page (along with the links to your code for the other solutions). It's OK to do some research if you need a refresher -- just be sure to cite your sources!

1. What are arrays in JavaScript and why are they useful?

2. What are objects in JavaScript and why are they useful?

3. What are a couple of key differences between objects and arrays? (And can you find any good examples or metaphors that illustrate the difference?)

4. What is the index of an array? What is it used for?

5. What is a property?

6. What is a method?

Review of arrays

✏️ Write and test your answers for this section here: https://repl.it/IlVK/0
And remember to click "Save" at the top to save your progress and save the URL! When you're done, save it again, copy the links to your solutions, and paste them all into your comment on the bottom of this page.

7. Create an array named colors that contains five different names of colors as strings.

8. Access the first color in the array and print it to the console using console.log()

9. Now do the same with the third color in the list. (Remember that array indexes start at 0, not at 1!)

10. Write one line of code that changes the value of the last color in the list to "ultraviolet" (overwriting the previous value).

11. Create a new variable called fourthColor and set it equal to the fourth color in the list.

12. Add another color to the end of the list.

13. Add another color to the beginning of the list.

14. Print the length of the array to the console with console.log()

15. Remove the last color from the end of list, and then print the length of the array to the console one more time.

16. Write a for loop to iterate through every color in the array and print each color's value to the console.

17. Copying from that loop you just wrote, modify it to print every color's value and every color's index in this format: 3, purple or 0, blue etc.

18. Create a variable named lastColor that will always point to the last element of the colors array, no matter how many colors are in the list. (Hint: make use of the array's length property for this!)

βœ”οΈ SOLUTION for array review problems: https://repl.it/IlVK/2

Review of objects

✏️ Write and test your answers for this section here: https://repl.it/IlV2/1

For now, we'll just stick with one way to create objects in JavaScript called object literal notation or object initializers. Feel free to use that link as a reference or find other examples online if you need a refresher.

πŸ“š For extra review: read MDN's intro to JavaScript objects

19. Pick a penguin from Wikipedia's List of Fictional Penguins and create an object named myPenguin with properties that represent the information listed in each column on that Wikipedia page (for example: the character's name, origin, and author).

20. Use console.log() to print the penguin's name to the console as part of a welcome message, like "Hello, I'm a penguin and my name is [NAME HERE]!"

21. Write another line of code that adds a new property to your penguin called canFly and set it to false. (Note: Don't modify your penguin-creation code that you wrote above! Do this step in a separate line of code.)

22. Add a method to your penguin called chirp that prints to the console: "CHIRP CHIRP! Is this what penguins sound like?" (Note: Again, don't modify your previous code! Do this step by writing a new line of code.)

23. Add another method to your penguin called sayHello that prints to the console the same message from step 20 above. But this time, be sure to use the mystical, magical, all-powerful this keyword to access your penguin's name, so that way the sayHello method could potentially work for any penguin that has a name!

24. Next, call your penguin's sayHello() method and make sure that it works! (Hint: if you need an example of what it looks like when you call a method of an object, look at console.log() -- that's how you call the log() method of the console object!)

25. Without modifying any of your previous code, change the penguin's name to "Penguin McPenguinFace" and then call your penguin's sayHello() function one more time to make sure it still works.

26. Write another method called fly, and inside that method, use an if / else statement to print "I can fly!" to the console if your penguin's canFly property is true, or "No flying for me!" if its canFly property is false.

Hint: Remember to use the very handy this keyword to access the object that your new method is currently attached to!

27. Call your penguin's fly() method and make sure it works!

28. Change the canFly property to true -- again, without modifying any of your previous code!

29. Now call your penguin's fly() method again and make sure it works as expected!

30. Write a for ... in loop to print each key to the console. (Hint: See this page for an example of this special type of loop.)

31. Write another for ... in loop to print the value of each key to the console. (Hint: You'll need to use bracket notation to access the values this way, instead of dot notation!)

βœ”οΈ SOLUTION for object review problems: https://repl.it/IlV2/7

Arrays inside objects

✏️ Write and test your answers for this section here: https://repl.it/IlVj/3

32. Add a new property to your penguin called favoriteFoods and set it equal to an array containing a list of three strings.

33. Access your penguin's second favorite food and print it to the console using console.log()

34. Create a new variable called firstFavFood and set it equal to the first item in your penguin's array of favorite foods.

35. Add another food to the end of the list.

36. Print the length of your penguin's favoriteFoods array to the console with console.log()

37. Without modifying any of your previous code, write a new line of code that changes the value of the last item in the list to "pineapples" (overwriting the previous value).

38. Create a new variable named lastFavFood that will always point to the last element of your penguin's favoriteFoods array, no matter how many items are in the list. (Hint: this is essentially the same problem as step 18 from above.)

39. Write a for loop to iterate through every food in your penguin's favoriteFood property and print each one to the console. (Hint: This loop will look exactly the same as the one you wrote for step 16 above, except now you're accessing the array as a property of an object.)

βœ”οΈ SOLUTION for arrays inside objects review problems: https://repl.it/IlVj/4

Objects inside other objects

✏️ Write and test your answers for this section here: https://repl.it/IlVr/4

It's cold at the South Pole, so let's give this penguin some clothes!

40. Add a new property to your penguin called outfit and set it equal to another object with the following properties: hat, shirt, pants, and shoes -- each property should have a string as its value! (I suggest you give it a baseball cap, Hawaiian shirt, cargo shorts, and flip-flops, because wouldn't that be ridiculous?)

41. Create a new variable called penguinHatType and set it equal to the value of the hat in your penguin's outfit! Then print your new variable to the console.

42. Without modifying any of your previous code, write one new line of code to add an accessory property to your penguin's outfit and set it equal to the string "pocket watch" -- because penguins are classy like that!

43. Write one more line of code to change the hat in your penguin's outfit to "top hat" and override the previous value. (Again, because penguins are classy!)

44. This penguin is a freelancer who always works from home, so it doesn't actually need to wear any pants! Let's delete the pants property from this penguin's outfit property. (Hint: see this page on the delete operator for examples.)

45. Write a for ... in loop to print the value of each piece of clothing in your penguin's outfit so you can see a list of clothing items in the console. (Hint: This is the same as step 31 from above, only now we're accessing values from a nested object!)

βœ”οΈ SOLUTION for arrays inside objects review problems: https://repl.it/IlVr/6

Objects inside arrays

✏️ Write and test your answers for this section here: https://repl.it/IlVy/4

For these last few challenges, I'll create three penguins for you to work with. Copy-paste this code snippet to the end of your code:

var gunter = {
  name: "Gunter",
  origin: "Adventure Time",
  canFly: false,
  sayHello: function () {
    console.log("QUACK!!!");
  }
};

var ramon = {
  name: "RamΓ³n",
  origin: "Happy Feet",
  canFly: true,
  sayHello: function () {
    console.log("Estoy encantado de conocerle.");
  }
};

var fred = {
  name: "Fred",
  origin: "Sitting Ducks",
  canFly: false,
  sayHello: function () {
    console.log("Hi there!");
  }
};

46. Create a new variable named penguins and set it equal to an array that lists these three penguins! (Hint: remember you can put variable names inside an array, not just hard-coded values! And remember that variable names don't have quotes around them.)

47. Access the first penguin in the list and print it to the console using console.log() -- notice that you can see all the properties and methods of that object listed in the console! (Hint: remember that array indexes start counting at 0, not 1!)

48. Create a new variable called secondPenguin and set it equal to the second penguin in your penguins array.

49. Print to the console the name of the last penguin in the list.

50. Remember the penguin you created earlier, with the variable name of myPenguin? Add that penguin to the end of the penguins array!

51. Print the length of the penguins array to the console.

52. Write one more line of code to change the first penguin's canFly property to the value true (overriding its existing value).

53. Call the sayHello method of the first penguin in your penguins array!

54. Write a for loop to iterate through every penguin in the array and print the value of each penguin's name property to the console.

55. Write a for loop to call the sayHello method of every penguin in the array!

56. Write a for loop to iterate through every penguin in the array, and add a new property to each penguin called numberOfFeet with the value 2

57. Write another for loop to iterate through every penguin in the array, and for each penguin that can fly, print to the console a message containing the penguin's name and " can fly!" -- for example, "Gunter can fly!" or "RamΓ³n can fly!" (Don't do anything for the penguins that cannot fly.)

πŸ† Great work! You're well on your way towards earning your black belt as a JavaScript ninja!

πŸ“ The rest of the solutions will be posted soon!

Editing User Profile feature

Implementing a feature which allows the user to edit fields on their profile:
username:
city:
checkboxes for languages:

Save Changes - button

Messaging service

Implementing a direct messaging service that users can use to communicate with each other located across every page.

Login With Github

Is the User's Login accessed via their Github Account?
If not, what happens if the User forgets their password?

Up for grabs: Create an example of the Firebase set() method

⭐️ This challenge is up for grabs! Claim it by clicking "assign yourself" on the right, under the "Assignees" section for this GitHub issue! You can work on this by yourself or in pairs.

βœ”οΈ To complete this challenge: Post a comment at the bottom of this page with some instructions and sample code, so the rest of our team can learn how to use this new Firebase method by reading your comment!

You can edit your comment at any point to update your answer, so you don't have to do these all at once! To edit your comment after you publish it, click the pencil icon in the top right corner of your comment:
github-edit-comments

❓ If you have any questions, please post a comment at the bottom of this page! (You can also ask us on Slack, but please post a comment here too so we can more easily reference it later.)

About the Firebase set method

πŸ“š Official documentation: Firebase API section on the set method

The set method saves data to a specified location in the database (using a database Reference object). If that database location doesn't exist yet, the set method will create it! Otherwise, if data already exists there, the set method will replace it with the new data. If that database location contains any children (nested objects), they will all be overwritten with the new data.

Your challenge

πŸ† The goal: learn how this method works, test it out for yourself, and then post a comment at the bottom of this page with some instructions and sample code to help teach the rest of our team!

Questions to keep in mind:

  • What does the official documentation say about this method?
  • When would we need to use this method? What are some example use cases? (Write some sample code for us, please!)
  • When should we not use this method? Can you think of any scenarios where using this method would cause errors or unintended side effects?
  • How many inputs does this method require, if any? What data types can the inputs be?
  • What does this method return as an output, if any? What data type is returned?
  • If there are different options for inputs, how does this method behave differently depending on the different possible input(s)?

For Melanie: Create your first Firebase app!

Firebase is a set of tools (now owned by Google) that help software developers build web and mobile apps more quickly and easily. We'll be using their real-time database platform as the backend for our app, so we don't have to worry about setting up or maintaining our own server! It's a great beginner-friendly way to start learning about databases, and these "Backend as a Service" (BaaS) tools are a huge trend in the tech industry right now!

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

1. Set up for local development on your computer

  • Open the command line and navigate into your directory/folder for the pair-partners project.

    Remember to use the commands cd to change directories, pwd to check where you currently are, and ls to list what's inside the current directory!

  • Switch to the master branch (if you aren't already on it) with the git checkout master command.

  • Get the latest changes from GitHub with the git pull command.

  • Create a new local branch with git checkout -b BRANCH-NAME, replacing BRANCH-NAME with an all-lowercase name for this new feature followed by your initials (for example, firebase-test-lk).

Great! Now any commits you make will be part of this new branch that you just created and switched to.

Remember: every time you resume working on this challenge, you can switch to this branch with the git checkout BRANCH-NAME command. You can see a list of all your local branches and which one you're currently on by using the git branch command.

2. Create new files and folders for your Firebase test app

  • Inside the pair-partners project directory, create a new directory called firebase-test.

    Remember you can create new directories from the command line with the mkdir command, as in mkdir firebase-test.

  • Navigate into the new firebase-test directory and create two new files: index.html and firebasetest.js.

    Remember you can create new files from the command line with the touch command, as in touch index.html firebasetest.js to create both files at the same time!

  • Copy this HTML boilerplate code and paste it into your firebase-test/index.html file (in other words, into your new index.html file inside the firebase-test directory).

  • Change the <title> to something like "Testing Firebase!" or similar.

  • Inside the <body> element, create the following elements:

    • An <h1> heading element that contains the same text as the title, something like "Testing Firebase!" or similar.

    • A empty paragraph with the id of "message", as in <p id="message"></p>.

    • A <script> element to import the Firebase JavaScript library into your web page. The source URL of the Firebase JavaScript file (hosted on Google's servers for our convenience!) is "https://www.gstatic.com/firebasejs/4.1.2/firebase.js". So your code for this step should be:
      <script src="https://www.gstatic.com/firebasejs/4.1.2/firebase.js"></script>.

    • Another <script> element to import your firebasetest.js file, as in:
      <script src="firebasetest.js"></script>.

Awesome! Now that you have your files set up and the Firebase library imported into your web page, you're ready to set up your first Firebase app! If you haven't already, now is a good time to make a Git commit to save your progress!

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/dee22d9806d213aedfa151ed5898bb17

Please don't look at the solutions until after you've checked and double-checked your code for each part of this challenge. No cheating! haha :)

3. Set up your Firebase project

  • Open the Firebase console (which is just a web page that lets you manage your app) and log in using your Google account.

  • Click "Add New Project" and give your project a name like "Firebase Test":
    firebase-add-project

  • Click "Add Firebase to your web app":
    firebase-web-app

  • Copy and paste the JavaScript part of the initialization code into your firebasetest.js file, starting from // Initialize Firebase until before the closing </script> tag:
    firebase-code-snippet

  • In the Firebase console, navigate to the "Database" page and then to the "Rules" tab.
    Shortcut: Click on this link and then choose your project to get to the page quickly!

  • Double click the code where it says "auth !== null" and type to replace it with true so that the code says ".read": true, ".write": true for the rules. Note: Don't use quote marks around true!
    firebase-rules-publish

  • Click the "Publish" button right above the rules to save your changes. You should now see a warning that your security rules are defined as public and anyone can read or write to your database:
    firebase-rules-public-warning

That's exactly what we want right now; while we're testing this first version of our app, we want it to work without requiring users to sign in first. Later we'll change the rules again to add security as needed.

βœ”οΈ SOLUTION for Part 3: https://gist.github.com/LearningNerd/288df7eff9f78e9a44ab9215f8858355

Congrats, you now have a Firebase app! If you haven't already, be sure to make another Git commit to save your progress. Next, let's test out the app and make sure it works!

4. Add JavaScript code to display Firebase data on your web page

  • Create a JavaScript object named 'messageBox' for the HTML element that has an id of "message".

  • Create another JavaScript object called dbRef. This object will be our reference to the "greeting" row of our Firebase database. Use this chain of built-in Firebase methods:
    var dbRef = firebase.database().ref().child("greeting");

  • Last but not least, we'll use another built-in Firebase function to create an event listener that will display our data on the web page any time our database is updated:
    dbRef.on("value", function(dataSnapshot) { messageBox.textContent = dataSnapshot.val(); });

βœ”οΈ SOLUTION for Part 4: https://gist.github.com/LearningNerd/43b7edeaa40e3e61b6017c035c07670f

We'll learn more about all of these Firebase functions in the next challenges, but first let's test the app and make sure that our code is working!

5. Add sample data with the Firebase Console and test your app

  • In the Firebase Console, navigate to the "Database" page and then to the "Data" tab.
    Shortcut: Click on this link and then choose your project.

  • Hover your mouse over the text that looks similar to fir-test-c7763: null and then click on the green plus sign that appears:
    firebase-add-1

  • In the two text boxes that pop up, type "greeting" for the name and "Hi from Firebase!" for the value. Then click the blue "Add" button when you're ready to save your new data:
    firebase-add-2

  • Now let's test our new app! Open up your firebase-test/index.html file with your web browser and you should now see your message "Hi from Firebase!" appear on the page!

  • Next, navigate back to the "Data" tab of the "Database" page in the Firebase Console, click on your "Hi from Firebase!" message, type in the box to change the value to something else like "I changed this data in Firebase!", and then press the Enter key to save your changes:
    firebase-edit

  • If you switch back to your index.html page in your web browser again, you should see the data change!

πŸ† Congratulations, your first Firebase app is working! The coolest thing about Firebase is that it updates the data in real time so you don't even need to refresh the page to see the changes. Behind the scenes, it's using a WebSocket connection just like our SocketIO chatroom app did! Cool stuff, right?

βœ”οΈ If you haven't already, be sure to make another Git commit. And while you're at it, be sure to check off all the checkboxes in these instructions for every step that you've completed -- that way the rest of our team can easily see your progress!

6. Create a pull request to share your code with us

πŸ’‘ You can create a pull request at any point! Please share your code with us at the end of every work session, whether or not you've finished the challenge. Pull requests are a great way to ask for feedback on your code!

  • If you haven't already, make a commit! (Make sure you're on the branch for this challenge.)

    Remember: Start with git branch to see a list of your branches and which one you're currently on. Then use git checkout BRANCH-NAME to switch to the branch you created earlier for this challenge. Then do your usual workflow, using git status as needed, git add . to track all changes, and git commit -m "your commit description here" to save a snapshot of your project.

  • Upload your branch to GitHub with the git push origin BRANCH-NAME command.

  • Create a new pull request by clicking here, and make sure the base branch is set to "master" and the compare branch is set to the name of your new branch:

    github-pull-request-compare-branch

  • Review your files to make sure all your changes show up, and then click the green "Create pull request" button:

    github-pull-request-create

  • Make sure the title of your pull request includes the name of the challenge you're working on (for example, Solution for "Create your first Firebase app!" challenge). Then add any comments or questions in the description box and click "Create pull request" again to publish it:

    github-pull-request-publish

Once you've submitted your pull request, everyone on our team can share feedback on your code using GitHub's code review and commenting features. So keep an eye out for GitHub notifications in your email inbox!

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Create user stories and sketches to identify our first tasks!

Before we meet this Saturday, let's start identifying features for the app that we'll build together for our group project. :) What features should we include in our pair programming / study partner match-making app?

Before Saturday: click here to create a new GitHub issue and submit a new issue for EACH feature idea that you'd like to share!

For each feature idea, please include:

1. A user story to describe your feature idea

A "user story" is just a plain-English description of a feature for the project. A common format for user stories looks like this:

"As a [role], I want [goal/desire] so that [benefit]."

For example, if we were building an app for sharing recipes, one user story might be this:

"As a professional cake decorator, I want a photo gallery feature on my user profile so that I can easily show clients examples of my designer cupcakes."

2. A sketch of how this feature might work or how the user interface might look

You can draw a flow chart to illustrate how this feature might work, or draw a sketch of the user interface! (You could draw it on paper and take a photo with your phone, or use a program on your computer like Paint or Powerpoint, or try a web-based drawing tool like https://www.draw.io/)

Quick tip: You can upload images by dragging/dropping them right into the text box where you write your comment on this page! Pretty convenient, right?

Examples:
pexels-photo-196644
419px-lava_lamp_flowchart svg

Sign-up / Login implementation

  • using username
  • using email
  • using GitHub account
  • using Google+
  • using Facebook
  • using Twitter

Perhaps GitHub would be best as we plan to link GitHub repositories to user profiles and various features

For Melanie: Add Login with GitHub feature using Firebase Authentication

So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!

πŸ“š Prerequisites: First complete "Challenge: Practice displaying Firebase data"

βœ”οΈ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.

❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!

1. Set up for local development and testing with a local server

  • First make sure you're in the pair-partners project folder, and make sure you're on the master branch (use git checkout master if you need to switch).

  • Download the latest working version of our project code from GitHub with git pull -- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work!

  • If you haven't already, make a new local branch called something like gh-login-lk (with your initials at the end) for this new feature.

    Note: it's important that we create this new branch from the master branch, because we want this new branch to start out as a copy of the master branch, with the latest agreed-upon version of our project!

  • Install the http-server package from npm by running this code in your command line: npm install http-server -g (If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)

  • Make sure you're inside the pair-partners/firebase-test folder (if not, use cd to navigate there via command line), and then start your local server by running the http-server command. (Just literally type http-server into your command line, no other words needed!)

    http-server

  • View your app from the local server by going to http://localhost:8080 in your web browser. You should see everything working just like before!

  • Any time you want to turn off your local server, press Ctrl + C on your keyboard. Then run the http-server command again from inside the pair-partners/firebase-test folder each time you want to restart the server.

    Suggestion: If you want to use the command line while running the server, you can open two command line windows at the same time: one to keep the server running, and one to run commands as usual!

Why we need to use a local server

From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!

The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with file:// -- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!

GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like http://localhost:8080 -- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)

2. Create buttons and event listeners for login and logout

  • In your firebase-test/index.html file, add another paragraph that says "Not currently logged in." and give it an ID of "userinfo".

  • Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!

    Remember: all your IDs and variable names should be specific and descriptive (but also relatively short, if possible). There is an art to this! A good rule of thumb is: just by glancing at its name, can you immediately tell how this element is different from all the other elements of your app?

  • In your firebasetest.js file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)

  • Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either "User clicked LOGIN" or "User clicked LOGOUT"

βœ”οΈ SOLUTION for Part 2: https://gist.github.com/LearningNerd/26e3996aebf800225145c33e512c0d07

3. Register a new GitHub OAuth application

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript and Registering OAuth Apps on GitHub

OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!

When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password --
never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)

  • First, click here to register a new OAuth app on GitHub.

  • For "Application name", enter something like Pair Partners (Local Test Version)

  • For Homepage URL and "Authorization callback URL", enter http://localhost:8080

    Note: We're going to change the callback URL later to point to Firebase's server. The callback URL is where GitHub will redirect users after they've successfully logged in with GitHub and given permission for our app to access their GitHub account.

  • Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.

4. Set up GitHub authentication in the Firebase console

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript

  • In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab.
    Shortcut: Click on this link and then choose your project.

  • Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).

  • From the bottom of that page, copy the authorization callback URL (it should look something like https://fir-test-c7763.firebaseapp.com/__/auth/handler) and click the blue "Save" button to save your changes in Firebase.

  • Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the http://localhost:8080 link that was there before), and then click the green "Update application" button to save your changes in GitHub.

Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.

5. Add Firebase Authentication functions to your JavaScript

πŸ† The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."

πŸ“‘ Official documentation: Firebase Authentication Using GitHub with JavaScript (the section titled "Handle the sign-in flow with the Firebase SDK") and Manage Users in Firebase

  • In your firebasetest.js file, create an instance of Firebase's GitHub provider object: var provider = new firebase.auth.GithubAuthProvider();

    Note: It doesn't really matter where you put this in your JavaScript file, as long as you define the provider object before any code that uses it. To keep things organized, it might be best to define this object immediately after you initialize your Firebase app.

  • Change your login button's event listener so that the following code runs every time the user clicks the login button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signInWithPopup(provider).catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signInWithPopup method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)

If you like, you can switch out the signInWithPopup method with the signInWithRedirect method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)

  • Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:

    // Use Firebase with GitHub Auth to log in the user
    firebase.auth().signOut().catch(function(error) {
      // Log any errors to the console
      console.log(error);
    });

The Firebase signOut method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).

  • Add the Firebase onAuthStateChanged event listener method with the following code:

    // When user logs in or logs out:
    firebase.auth().onAuthStateChanged(function(user){
      // If user is now logged in:
      if (user) {
    
        console.log('User successfully logged in to Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display user's GitHub username and GitHub profile photo!
    
      // Otherwise, if no user currently logged in:
      } else {
    
        console.log('User successfully logged OUT from Firebase!');
    
        // HERE: Update the paragraph with ID of "userinfo" to display the message "Not currently logged in."
    
      }
    });

The Firebase onAuthStateChanged method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameter user), which contains a bunch of information about the user!

πŸ’‘ Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

6. Access Firebase user profile information

First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.

  • Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.

  • In your firebasetest.js file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the // HERE comment -- create one variable for the user's name and one variable for the user's profile photo URL.

    Hint: Remember that you can use dot notation to access properties of JavaScript objects. In this case, the user parameter is our object, and we want to access some properties inside of it!

7. Display the user's profile information on the web page

For the next step, we're going to use a new DOM element property called innerHTML! It's very similar to the textContent property, but the main difference is that innerHTML will render HTML elements in your string as actual HTML elements on the page!

  • First, try a quick test with the textContent property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:

    document.getElementById("userinfo").textContent = 'The <strong>username</strong> will go here and the profile photo will go here: <img src="#">';

You should see that message with the literal HTML tags show up as code on your web page! That's because the textContent property does not render HTML.

  • Next, run the same code as before, but replace textContent with innerHTML, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message!

  • Back in your firebasetest.js file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use its innerHTML property to display the user's name and their actual profile photo!

    Hint: Remember that you can combine variables with literal strings in JavaScript using the + operator, often called the string concatenation operator! For example: "Hello, " + yourNameHere + "! Nice to meet you!"

  • In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the textContent of the "userinfo" paragraph to contain the message "Not currently logged in" so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.

    Note: We can just use textContent this time, because our simple message doesn't contain any HTML tags. It's best to use textContent for simple things like this, because it actually runs much faster in the browser compared to innerHTML!

βœ”οΈ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!

8. Test the app with your local server

Now we're finally ready to see if the app works! Let's try logging in with GitHub!

  • Remember to first start up your local server with the firebase-test folder as the root! (So in command line, first cd into that folder if you aren't already there.) Then run http-server and navigate to http://localhost:8080 in your web browser.

  • Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!

    Debugging tip: If your web app isn't updating as expected after making changes to your code, try these instructions to do a "hard refresh" and clear your web browser's cache!

πŸ† Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!

9. Create a pull request to share your code with us

You know the drill! If you need to review the detailed instructions, see the bottom of the previous challenge ("Practice displaying Firebase data"). Here's a less detailed, quick recap:

  • Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.

  • Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.

  • After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.

Congrats, you've completed this challenge!

βœ”οΈ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!

πŸ‘‰ More challenges to come, so stay tuned!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.