Choorai
Lv.2 BaaS

Getting Started with Firebase

With Backend-as-a-Service, you can use a NoSQL database and authentication without a separate backend server.

What is Firebase?

  • Firestore - NoSQL realtime database
  • Auth - Built-in email/social login
  • Cloud Storage - File storage and management
  • Hosting - Static site deployment
  • Cloud Functions - Serverless function execution
  • Free tier - Spark plan with unlimited projects

1Create a Firebase Project

  1. Log in with your Google account at console.firebase.google.com
  2. Click Add project
  3. Enter a project name
  4. Configure Google Analytics (optional)
  5. Click Create project
  6. After creation, click Add web app (</> icon) to get SDK configuration

Info

After project creation, go to Project Settings in the dashboard to find your API keys and configuration.

2Firestore Database Setup

Select Firestore Database in the dashboard and create a database.

  1. Click Create database
  2. Choose production mode or test mode
  3. Select a region: asia-northeast3 (Seoul) recommended

Security Rules Setup

Go to FirestoreRules tab and apply the security rules below.

Firestore Rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /todos/{todoId} {
      allow read, write: if request.auth != null
        && request.auth.uid == resource.data.userId;
      allow create: if request.auth != null
        && request.auth.uid == request.resource.data.userId;
    }
  }
}

Why security rules matter

Without security rules, all users can access all data. Use request.auth.uid to restrict access so only logged-in users can access their own data.

3Client Setup (React)

Install Dependencies

Terminal
npm install firebase

Environment Variables

.env.local
# .env.local
VITE_FIREBASE_API_KEY=your-api-key
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
VITE_FIREBASE_APP_ID=your-app-id

Find these in Firebase Console → Project SettingsGeneralYour apps.

Firebase Client

src/lib/firebase.ts
// src/lib/firebase.ts
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';

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,
};

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

4CRUD Example (React + Firestore)

A Todo app example using Firestore's realtime subscription (onSnapshot).

src/hooks/useTodos.ts
// src/hooks/useTodos.ts
import { useState, useEffect } from 'react';
import {
  collection,
  addDoc,
  getDocs,
  updateDoc,
  deleteDoc,
  doc,
  query,
  where,
  orderBy,
  onSnapshot,
  serverTimestamp,
} from 'firebase/firestore';
import { db, auth } from '../lib/firebase';

interface Todo {
  id: string;
  title: string;
  completed: boolean;
  userId: string;
  createdAt: any;
}

export function useTodos() {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const user = auth.currentUser;
    if (!user) return;

    const q = query(
      collection(db, 'todos'),
      where('userId', '==', user.uid),
      orderBy('createdAt', 'desc')
    );

    // Realtime subscription
    const unsubscribe = onSnapshot(q, (snapshot) => {
      const items = snapshot.docs.map((doc) => ({
        id: doc.id,
        ...doc.data(),
      })) as Todo[];
      setTodos(items);
      setLoading(false);
    });

    return () => unsubscribe();
  }, []);

  // Create
  const addTodo = async (title: string) => {
    const user = auth.currentUser;
    if (!user) throw new Error('Not authenticated');

    await addDoc(collection(db, 'todos'), {
      title,
      completed: false,
      userId: user.uid,
      createdAt: serverTimestamp(),
    });
  };

  // Update
  const toggleTodo = async (id: string, completed: boolean) => {
    await updateDoc(doc(db, 'todos', id), { completed });
  };

  // Delete
  const removeTodo = async (id: string) => {
    await deleteDoc(doc(db, 'todos', id));
  };

  return { todos, loading, addTodo, toggleTodo, removeTodo };
}

5Authentication Example (Optional)

With Firebase Auth, you can easily implement email/password login.

src/hooks/useAuth.ts
// src/hooks/useAuth.ts
import { useState, useEffect } from 'react';
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut as firebaseSignOut,
  onAuthStateChanged,
  User,
} from 'firebase/auth';
import { auth } from '../lib/firebase';

export function useAuth() {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setUser(user);
      setLoading(false);
    });

    return () => unsubscribe();
  }, []);

  // Sign up
  const signUp = async (email: string, password: string) => {
    const { user } = await createUserWithEmailAndPassword(
      auth, email, password
    );
    return user;
  };

  // Sign in
  const signIn = async (email: string, password: string) => {
    const { user } = await signInWithEmailAndPassword(
      auth, email, password
    );
    return user;
  };

  // Sign out
  const signOut = async () => {
    await firebaseSignOut(auth);
  };

  return { user, loading, signUp, signIn, signOut };
}

Social login

Social login with Google, GitHub, Facebook, and more is also supported. Configure it in Firebase Console → AuthenticationSign-in method.

When should you use Firebase?

Recommended

  • - Building a prototype quickly
  • - When realtime data sync is needed
  • - Supporting mobile and web simultaneously
  • - When Google ecosystem integration is needed

Consider carefully

  • - Complex relational queries are needed
  • - SQL-based data analysis is important
  • - Vendor lock-in is a concern
  • - Frequent bulk data exports are needed

Next steps

Last updated: February 22, 2026 · Version: v0.0.1

Send Feedback

Opens a new issue page with your message.

Open GitHub Issue