Firebase
Firebase BaaS with Firestore, Authentication, Cloud Functions, and Hosting
You are an expert in Firebase for rapid backend development, including Firestore, Authentication, Cloud Functions, Cloud Storage, and Firebase Hosting. ## Key Points - Use the Firestore emulator during development to avoid incurring costs and to test security rules locally. - Model data for the queries you need — denormalize aggressively in Firestore, since joins are not supported. - Use `serverTimestamp()` instead of `new Date()` to avoid clock-skew issues across clients. - Deploy security rules alongside code using `firebase deploy --only firestore:rules`. - Use batched writes or transactions when updating multiple documents atomically. - Prefer Cloud Functions v2 (2nd gen) for better scaling, concurrency control, and longer timeouts. - **No security rules**: By default, new Firestore databases start in test mode with open access — always deploy rules before going to production. - **Reading entire collections**: Firestore charges per document read; always use queries with filters and limits. - **Nested subcollections vs. root collections**: Subcollections cannot be queried across parents without collection group queries (`collectionGroup`). - **Cold starts in Cloud Functions**: First invocations take seconds; use `minInstances` in v2 functions for latency-sensitive endpoints. - **Not unsubscribing listeners**: Forgetting to call the `unsubscribe` function from `onSnapshot` causes memory leaks and unexpected reads. ## Quick Example ```bash # Deploy functions firebase deploy --only functions ```
skilldb get baas-skills/firebaseFull skill: 260 linesFirebase — Backend as a Service
You are an expert in Firebase for rapid backend development, including Firestore, Authentication, Cloud Functions, Cloud Storage, and Firebase Hosting.
Core Philosophy
Overview
Firebase is Google's app development platform providing a suite of cloud services: Firestore (NoSQL document database), Firebase Authentication, Cloud Functions (serverless Node.js/Python), Cloud Storage for Firebase, Firebase Hosting (static + SSR), Remote Config, and Cloud Messaging. It integrates tightly with the Google Cloud Platform ecosystem.
Setup & Configuration
Project Initialization
# Install Firebase CLI
npm install -g firebase-tools
# Login
firebase login
# Initialize project (select Firestore, Functions, Hosting, etc.)
firebase init
# Start local emulators
firebase emulators:start
Client SDK Setup
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';
import { getStorage } from 'firebase/storage';
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const auth = getAuth(app);
const storage = getStorage(app);
Admin SDK (Server-side)
import { initializeApp, cert } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';
initializeApp({
credential: cert(JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT!)),
});
const adminDb = getFirestore();
Core Patterns
Authentication
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signInWithPopup,
GoogleAuthProvider,
onAuthStateChanged,
signOut,
} from 'firebase/auth';
// Sign up
const { user } = await createUserWithEmailAndPassword(auth, email, password);
// Sign in
const { user } = await signInWithEmailAndPassword(auth, email, password);
// Google OAuth
const provider = new GoogleAuthProvider();
const { user } = await signInWithPopup(auth, provider);
// Listen for auth state changes
onAuthStateChanged(auth, (user) => {
if (user) {
console.log('Signed in:', user.uid);
} else {
console.log('Signed out');
}
});
// Sign out
await signOut(auth);
Firestore Database
import {
collection, doc, addDoc, setDoc, getDoc, getDocs,
updateDoc, deleteDoc, query, where, orderBy, limit,
onSnapshot, serverTimestamp,
} from 'firebase/firestore';
// Add a document (auto-generated ID)
const docRef = await addDoc(collection(db, 'posts'), {
title: 'My Post',
body: 'Content here',
authorId: auth.currentUser.uid,
createdAt: serverTimestamp(),
});
// Set a document (explicit ID)
await setDoc(doc(db, 'users', userId), {
name: 'Alice',
email: 'alice@example.com',
}, { merge: true });
// Get a single document
const snap = await getDoc(doc(db, 'posts', postId));
if (snap.exists()) {
console.log(snap.data());
}
// Query documents
const q = query(
collection(db, 'posts'),
where('authorId', '==', userId),
orderBy('createdAt', 'desc'),
limit(10)
);
const snapshot = await getDocs(q);
snapshot.forEach((doc) => console.log(doc.id, doc.data()));
// Real-time listener
const unsubscribe = onSnapshot(q, (snapshot) => {
snapshot.docChanges().forEach((change) => {
if (change.type === 'added') console.log('New:', change.doc.data());
if (change.type === 'modified') console.log('Modified:', change.doc.data());
if (change.type === 'removed') console.log('Removed:', change.doc.data());
});
});
// Update
await updateDoc(doc(db, 'posts', postId), { title: 'Updated Title' });
// Delete
await deleteDoc(doc(db, 'posts', postId));
Firestore Security Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users can read/write their own profile
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
// Posts: anyone can read published, only author can write
match /posts/{postId} {
allow read: if resource.data.published == true;
allow create: if request.auth != null
&& request.resource.data.authorId == request.auth.uid;
allow update, delete: if request.auth != null
&& resource.data.authorId == request.auth.uid;
}
}
}
Cloud Storage
import { ref, uploadBytes, getDownloadURL, deleteObject } from 'firebase/storage';
// Upload
const storageRef = ref(storage, `avatars/${userId}/profile.jpg`);
const snapshot = await uploadBytes(storageRef, file);
const downloadURL = await getDownloadURL(snapshot.ref);
// Delete
await deleteObject(ref(storage, `avatars/${userId}/profile.jpg`));
Cloud Functions
// functions/src/index.ts
import { onRequest } from 'firebase-functions/v2/https';
import { onDocumentCreated } from 'firebase-functions/v2/firestore';
import { getFirestore } from 'firebase-admin/firestore';
import { initializeApp } from 'firebase-admin/app';
initializeApp();
const db = getFirestore();
// HTTP function
export const hello = onRequest(async (req, res) => {
res.json({ message: 'Hello from Firebase!' });
});
// Firestore trigger — runs when a new post is created
export const onPostCreated = onDocumentCreated('posts/{postId}', async (event) => {
const snap = event.data;
if (!snap) return;
const post = snap.data();
// Example: update author's post count
await db.doc(`users/${post.authorId}`).update({
postCount: FieldValue.increment(1),
});
});
# Deploy functions
firebase deploy --only functions
Best Practices
- Use the Firestore emulator during development to avoid incurring costs and to test security rules locally.
- Model data for the queries you need — denormalize aggressively in Firestore, since joins are not supported.
- Use
serverTimestamp()instead ofnew Date()to avoid clock-skew issues across clients. - Deploy security rules alongside code using
firebase deploy --only firestore:rules. - Use batched writes or transactions when updating multiple documents atomically.
- Prefer Cloud Functions v2 (2nd gen) for better scaling, concurrency control, and longer timeouts.
Common Pitfalls
- No security rules: By default, new Firestore databases start in test mode with open access — always deploy rules before going to production.
- Reading entire collections: Firestore charges per document read; always use queries with filters and limits.
- Nested subcollections vs. root collections: Subcollections cannot be queried across parents without collection group queries (
collectionGroup). - Cold starts in Cloud Functions: First invocations take seconds; use
minInstancesin v2 functions for latency-sensitive endpoints. - Not unsubscribing listeners: Forgetting to call the
unsubscribefunction fromonSnapshotcauses memory leaks and unexpected reads.
Anti-Patterns
Over-engineering for hypothetical requirements. Building for scenarios that may never materialize adds complexity without value. Solve the problem in front of you first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide wastes time and introduces risk.
Premature abstraction. Creating elaborate frameworks before having enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at system boundaries. Internal code can trust its inputs, but boundaries with external systems require defensive validation.
Skipping documentation. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add baas-skills
Related Skills
Hasura
Hasura is an open-source engine that connects to your databases (PostgreSQL, MS SQL, etc.) and instantly gives you a production-ready GraphQL API. It simplifies data access, real-time subscriptions, and authorization management, making it ideal for rapidly developing data-driven applications.
Nhost
Nhost BaaS with Hasura GraphQL, PostgreSQL, authentication, and storage
Parse Server
Parse Server is an open-source backend framework that provides a scalable and flexible way to build web and mobile applications with a self-hostable backend-as-a-service (BaaS). It offers database management, REST APIs, GraphQL, push notifications, and user authentication.
Pocketbase
PocketBase single-binary BaaS with SQLite, auth, real-time, and file storage
Strapi Baas
Strapi is an open-source, headless CMS that allows you to build custom APIs and manage content. Use it when you need full control over your backend, a flexible content structure, and a powerful admin panel.
Supabase
Supabase BaaS with Postgres, Auth, Realtime, Storage, and Edge Functions