DEV Community

Cover image for Firebase Bootcamp: Hex-Clicker
Madhav Jha
Madhav Jha

Posted on

Firebase Bootcamp: Hex-Clicker

What is Firebase ?

Firebase is a Google-backed application development software that enables developers to develop iOS, Android and Web apps.

Firebase provides tools and serviced such as:

  • Analytics
  • Authentication
  • Cloud functions
  • Realtime database
  • Crashlytics
  • Performance monitoring, and much more...!

and all this serverless.

Why use Firebase ?

  • It is less technical and time-saving alternative to writing full-fledged backend code for dynamic apps.
  • You might also want to consider leveraging this tool if you eventually wish to host and manage your app in the cloud.
  • Being serverless, Firebase removes the need to worry about the technicalities of cloud server configuration.
  • It gives easy access to connect and use built-in third-party authentication providers, including Google, Facebook, Twitter, among others.
  • Low cost as firebase pricing is flexible and has pay-as-you-go services as well.
  • Firebase is a good choice if you want to deploy a working product on the cloud rapidly.

Hands on demo:

Let's make an easy and simple clicker game using HTML, CSS & JavaScript and see how we can use Firebase can make it more amazing.

Flow of the demo:

  1. Initiate a Firebase project.
  2. Create a basic clicker game and host it on Firebase.
  3. Add google login to the web-app.
  4. Use Firestore to store user details and total clicks.
  5. Set-up Firestore database rules.
  6. Create a leaderboard for the game.

Pre-requisites:

  1. Install VSCODE (or any other code editor of your choice) on your machine.
  2. Download NodeJS thus have NPM.

So let's get started πŸ₯³

1. Initiate a Firebase project:

You can start a project direct from Firebase site or directly from your terminal.
1.1 Click on Create a project to start a new project.
Create project via firebase site

1.2 To initialize your project from your VSCODE Terminal:

1.2.1 Install Firebase SDK and Firebase Tools

npm install firebase

npm install -g firebase-tools

Installed Firebase SDK and tools

1.2.2 Login

firebase login

Firebase Login

1.2.3 Initialize a project

firebase init

Initiated firebase project

You will see on the left side file explorer that some files have been made.

File explorer

Apart from the public/index.html all other files/folders are of no use to us. They are for configurations and we can ignore them

Run firebase emulators:start to see the project running on your localhost.

Local host
Local host Page

You will see that the index.html given to us as boilerplate include many unnecessary things, so let's edit those out and create a simpler version for our selves.

index.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Hex Clicker</title>

  <!-- update the version number as needed -->
  <script defer src="/__/firebase/9.12.1/firebase-app-compat.js"></script>
  <!-- include only the Firebase features as you need -->
  <script defer src="/__/firebase/9.12.1/firebase-auth-compat.js"></script>
  <script defer src="/__/firebase/9.12.1/firebase-firestore-compat.js"></script>
  <!-- 
      initialize the SDK after all desired features are loaded, set useEmulator to false
      to avoid connecting the SDK to running emulators.
    -->
  <script defer src="/__/firebase/init.js?useEmulator=true"></script>

  <!-- script and style file made by us -->
  <script src="./script.js"></script>
  <link rel="stylesheet" href="./style.css">

</head>

<body>
  <p>Hi there</p>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

To simplify the code more, let's make separate CSS and JavaScriptfile.

File explorer view

script.js

window.onload = () => {
    console.log("Firebase loaded")
}
Enter fullscreen mode Exit fullscreen mode

You can refresh the localhost and see the changes made, open dev tools press CTRL + SHIFT + I to open it. You can see that fire base has been loaded.

page ss

2. Create a basic clicker game and host it on Firebase.

Let's create a button and attach a JS function to increase the count on click.

index.html

...
<body>
  <button id="count-btn">
    <span id="count-value">0</span>
  </button>
  <p>Click to increase count !</p>
</body>
...
Enter fullscreen mode Exit fullscreen mode

style.css

#count-btn{
    font-size: large;
    padding: 10px 40px;
    cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

script.js

let countScore = 0
window.onload = () => {
    console.log("Firebase loaded")

    document.getElementById("count-btn").onclick = () => {
        increaseCount()
    }
}

const increaseCount = () => {
    countScore++
    document.getElementById("count-value").innerText = countScore
}
Enter fullscreen mode Exit fullscreen mode

Our basic clicker game is ready!!! πŸŽ‰
Let's host it so that you can send it to your friends so that they can play as well

Run firebase deploy

Firebase deploy

Site online

πŸ₯³πŸ₯³πŸ₯³and.... it is online !

3. Add google login to the web-app.

Before we move forward and add login, let's enable Authentication and add permissions so that we can test features on our local host.

Move to your project on firebase console.
Goto Authentication > Sign-in method
Choose Google
sign in method

Goto Settings > Authorized domains
Add 127.0.0.1
Authorized domains

Now we are ready to add sign-in button and functions in our app.

index.html

...
<body>
  <p id="user-details">your details...</p>
  <button id="sign-in">sign in</button>
  <button id="sign-out">sign out</button>
  <br><br>

  <button id="count-btn">
    <span id="count-value">0</span>
  </button>
  <p>Click to increase count !</p>
</body>
...
Enter fullscreen mode Exit fullscreen mode

script.js

let userDetails = undefined
let countScore = 0
window.onload = () => {
    console.log("Firebase loaded")
    document.getElementById("count-btn").onclick = () => {
        increaseCount()
    }
    document.getElementById("sign-in").onclick = () => {
        googleSignIn()
    }
    document.getElementById("sign-out").onclick = () => {
        signOut()
    }
    firebase.auth().onAuthStateChanged((user) => {
        if (!user) {
            userDetails = undefined
            console.log("user not signed in")
            return
        }
        userDetails = {
            "name": user["multiFactor"]["user"]["displayName"],
            "email": user["multiFactor"]["user"]["email"],
        }
        console.log(userDetails)
        document.getElementById("user-details").innerText = `Hi ${userDetails["name"]} πŸ‘‹`
    })
}

const increaseCount = () => {
    countScore++
    document.getElementById("count-value").innerText = countScore
}

const googleSignIn = () => {
    let provider = new firebase.auth.GoogleAuthProvider();
    firebase.auth()
        .signInWithPopup(provider)
        .then((result) => {
            console.log("sign in successful")
        }).catch((error) = () => {
            console.log(error);
            console.log("sign in successful")
        })
}

const signOut = () => {
    firebase.auth().signOut().then(() => {
        console.log('Sign-out successful')
    }, (error) => {
        console.log('Sign-out failed')
        console.log(error)
    })
    userDetails = undefined
}
Enter fullscreen mode Exit fullscreen mode

After login

You can see all the user logins:
All users

4. Use Firestore to store user details and total clicks.

Now that we have Google login added, let's store user details and total-clicks in firestore database.

Move to Cloud firestore > Create database
create in test mode > choose default location
create database

Start game collection and add the following dummy data:
dummy data

Now that we have a database set up, let's do the following:

  • Add user data on sign-up
  • increase clicks count on each click
  • showcase total clicks

Get user data function:

const getYourData = async () => {
    let docPath = `/game/${userDetails["email"]}`
    let dbData = await firebase.firestore().doc(docPath).get()
    return dbData.data()
}
Enter fullscreen mode Exit fullscreen mode

Create new user data function:

const createNewDoc = () => {
    firebase.firestore().collection("game").doc(userDetails["email"]).set({
        "name": userDetails["name"],
        "clicks": 0,
        "email": userDetails["email"]
    }).then(() => {
        console.log("new data added")
    });
}
Enter fullscreen mode Exit fullscreen mode

Update user data function:

const updateData = () => {
    firebase.firestore().collection("game").doc(userDetails["email"]).update({
        "clicks": firebase.firestore.FieldValue.increment(1)
    }).then(() => {
        console.log("data updated!")
    })
}
Enter fullscreen mode Exit fullscreen mode

Increment function

const increaseCount = () => {
    countScore++
    document.getElementById("count-value").innerText = countScore

    if (userDetails == undefined) return
    updateData()

    totalClicks++
    document.getElementById("clicks").innerText = `Total clicks: ${totalClicks}`
}
Enter fullscreen mode Exit fullscreen mode

When user sign-up (sign-in for the first time), we will check in the database if doc for the user already exists if it doesn't we will create new data.
And if users clicks on the button update the value.

...
firebase.auth().onAuthStateChanged(async (user) => {
        if (!user) {
            userDetails = undefined
            console.log("user not signed in")
            return
        }
        userDetails = {
            "name": user["multiFactor"]["user"]["displayName"],
            "email": user["multiFactor"]["user"]["email"]
        }
        console.log(userDetails)
        document.getElementById("user-details").innerText = `Hi ${userDetails["name"]} πŸ‘‹`

        // retrieve user data if it is undefined then create new doc
        let dbData = await getYourData()
        if (dbData == undefined) {
            createNewDoc()
        }
        dbData = await getYourData()
        totalClicks = dbData["clicks"]
        document.getElementById("clicks").innerText = `Total clicks: ${totalClicks}`
    })
...
Enter fullscreen mode Exit fullscreen mode

Total clicks

DB ss

5. Set-up Firestore database rules.

Currently our database is open, that means anyone can edit anyone's data, this is where we can use firestore rules.
We will add rules so that everyone can read the database but only only signed in users can update database docs and even then they can only update their own docs.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /game/{document} {
      allow read,create: if true;
      allow update: if request.auth != null && document == request.auth.token.email;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

DB rules

Our demo project is almost done..!

6. Create a leaderboard for the game.

Let's create leaderboard so that others can also see their friends progress.

Get data of every user:

const getAllData = async () => {
    let docPath = "/game"
    snapshot = await firebase.firestore().collection(docPath).get()
    return snapshot.docs.map(doc => doc.data())
}
Enter fullscreen mode Exit fullscreen mode

index.html

...
<button id="get-board">Get leaderboard</button>
  <div class="leaderboard">
    <div class="block">
      <div class="name">Username</div>
      <div class="score">Total clicks</div>
    </div>
    <div id="leaderboard-data">

    </div>
  </div>
...
Enter fullscreen mode Exit fullscreen mode

style.css

#count-btn{
    font-size: large;
    padding: 10px 40px;
    cursor: pointer;
}

.leaderboard{
    display: flex;
    flex-direction: column;
}

.block{
    display: flex;
    flex-direction: row;
}
.block div{
    padding: 4px 10px;
}
Enter fullscreen mode Exit fullscreen mode

script.js

...
document.getElementById("get-board").onclick = async () => {
        let allData = await getAllData()

        let divData = ""
        for (let i = 0; i < allData.length; ++i) {
            divData += `<div class="block">
            <div class="name">${allData[i]["name"]}</div>
            <div class="score">${allData[i]["clicks"]}</div>
          </div>`
        }
        document.getElementById("leaderboard-data").innerHTML = divData
    }
...
Enter fullscreen mode Exit fullscreen mode

Leaderboard

And with this we are done πŸ₯³πŸ₯³πŸ₯³
Now you can style it more as you wish make it more interesting add more feature... endless possibilities.

Conclusion

I hope this article gave you an insight on Firebase on when, where and why you should use it. The demo project is made in a way that it keeps the bare minimum code and style so that it is easier for you to refer if you get stuck.

Hosting, Authetication and Database are the bare bones that are needed for any web-app project. So make more intersting web-apps with firebase and if you do make them post abou it on Linkedin and do tag me as well.

Happy learning ...πŸŽ‰

Project links

My socials

Top comments (0)