Skip to main content
Svelte Fundamentals
CHAPTER 21 Beginner

Svelte with Firebase

Updated: May 18, 2026
5 min read

# CHAPTER 21

Svelte with Firebase

1. Chapter Introduction

Firebase is Google's Backend-as-a-Service (BaaS) that provides authentication, real-time Firestore database, and hosting — all without a backend server. Paired with Svelte's reactive stores, Firebase Firestore's real-time listeners become incredibly powerful: data updates in Firestore instantly update your Svelte UI.

2. Learning Objectives

  • Initialize Firebase in a Svelte project.
  • Implement Firebase Auth (email/password, Google).
  • Perform Firestore CRUD with real-time listeners.
  • Create a Firebase-powered Todo App.
  • Deploy to Firebase Hosting.

3. Setup

bash
1
npm install firebase
javascript
1234567891011121314151617
// src/lib/firebase.js
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';

const firebaseConfig = {
  apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
  authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
  projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
  storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
  appId: import.meta.env.VITE_FIREBASE_APP_ID
};

export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);

4. Firebase Auth Store

javascript
1234567891011121314151617181920212223
// src/lib/stores/firebaseAuth.js
import { writable } from 'svelte/store';
import { auth } from '$lib/firebase.js';
import {
  signInWithEmailAndPassword, createUserWithEmailAndPassword,
  signOut, onAuthStateChanged, GoogleAuthProvider, signInWithPopup
} from 'firebase/auth';

export const user = writable(null);
export const authLoading = writable(true);

// Listen to auth state changes
onAuthStateChanged(auth, (firebaseUser) => {
  user.set(firebaseUser);
  authLoading.set(false);
});

export const authActions = {
  login: (email, password) => signInWithEmailAndPassword(auth, email, password),
  register: (email, password) => createUserWithEmailAndPassword(auth, email, password),
  loginWithGoogle: () => signInWithPopup(auth, new GoogleAuthProvider()),
  logout: () => signOut(auth)
};

5. Firestore CRUD with Real-Time Updates

javascript
12345678910111213141516171819202122232425262728
// src/lib/services/todoService.js
import { db } from '$lib/firebase.js';
import {
  collection, addDoc, getDocs, deleteDoc, updateDoc,
  doc, query, where, orderBy, onSnapshot, serverTimestamp
} from 'firebase/firestore';

const COLLECTION = 'todos';

export const todoService = {
  // Real-time listener — returns an unsubscribe function
  subscribe: (userId, callback) => {
    const q = query(
      collection(db, COLLECTION),
      where('userId', '==', userId),
      orderBy('createdAt', 'desc')
    );
    return onSnapshot(q, snapshot => {
      const todos = snapshot.docs.map(d => ({ id: d.id, ...d.data() }));
      callback(todos);
    });
  },
  add: (userId, text) => addDoc(collection(db, COLLECTION), {
    text, done: false, userId, createdAt: serverTimestamp()
  }),
  toggle: (id, done) => updateDoc(doc(db, COLLECTION, id), { done: !done }),
  delete: (id) => deleteDoc(doc(db, COLLECTION, id))
};

6. Mini Project: Firebase Todo App

svelte
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
<!-- TodoApp.svelte -->
<script>
  import { onDestroy } from &#039;svelte';
  import { user, authLoading, authActions } from &#039;$lib/stores/firebaseAuth.js';
  import { todoService } from &#039;$lib/services/todoService.js';

  let todos = [];
  let newTodo = &#039;';
  let unsubscribe;

  // Subscribe to real-time todos when user logs in
  $: if ($user) {
    if (unsubscribe) unsubscribe();
    unsubscribe = todoService.subscribe($user.uid, (data) => {
      todos = data;
    });
  }

  onDestroy(() => { if (unsubscribe) unsubscribe(); });

  async function addTodo() {
    if (newTodo.trim() && $user) {
      await todoService.add($user.uid, newTodo.trim());
      newTodo = &#039;';
    }
  }

  $: remaining = todos.filter(t => !t.done).length;
</script>

{#if $authLoading}
  <p>Loading...</p>
{:else if !$user}
  <div class="login-page">
    <h1>Firebase Todo</h1>
    <button on:click={authActions.loginWithGoogle}>
      Sign in with Google
    </button>
  </div>
{:else}
  <div class="app">
    <header>
      <h1>My Todos ({remaining} remaining)</h1>
      <button on:click={authActions.logout}>Logout</button>
    </header>

    <div class="input-row">
      <input bind:value={newTodo} on:keydown={e => e.key===&#039;Enter' && addTodo()} placeholder="Add todo..." />
      <button on:click={addTodo}>Add</button>
    </div>

    <ul>
      {#each todos as todo (todo.id)}
        <li class:done={todo.done}>
          <input type="checkbox" checked={todo.done}
            on:change={() => todoService.toggle(todo.id, todo.done)} />
          <span>{todo.text}</span>
          <button on:click={() => todoService.delete(todo.id)}>✕</button>
        </li>
      {:else}
        <li class="empty">No todos yet!</li>
      {/each}
    </ul>
  </div>
{/if}

7. Firebase Hosting Deployment

bash
12345
npm install -g firebase-tools
firebase login
firebase init hosting   # Select 'dist' as public folder
npm run build           # Builds to /dist
firebase deploy

8. Common Mistakes

  • Not unsubscribing from Firestore listeners: Always call the returned unsubscribe() function in onDestroy to prevent memory leaks.
  • Storing secrets in .env without VITE prefix: Vite only exposes env vars that start with VITE to the browser. Never expose server-only secrets.

9. MCQs

Question 1

What Firebase product provides a real-time NoSQL database?

Question 2

What function listens for real-time Firestore updates?

Question 3

What does onSnapshot return?

Question 4

What function adds a document to a Firestore collection?

Question 5

What does onAuthStateChanged do?

Question 6

What Firebase function signs in with Google popup?

Question 7

How do you delete a Firestore document?

Question 8

What env var prefix does Vite require to expose variables to the browser?

Question 9

Where do you store Firebase config in production?

Question 10

What command deploys a built Svelte app to Firebase Hosting?

10. Interview Questions

  • Q: How does Firestore's onSnapshot integrate with Svelte's reactive store system?
  • Q: What are the security implications of exposing the Firebase config in client-side code?

11. Summary

Firebase and Svelte are a natural pairing. Firebase's real-time onSnapshot listeners become Svelte stores that automatically trigger UI updates. Authentication state flows through reactive stores to every component. The result is a real-time, collaborative application with zero backend code.

12. Next Chapter Recommendation

In Chapter 22: Svelte with TailwindCSS, we integrate the most popular utility-first CSS framework with Svelte to build beautiful, responsive UIs without writing custom CSS.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·