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:
- Initiate a Firebase project.
- Create a basic clicker game and host it on Firebase.
- Add google login to the web-app.
- Use Firestore to store user details and total clicks.
- Set-up Firestore database rules.
- Create a leaderboard for the game.
Pre-requisites:
- Install VSCODE (or any other code editor of your choice) on your machine.
- 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.
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
1.2.2 Login
firebase login
1.2.3 Initialize a project
firebase init
You will see on the left side file explorer that some files have been made.
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.
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>
To simplify the code more, let's make separate CSS and JavaScriptfile.
script.js
window.onload = () => {
console.log("Firebase loaded")
}
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.
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>
...
style.css
#count-btn{
font-size: large;
padding: 10px 40px;
cursor: pointer;
}
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
}
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
π₯³π₯³π₯³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
Goto Settings > Authorized domains
Add 127.0.0.1
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>
...
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
}
You can see all the user logins:
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
Start game collection and add the following 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()
}
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")
});
}
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!")
})
}
Increment function
const increaseCount = () => {
countScore++
document.getElementById("count-value").innerText = countScore
if (userDetails == undefined) return
updateData()
totalClicks++
document.getElementById("clicks").innerText = `Total clicks: ${totalClicks}`
}
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}`
})
...
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;
}
}
}
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())
}
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>
...
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;
}
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
}
...
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
- Demo site link: https://hexclicker.web.app
- Final site link: https://hex-clicker-28.web.app
- Github repo: https://github.com/jhamadhav/hex-clicker
My socials
- Linkedin: @jhamadhav
- Twitter: @jhamadhav28
- Github: @jhamadhav
- Website: jhamadhav.com
Top comments (0)