⏳
Loading cheatsheet...
Firestore, Authentication, Cloud Functions, Hosting, Storage, Realtime Database, and Firebase Admin.
// ── Firebase Auth Setup ──
import { initializeApp } from "firebase/app";
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword,
signInWithPopup, GoogleAuthProvider, signOut, onAuthStateChanged,
sendPasswordResetEmail, updateProfile } from "firebase/auth";
const app = initializeApp({
apiKey: "AIza...",
authDomain: "myapp.firebaseapp.com",
projectId: "myapp",
storageBucket: "myapp.appspot.com",
messagingSenderId: "123456",
appId: "1:123:web:abc123",
});
const auth = getAuth(app);
const googleProvider = new GoogleAuthProvider();
// ── Email/Password Auth ──
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
await updateProfile(user, { displayName: "Alice" });
const loginCredential = await signInWithEmailAndPassword(auth, email, password);
// ── Google OAuth Popup ──
const result = await signInWithPopup(auth, googleProvider);
const user = result.user;
// ── Password Reset ──
await sendPasswordResetEmail(auth, "user@example.com");
// ── Sign Out ──
await signOut(auth);
// ── Auth State Listener ──
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("Logged in:", user.uid, user.displayName, user.email);
} else {
console.log("Signed out");
}
});
// ── Get Current User ──
const currentUser = auth.currentUser;
if (currentUser) {
const { uid, email, displayName, photoURL, emailVerified } = currentUser;
}
// ── ID Token (for backend verification) ──
const idToken = await currentUser.getIdToken();
// Send to backend: headers: { Authorization: 'Bearer ' + idToken }| Provider | Method |
|---|---|
| Email/Password | createUserWithEmailAndPassword() |
| signInWithPopup(auth, new GoogleAuthProvider()) | |
| signInWithPopup(auth, new FacebookAuthProvider()) | |
| Apple | signInWithPopup(auth, new OAuthProvider("apple.com")) |
| GitHub | signInWithPopup(auth, new GithubAuthProvider()) |
| Twitter/X | signInWithPopup(auth, new TwitterAuthProvider()) |
| Phone | signInWithPhoneNumber(auth, phone, appVerifier) |
| Anonymous | signInAnonymously(auth) |
| Custom | signInWithCustomToken(auth, token) |
| Method | Description |
|---|---|
| verifyIdToken() | Verify JWT from client |
| createUser() | Create user programmatically |
| updateUser() | Update user properties |
| deleteUser() | Delete a user |
| getUser() | Get user by UID |
| listUsers() | List all users (paginated) |
| setCustomUserClaims() | Set admin roles, etc. |
| revokeRefreshTokens() | Force re-authentication |
verifyIdToken() to validate the JWT. Set custom claims for role-based access control (admin, editor, etc.).import { getFirestore, collection, doc, setDoc, addDoc, getDoc, getDocs,
updateDoc, deleteDoc, query, where, orderBy, limit, onSnapshot,
serverTimestamp, increment, writeBatch, getDocsFromCache } from "firebase/firestore";
const db = getFirestore(app);
// ── Add Documents ──
// With auto-generated ID
const docRef = await addDoc(collection(db, "users"), {
name: "Alice",
email: "alice@example.com",
createdAt: serverTimestamp(),
});
console.log("Added with ID:", docRef.id);
// With custom ID
await setDoc(doc(db, "users", "alice-123"), {
name: "Alice",
email: "alice@example.com",
createdAt: serverTimestamp(),
});
// ── Read Documents ──
const userSnap = await getDoc(doc(db, "users", "alice-123"));
if (userSnap.exists()) {
console.log(userSnap.data()); // { name: "Alice", email: "..." }
}
// ── Query Documents ──
const q = query(collection(db, "users"),
where("age", ">=", 25),
orderBy("createdAt", "desc"),
limit(10)
);
const querySnap = await getDocs(q);
querySnap.forEach((doc) => console.log(doc.id, doc.data()));
// ── Real-time Updates ──
const unsub = onSnapshot(doc(db, "users", "alice-123"), (docSnap) => {
console.log("Real-time update:", docSnap.data());
});
// Later: unsub();
// ── Update & Delete ──
await updateDoc(doc(db, "users", "alice-123"), {
age: 31,
updatedAt: serverTimestamp(),
});
await deleteDoc(doc(db, "users", "alice-123"));
// ── Atomic Operations ──
await updateDoc(doc(db, "users", "alice-123"), {
score: increment(10), // atomic increment
tags: arrayUnion("react"), // add to array (no duplicate)
});
// ── Batch Write ──
const batch = writeBatch(db);
batch.set(doc(db, "users", "user1"), { name: "Alice" });
batch.set(doc(db, "users", "user2"), { name: "Bob" });
batch.update(doc(db, "users", "user3"), { score: increment(5) });
await batch.commit(); // atomic, max 500 writes
// ── Transactions ──
import { runTransaction } from "firebase/firestore";
try {
await runTransaction(db, async (transaction) => {
const fromSnap = await transaction.get(doc(db, "accounts", "from"));
const toSnap = await transaction.get(doc(db, "accounts", "to"));
const fromBal = fromSnap.data().balance;
if (fromBal < 100) throw new Error("Insufficient funds");
transaction.update(doc(db, "accounts", "from"), { balance: increment(-100) });
transaction.update(doc(db, "accounts", "to"), { balance: increment(100) });
});
} catch (err) {
console.error("Transaction failed:", err);
}| Feature | Firestore | Realtime DB |
|---|---|---|
| Data model | Documents + collections | JSON tree |
| Queries | Filtering, sorting, pagination | Limited (by key, order, limit) |
| Offline support | Full offline persistence | Limited |
| Scaling | Automatic (regional/multi-region) | Manual sharding |
| Pricing | Per read/write/delete | Per GB downloaded |
| Real-time | onSnapshot() | on("value") |
| Transactions | Yes (multi-document) | Single-location |
| Batch writes | 500 per batch | No native batch |
| Security | Firestore Security Rules | Realtime DB Rules |
| Operator | Description |
|---|---|
| where("field", "==", val) | Equal |
| where("field", "<", val) | Less than |
| where("field", "<=", val) | Less than or equal |
| where("field", ">", val) | Greater than |
| where("field", ">=", val) | Greater than or equal |
| where("field", "in", arr) | Match any in array |
| where("field", "array-contains", val) | Array contains value |
| orderBy("field", "desc") | Sort field |
| limit(n) | Limit results |
| startAfter(doc) | Cursor pagination |
// ── Firebase Cloud Functions (2nd gen) ──
const { onDocumentCreated, onDocumentUpdated, onDocumentDeleted,
onCall, HttpsFunction, httpsRequest } = require("firebase-functions/v2");
const { getFirestore } = require("firebase-admin/firestore");
const { getAuth } = require("firebase-admin/auth");
const logger = require("firebase-functions/logger");
const admin = require("firebase-admin");
admin.initializeApp();
const db = getFirestore();
// ── Firestore Triggers ──
exports.onUserCreated = onDocumentCreated("users/{userId}", async (event) => {
const snapshot = event.data;
const userData = snapshot.data();
logger.info("New user created:", userData.email);
// Create user profile
await db.collection("profiles").doc(event.params.userId).set({
displayName: userData.displayName,
bio: "",
createdAt: admin.firestore.FieldValue.serverTimestamp(),
});
});
exports.onPostDeleted = onDocumentDeleted("posts/{postId}", async (event) => {
// Clean up related data
const postId = event.params.postId;
const comments = await db.collection("posts").doc(postId).collection("comments").get();
const batch = db.batch();
comments.forEach((doc) => batch.delete(doc.ref));
await batch.commit();
logger.info(`Deleted ${comments.size} comments for post ${postId}`);
});
// ── Auth Triggers ──
exports.onUserSignUp = onDocumentCreated("users/{userId}", async (event) => {
const { email } = event.data.data();
// Send welcome email
await sendWelcomeEmail(email);
});
// ── Callable Functions (client-side invoke) ──
exports.createPaymentIntent = onCall(async (request) => {
const { uid } = request.auth;
const { amount, currency } = request.data;
if (!uid) throw new HttpsError("unauthenticated", "Must be logged in");
if (amount < 50) throw new HttpsError("invalid-argument", "Minimum $0.50");
// Create Stripe payment intent...
return { clientSecret: "pi_xxx_secret_xxx" };
});
// ── Scheduled Function (Cron) ──
exports.dailyCleanup = httpsRequest("0 2 * * *", async () => {
const cutoff = admin.firestore.Timestamp.fromDate(
new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // 30 days ago
);
const oldSessions = await db.collection("sessions")
.where("lastActive", "<", cutoff).limit(500).get();
const batch = db.batch();
oldSessions.forEach((doc) => batch.delete(doc.ref));
if (oldSessions.size > 0) await batch.commit();
logger.info(`Cleaned up ${oldSessions.size} expired sessions`);
});// ── Client: Call a Cloud Function ──
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions(app);
const createPaymentIntent = httpsCallable(functions, "createPaymentIntent");
try {
const result = await createPaymentIntent({
amount: 5000, // $50.00 in cents
currency: "usd",
});
console.log("Client secret:", result.data.clientSecret);
} catch (error) {
console.error("Function error:", error.code, error.message);
}import { getStorage, ref, uploadBytes, uploadBytesResumable,
getDownloadURL, deleteObject, listAll } from "firebase/storage";
const storage = getStorage(app);
// ── Upload File ──
const fileInput = document.getElementById("file");
const file = fileInput.files[0];
const storageRef = ref(storage, `avatars/${auth.currentUser.uid}/${file.name}`);
await uploadBytes(storageRef, file);
const downloadUrl = await getDownloadURL(storageRef);
// ── Resumable Upload (large files) ──
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on("state_changed",
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(`Upload: ${progress}%`);
},
(error) => console.error("Upload failed:", error),
() => {
getDownloadURL(uploadTask.snapshot.ref).then((url) => {
console.log("File available at:", url);
});
}
);
// ── Delete File ──
await deleteObject(ref(storage, "avatars/user123/photo.jpg"));
// ── List Files ──
const listRef = ref(storage, "avatars/user123");
const { items } = await listAll(listRef);
items.forEach((item) => console.log(item.name));# ── Firebase Hosting ──
firebase init hosting # configure hosting
firebase deploy # deploy to production
firebase deploy --only hosting # deploy only hosting
# firebase.json (hosting config)
# {
# "hosting": {
# "public": "dist",
# "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
# "rewrites": [
# { "source": "**", "destination": "/index.html" }
# ],
# "headers": [
# {
# "source": "**/*.@(jpg|jpeg|gif|png|webp|svg)",
# "headers": [{ "key": "Cache-Control", "value": "max-age=31536000, immutable" }]
# }
# ]
# }
# }
# ── Firestore Security Rules ──
# rules_version = '2';
# service cloud.firestore {
# match /databases/{database}/documents {
# match /users/{userId} {
# allow read: if request.auth != null;
# allow write: if request.auth.uid == userId;
# }
# match /posts/{postId} {
# allow read: if true; // public read
# allow create: if request.auth != null;
# allow update, delete: if get(/databases/$(database)/documents/posts/$(postId)).data.authorId == request.auth.uid;
# }
# }
# }
# ── Deploy rules only
firebase deploy --only firestore:rules# ── Install & Start Emulators ──
firebase login
firebase init emulators # select: Auth, Firestore, Functions, Storage, Hosting
firebase emulators:start --only auth,firestore # start specific
firebase emulators:start # start all
# Emulators run on:
# Auth: localhost:9099
# Firestore: localhost:8080
# Storage: localhost:9199
# Functions: localhost:5001
# Hosting: localhost:5000
# UI: http://localhost:4000 (Emulator Suite UI)// ── Connect to Emulators (development) ──
import { connectAuthEmulator } from "firebase/auth";
import { connectFirestoreEmulator } from "firebase/firestore";
import { connectStorageEmulator } from "firebase/storage";
import { connectFunctionsEmulator } from "firebase/functions";
// Connect Auth emulator
if (location.hostname === "localhost") {
connectAuthEmulator(auth, "http://localhost:9099");
connectFirestoreEmulator(db, "localhost", 8080);
connectStorageEmulator(storage, "localhost", 9199);
connectFunctionsEmulator(functions, "localhost", 5001);
}
// ── Seed Firestore with emulator data ──
// firebase.json:
// {
// "firestore": {
// "rules": "firestore.rules",
// "indexes": "firestore.indexes.json",
// "emulators": {
// "startPort": 8080,
// "host": "0.0.0.0"
// }
// }
// }