Firebase can be defined as a Backend-as-a-Service (BaaS). Firebase offers developers a variety of tools and services that can help them create and develop quality apps. Developers can build iOS, Android, and Web apps using the Google-backed application development platform.
Tools are provided from Firebase for monitoring analytics, reporting and resolving app errors, as well as developing marketing and product experiments. The awesome thing about Firebase is that, you do not need to build or maintain backend services, Firebase does the job for you.
In this article, we are going to be building a chat application using Svelte and Firebase.
While You Are Here, Why Not Discover the Top 10 React Courses To Help You Become a Better Developer?
What Is Svelte?
Svelte is a tool for creating quick web applications. It is quite similar to JavaScript frameworks like React and Vue, making it simple to create attractive dynamic user interfaces.
Svelte, however, makes a significant distinction: rather than interpreting your application code at run time, it turns your program into ideal JavaScript at build time. This means that you avoid paying the performance cost of the framework’s abstractions and that your app won’t load slowly at first.
Why Use Svelte?
I know you have probably wondered at this point, “why use Svelte?”. Well, in this section, we are going to look at some of the major reasons why you should use Svelte for your next project.
- Svelte is a cutting-edge JavaScript framework designed to create lean, quick, and enjoyable to use static web apps. Any project, including larger applications created using Angular, React, Vue, or any other framework, can use Svelte to generate simple, reusable components. Or you may use it to create complete web applications.
- Compared to Angular or React, it stands out for its capacity to generate smaller code bundles that execute more quickly in the browser.
- Almost no boilerplate code is needed for Svelte. HTML, CSS, and JavaScript blocks are used to create svelte components. Markup is specified using common HTML tags, but scripts have a feel that is quite similar to “vanilla JavaScript.” Unlike React’s JSX, Svelte does not also add new JavaScript syntax.
Setting Up Our Project
To get started with our project, the first thing we need to do is create our starter app template by running the following code on the terminal:
npx degit sveltejs/template svelte-chatt
cd svelte-chatt
npm install
After everything is installed, the next thing we want to do is install rxfire for our project by running the following command:
# npm
npm i rxfire firebase rxjs --save
# yarn
yarn add rxfire firebase rxjs
rxfire’s Features
- Observable creators: Rxfire has observable bindings for most of the Firebase web libraries.
- It is portable: Rxfire can either be used with or without a framework.
- Combine multiple data sources: Let’s assume we wanted to combine two Firestore references, or we wanted to combine an image from Cloud storage with a Firestore document, Rxfire got you covered with observables and operators.
- You can simplify code-splitting of Firebase: when you use Rxfire with Webpack, it makes it easier to load features on-demand.
Now that we have looked at the features of Rxfire, the next step is to open up our newly created project on our code editor. If you are using VScode, the command for this is:
code .
Once you have opened up your newly scaffolded Svelte template, the directory should look like this:
Now, the next thing we need to do is head into our App.svelte file and edit it to be like this:
<script>
</script>
<style>
</style>
<main>
Hello World
</main>
For our project, we are going to need a cloudflare CDN which is a required library for our project. We are going to include it in our index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='text/css' href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/fontawesome.min.css"
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>
Now we need to go into our global.css file and edit it like this:
* {
margin: 0px;
padding: 0px;
box-sizing: border-box
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
background: #f0f1f2;
}
Once we run the program using the npm run dev command, we will see this on our browser:
Firebase Configuration
Now, we need to initialize our application and to do this, we need to create a project in Firebase.
When you click on “Get started” you will be taken to this next page where you will be asked to “Create a project”.
After this, you will be asked to enter your project name. You can name it whatever you like.
After this, you will be directed to the Google Analytics page, but for the purpose of this project, we are going to disable Google Analytics for our project. Click on “Create project”.
After this, you will automatically be directed to your project dashboard.
If you are following this article, and you have come to this far congratulations!!, you have successfully created your Firebase project.
Next, we need to set up Authentication for our project. For the purpose of our project, we are going to be using Google authentication.
Once you navigate to Authentication, click on “Get started”, and you will see the page in the image below:
Click on the Google symbol, which will lead you to the page below:
For the “Project support email”, put in your email, then click save.
Now, we are going to set up a “Firestore Database” for our project. The first thing we need to do is navigate to “Firestore Database”.
Click on “Create database”.
For our project, we are going to select “Start in test mode” which will allow anyone to write to the database.
Click on “Next”.
Wow! We have successfully created our Firebase database.
Now, let’s head back to the project overview. What we want to do now is connect Firebase to our Svelte chat app.
Click on the gear symbol, and you will be directed to the next page below:
You can put in whatever app nickname you want. Click on “Register app”.
This contains all the configurations we are going to need to initiate our app.
Svelte-Firebase Integration
To integrate Firebase into our Svelte application, we first created a firebase.js file, and added the following code:
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import "firebase/compat/firestore";
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: "AIzaSyAnqwBk2OJAmNlEFsR78ne8dEYp_qLi-_c",
authDomain: "chat-app-7abb1.firebaseapp.com",
projectId: "chat-app-7abb1",
storageBucket: "chat-app-7abb1.appspot.com",
messagingSenderId: "392240388268",
appId: "1:392240388268:web:f69a34ee669130dbb7e709",
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export const auth = firebase.auth();
export const googleProvider = new firebase.auth.GoogleAuthProvider();
export const db = firebase.firestore();
Here, we imported some components from Firebase, then we copied and pasted the configuration to initialize our application. compat allows you to upgrade to Firebase version 9 without changing all your Firebase code at once.
Google Authentication Implementation
We want to implement Google authentication from Firebase into our application. First, let’s go into our App.svelte and include the following code:
<script>
import {auth,googleProvider} from "./firebase";
import {authState} from "rxfire/auth";
let user;
const unsubscribe = authState(auth).subscribe(usr => user = usr);
function login(){
auth.signInWithPopup(googleProvider);
}
function logout(){
auth.signOut();
}
</script>
<style>
main {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
max-width: 400px;
max-height: 500px;
background: #fff;
border: 1px solid #eee;
box-shadow: 0px 5px 10px rgba(0,0,0,0.05);
}
</style>
<main>
{#if user}
Logged in as {user.uid}
{:else}
<button on:click={login}>
<i class="fa fa-google"></i>
Sign in with Google
</button>
{/if}
</main>
Here we first imported auth and googleProvider from firebase, then we also created a function that allows a user to sign in and sign out. Then we styled our page inside the style tag. We also have an #if block which is unique to Svelte.
When you run the code, this is what it looks like on the browser:
For our remaining code, let us edit our App.svelte file to be like this:
<script>
import {auth,googleProvider} from "./firebase";
import {authState} from "rxfire/auth";
Import Chatroom from “./Chatroom.svelte”;
let user;
const unsubscribe = authState(auth).subscribe(usr => user = usr);
function login(){
auth.signInWithPopup(googleProvider);
}
function logout(){
auth.signOut();
}
</script>
<style>
main {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
max-width: 400px;
max-height: 500px;
background: #fff;
border: 1px solid #eee;
box-shadow: 0px 5px 10px rgba(0,0,0,0.05);
}
.login-form{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.login-form button {
padding: 10px;
background: #fff;
color: #111;
font-size: 16px;
cursor: pointer;
outline: none;
border: 1px solid #bbb;
}
.login-form button i.fa{
padding-right: 10px;
border-right: 1px solid #ddd;
color: #555;
}
</style>
<main>
{#if user}
Logged in as {user.uid}
{:else}
<div class="login-form">
<button on:click={login}>
<i class="fa fa-google"></i>
Sign in with Google
</button>
</div>
{/if}
</main>
We wrapped our button in a div tag, then we created a class of login-form which we used to style our Login page.
Once you click on Sign in with Google, you should see something like this:
Click on your email account, and you will automatically be directed to this page:
Firestore Integration for Chat
Here, we are going to integrate Firestore for our chat. The first thing we did was create a Chatroom.svelte file under the src folder, then we included the following code:
<script>
import {db} from "./firebase";
import {collectionData} from "rxfire/firestore";
import {startWith} from "rxjs/operators";
export let user;
export let logout;
let message = "";
const query = db.collection("chats").orderBy("sentAt");
const chats = collectionData(query, "id").pipe(startWith([]));
function sendMessage(){
db.collection("chats").add({
uid:user.uid,
message:message,
avatar:user.photoUrl,
sentAt:+new Date()
});
message = "";
}
</script>
<style>
</style>
<main>
<div class="header">
<div class="logo">Chatroom</div>
<button on:click={logout}>Logout</button>
</div>
<div class="messages">
{#each $chats as chat}
{#if user.uid == chats.uid}
<div class="message my-message">
<div class="text">
{chat.message}
</div>
</div>
{:else}
<div class="message my-message">
<div class="avatar">
<img src={chat.avatar}>
</div>
<div class="text">
{chat.message}
</div>
</div>
{/if}
{/each}
</div>
<div class="form">
<input type="text" bind:value={message}>
<button on:click={sendMessage}>
<i class="fa fa-paper-plane"></i>
</button>
</div>
</main>
The code above allows users to now input chats or text, which will be stored on the Firestore Database. Now, for our Chatroom styling, we are going to include the following code in our style tag:
<style>
main {
height: 100%;
}
.header {
width: 100%;
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 10px;
border-bottom: 1px solid #ddd;
}
.header .logo {
font-size: 15px;
font-weight: 600;
color: #111;
}
.header button {
background: transparent;
padding: 5px 10px;
border: 1px solid #ddd;
color: #555;
font-size: 15px;
cursor: pointer;
}
.form {
display: flex;
width: 100%;
height: 40px;
border-top: 1px solid #ddd;
}
.form input {
flex: 1;
border: none;
outline: none;
font-size: 16px;
color: #111;
padding: 10px;
}
.form button {
padding: 10px;
font-size: 20px;
color: #555;
background: transparent;
border: none;
outline: none;
cursor: pointer;
}
.messages {
width: 100%;
height: calc(100% - 90px);
padding: 10px;
overflow-y: auto;
}
.messages::-webkit-scrollbar {
width: 4px;
background: #fff;
}
.messages::-webkit-scrollbar-thumb {
width: 4px;
background: #888;
}
.messages .message {
margin: 10px 0px;
display: flex;
}
.messages .my-message {
justify-content: flex-end;
}
.messages .message .avatar {
width: 30px;
height: 30px;
margin-right: 8px;
}
.messages .message .text {
padding: 10px;
background: #f0f4f7;
color: #555;
font-size: 13px;
font-weight: 600;
max-width: fit-content;
flex: 1;
border-radius: 5px;
}
.messages .message .avatar img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.messages .my-message .text {
background: #555;
color: #fff;
}
</style>
This is what our final project looks like:
When we navigate to our Firestore Database where our chats are stored, this is what it looks like:
We are done!!
Conclusion
In this article, we looked at how we can build a chat app with Svelte, and integrate it with Firebase. We also looked at how we can store our data in the Firestore database, without necessarily building a back-end.
Link to GitHub.