api-baas-firebase
Firebase backend-as-a-service — Firestore, Authentication, Cloud Functions v2, Storage, Hosting, Admin SDK, security rules, emulator suite
Works with
---
name: api-baas-firebase
description: Firebase backend-as-a-service — Firestore, Authentication, Cloud Functions v2, Storage, Hosting, Admin SDK, security rules, emulator suite
license: MIT
---
# Firebase Patterns
> **Quick Guide:** Use Firebase as your backend-as-a-service for Firestore database, authentication, Cloud Functions, file storage, and hosting. Always use the modular SDK (`firebase/app`, `firebase/firestore`, etc.) for tree-shaking, type Firestore documents with TypeScript interfaces, write security rules for every collection, and use the Admin SDK only on the server.
---
<critical_requirements>
## CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST use the modular Firebase SDK imports (`firebase/app`, `firebase/firestore`, `firebase/auth`) -- NEVER use the deprecated `firebase/compat` namespace API)**
**(You MUST write Firestore security rules for EVERY collection -- a collection without rules is wide open in production)**
**(You MUST NEVER expose Firebase Admin SDK credentials or service account keys in client-side code)**
**(You MUST use Cloud Functions v2 API (`firebase-functions/v2/https`, `firebase-functions/v2/firestore`) -- NOT the deprecated v1 API)**
**(You MUST handle all Firestore operations with error checking -- never assume reads/writes succeed)**
</critical_requirements>
---
**Auto-detection:** Firebase, initializeApp, firebase/app, firebase/firestore, firebase/auth, getFirestore, getAuth, onAuthStateChanged, collection, doc, getDocs, setDoc, updateDoc, deleteDoc, onSnapshot, firebase-admin, firebase-functions, Cloud Functions, Firestore security rules, firebase.json, firebase deploy
**When to use:**
- Initializing Firebase and configuring services (Firestore, Auth, Storage, Functions)
- Implementing authentication (email/password, OAuth, phone, custom tokens)
- Querying and writing Firestore documents (CRUD, real-time listeners, transactions)
- Writing Cloud Functions v2 (HTTP handlers, callable functions, Firestore triggers, scheduled functions)
- Uploading and serving files from Firebase Storage
- Deploying to Firebase Hosting with function rewrites
- Writing Firestore and Storage security rules
- Using the Firebase Admin SDK for server-side operations
**Key patterns covered:**
- Modular SDK setup with `initializeApp` and service getters (`getFirestore`, `getAuth`, `getStorage`)
- Auth flows: sign up, sign in, OAuth, phone auth, `onAuthStateChanged`, session management
- Firestore CRUD with `doc()`, `collection()`, `getDocs()`, `setDoc()`, `updateDoc()`, `deleteDoc()`
- Firestore real-time listeners with `onSnapshot()`
- Firestore queries with `where()`, `orderBy()`, `limit()`, composite indexes
- Cloud Functions v2: `onRequest`, `onCall`, `onDocumentCreated`, `onSchedule`
- Firebase Admin SDK: `initializeApp()`, `getFirestore()`, `getAuth()`, custom tokens, user management
- Security rules: read/write granularity, auth-based access, data validation
- Emulator suite for local development and testing
- Offline persistence with `persistentLocalCache`
**When NOT to use:**
- Complex relational queries needing JOIN operations (use a relational database with an ORM)
- Full server-side ORM patterns (Firestore is a document database, not relational)
- Applications using a non-Firebase authentication provider
- Applications requiring complex server-side business logic beyond Cloud Functions scope
**Examples:**
- [Core Setup & Configuration](examples/core.md) -- App init, emulators, offline persistence
- [Firestore Database](examples/firestore.md) -- CRUD, queries, real-time listeners, transactions
- [Authentication](examples/auth.md) -- Email/password, OAuth, auth state, profile sync
- [Cloud Functions & Admin SDK](examples/functions.md) -- HTTP, callable, triggers, scheduled, Admin SDK
- [Cloud Storage](examples/storage.md) -- Upload with progress, validation, App Check
- [Security Rules](examples/security-rules.md) -- Firestore and Storage rules patterns
---
<philosophy>
## Philosophy
Firebase is Google's Backend-as-a-Service platform providing a complete backend through Firestore (document database), Authentication, Cloud Functions, Storage, Hosting, and more. The modular SDK (v12+) uses tree-shakeable ES module imports for minimal bundle sizes.
**Core principles:**
1. **Modular imports for tree-shaking** -- Import only what you need from `firebase/firestore`, `firebase/auth`, etc. The modular SDK can reduce bundle size by 80%+ compared to the legacy namespace API.
2. **Document-oriented data model** -- Firestore stores data as documents in collections. Design your data model around your query patterns, not normalized relations. Denormalization is expected.
3. **Security rules are mandatory** -- Firestore and Storage are directly accessible from clients. Security rules are your only server-side access control. Every collection needs rules.
4. **Cloud Functions v2 on Cloud Run** -- 2nd generation functions run on Cloud Run with better scaling, concurrency, longer timeouts (up to 60 minutes), and traffic splitting. Always use v2 for new projects.
5. **Offline-first with persistence** -- Firestore supports offline persistence via IndexedDB. Enable it with `persistentLocalCache` for apps that must work without connectivity.
6. **Admin SDK for server-side** -- The Firebase Admin SDK bypasses security rules and has full access. Use it only in trusted server environments (Cloud Functions, API servers).
**When to use Firebase:**
- Rapid prototyping and MVPs with auth, database, and storage out of the box
- Real-time applications (chat, live dashboards, collaborative editing) via Firestore listeners
- Mobile and web apps needing offline support with automatic sync
- Projects wanting serverless backend logic with Cloud Functions
- Applications needing simple file storage with security rules
**When NOT to use:**
- Complex relational data with many-to-many relationships and JOINs (use a relational database)
- Applications needing full-text search (Firestore has limited query capabilities -- use a dedicated search service)
- High-write-throughput scenarios exceeding 10,000 writes/second to a single document
- Applications requiring complex server-side transactions spanning multiple services
</philosophy>
---
<patterns>
## Core Patterns
### Pattern 1: Firebase App Initialization (Modular SDK)
Initialize Firebase with the modular SDK for tree-shaking. Each service has its own import path.
```typescript
// lib/firebase.ts
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
import { getStorage } from "firebase/storage";
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth(app);
export const storage = getStorage(app);
```
**Why good:** Modular imports enable tree-shaking, each service initialized from the app instance, named exports
> Full setup with emulators and offline persistence: [examples/core.md](examples/core.md)
---
### Pattern 2: Firestore CRUD Operations
Use modular functions for all Firestore read/write operations. Always type your documents.
```typescript
const POSTS_COLLECTION = "posts";
// Read
const docSnap = await getDoc(doc(db, POSTS_COLLECTION, postId));
if (!docSnap.exists()) throw new Error(`Not found: ${postId}`);
// Create with auto-ID and server timestamp
const docRef = doc(collection(db, POSTS_COLLECTION));
await setDoc(docRef, { ...data, createdAt: serverTimestamp() });
// Update specific fields
await updateDoc(doc(db, POSTS_COLLECTION, postId), {
...data,
updatedAt: serverTimestamp(),
});
// Delete
await deleteDoc(doc(db, POSTS_COLLECTION, postId));
```
**Why good:** Named constants for collection names, existence check before accessing data, `serverTimestamp()` for consistent timestamps, typed input parameters
> Full CRUD service with pagination: [examples/firestore.md](examples/firestore.md)
---
### Pattern 3: Firestore Real-Time Listeners
Subscribe to document and collection changes with `onSnapshot`. Always unsubscribe to prevent memory leaks.
```typescript
function subscribeToPublishedPosts(
onUpdate: (posts: Post[]) => void,
onError: (error: Error) => void,
): Unsubscribe {
const q = query(
collection(db, POSTS_COLLECTION),
where("published", "==", true),
orderBy("createdAt", "desc"),
);
return onSnapshot(
q,
(snapshot) => {
onUpdate(
snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }) as Post),
);
},
(error) => {
onError(new Error(`Listener failed: ${error.message}`));
},
);
}
// Always store and call the unsubscribe function
const unsubscribe = subscribeToPublishedPosts(handler, errorHandler);
unsubscribe(); // Cleanup when done
```
**Why good:** Returns `Unsubscribe` for cleanup, separate error callback, typed parameters
> Real-time chat implementation: [examples/firestore.md](examples/firestore.md)
---
### Pattern 4: Firestore Transactions and Batched Writes
Use transactions for atomic read-then-write operations. Use batched writes for multiple writes without reads.
```typescript
// Transaction: atomic read-then-write
await runTransaction(db, async (transaction) => {
const postSnap = await transaction.get(postRef);
if (!postSnap.exists()) throw new Error("Not found");
transaction.update(postRef, { likeCount: increment(1) });
transaction.set(likeRef, { createdAt: serverTimestamp() });
});
// Batch: multiple writes (up to 500)
const batch = writeBatch(db);
for (const id of postIds.slice(0, MAX_BATCH_SIZE)) {
batch.delete(doc(db, POSTS_COLLECTION, id));
}
await batch.commit();
```
**Why good:** Transaction ensures atomicity, `increment()` for safe counters, batch for bulk operations
> Full examples: [examples/firestore.md](examples/firestore.md)
---
### Pattern 5: Authentication Flows
Use Firebase Authentication with the modular SDK. Handle auth state changes with `onAuthStateChanged`.
```typescript
// Sign up / Sign in / Sign out
const credential = await createUserWithEmailAndPassword(auth, email, password);
const credential = await signInWithEmailAndPassword(auth, email, password);
await signOut(auth);
// OAuth
const result = await signInWithPopup(auth, new GoogleAuthProvider());
// Listen to auth state -- register early in app lifecycle
const unsubscribe = onAuthStateChanged(auth, (user) => {
/* ... */
});
// Get ID token for API calls
const token = await auth.currentUser?.getIdToken(/* forceRefresh */ true);
```
**Why good:** Modular imports, typed `User` return values, `Unsubscribe` for cleanup
> Full auth service with profile sync: [examples/auth.md](examples/auth.md)
---
### Pattern 6: Cloud Functions v2
Write Cloud Functions using the v2 API. Import from `firebase-functions/v2/*` subpackages.
```typescript
// HTTP function
import { onRequest } from "firebase-functions/v2/https";
export const getPosts = onRequest(
{ cors: true, region: "us-central1" },
async (req, res) => {
/* ... */
},
);
// Callable function (with auth)
import { onCall, HttpsError } from "firebase-functions/v2/https";
export const createPost = onCall({ region: "us-central1" }, async (request) => {
if (!request.auth)
throw new HttpsError("unauthenticated", "Must be signed in");
/* ... */
});
// Firestore trigger
import { onDocumentCreated } from "firebase-functions/v2/firestore";
export const onPostCreated = onDocumentCreated(
{ document: "posts/{postId}", region: "us-central1" },
async (event) => {
/* ... */
},
);
// Scheduled function
import { onSchedule } from "firebase-functions/v2/scheduler";
export const cleanup = onSchedule(
{ schedule: "every 24 hours", region: "us-central1" },
async () => {
/* ... */
},
);
```
**Why good:** v2 imports from subpackages, region specified, `HttpsError` for callable error handling
> Full Cloud Functions API: [examples/functions.md](examples/functions.md)
---
### Pattern 7: Firebase Admin SDK (Server-Side)
Use the Admin SDK in Cloud Functions or trusted server environments. Bypasses all security rules.
```typescript
import { initializeApp } from "firebase-admin/app";
import { getFirestore } from "firebase-admin/firestore";
import { getAuth } from "firebase-admin/auth";
initializeApp(); // Default credentials in Cloud Functions
export const adminDb = getFirestore();
export const adminAuth = getAuth();
// Custom claims for role-based access
await adminAuth.setCustomUserClaims(uid, { admin: true });
// Verify client ID tokens
const decoded = await adminAuth.verifyIdToken(idToken);
```
**Why good:** Modular Admin SDK imports, default credentials in Cloud Functions, custom claims for RBAC
> Full Admin SDK patterns: [examples/functions.md](examples/functions.md)
---
### Pattern 8: Firebase Storage
Upload, download, and manage files with Firebase Storage.
```typescript
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
const storageRef = ref(storage, `avatars/${userId}/avatar.png`);
const uploadTask = uploadBytesResumable(storageRef, file, {
contentType: file.type,
customMetadata: { uploadedBy: userId },
});
uploadTask.on("state_changed", (snapshot) => {
const PERCENT_MULTIPLIER = 100;
const percent =
(snapshot.bytesTransferred / snapshot.totalBytes) * PERCENT_MULTIPLIER;
onProgress(percent);
});
```
**Why good:** Resumable upload with progress, `customMetadata` for audit trail, named constants
> Full upload/download/delete with validation: [examples/storage.md](examples/storage.md)
---
### Pattern 9: Security Rules
Firestore and Storage security rules are your primary access control mechanism.
```
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuthenticated() { return request.auth != null; }
function isOwner(userId) { return request.auth.uid == userId; }
match /posts/{postId} {
allow read: if resource.data.published == true
|| isOwner(resource.data.authorId);
allow create: if isAuthenticated()
&& request.resource.data.authorId == request.auth.uid;
allow update: if isOwner(resource.data.authorId);
allow delete: if isOwner(resource.data.authorId);
}
}
}
```
**Why good:** Helper functions, granular CRUD permissions, ownership checks, data validation
> Full Firestore + Storage rules: [examples/security-rules.md](examples/security-rules.md)
</patterns>
---
<performance>
## Performance Optimization
### Query Performance
- **Use composite indexes** -- Compound queries (multiple `where` + `orderBy`) need composite indexes. Deploy via `firestore.indexes.json` or let Firestore error messages guide you with auto-generated index links.
- **Limit result sets** -- Always use `limit()` to cap query results. Unbounded queries fetch all matching documents.
- **Paginate with cursors** -- Use `startAfter()` with the last document snapshot for efficient pagination instead of `offset()`.
- **Select specific fields** -- Use `select()` in Admin SDK queries to fetch only needed fields (client SDK always fetches full documents).
### Bundle Size
- **Use `initializeAuth` for granular control** -- `getAuth()` enables all auth methods by default. Use `initializeAuth()` with only the providers you need for smaller bundles.
- **Use `firebase/firestore/lite`** -- If you don't need real-time listeners, import from `firebase/firestore/lite` for a smaller Firestore bundle (no `onSnapshot`).
### Cloud Functions
- **Minimize cold starts** -- Use `onInit()` for lazy initialization. Keep function dependencies small. Consider "fat functions" (one entry point routing to handlers) over many small functions.
- **Set appropriate memory/timeout** -- Configure `memory` and `timeoutSeconds` in function options instead of using defaults.
- **Use global variables for reusable connections** -- Initialize Admin SDK and database connections outside the function handler so they persist across invocations.
</performance>
---
<decision_framework>
## Decision Framework
### Firestore vs Realtime Database
```
What does your app need?
+-- Complex queries (where, orderBy, compound) --> Firestore
+-- Simple key-value lookups with low latency --> Realtime Database
+-- Offline support with rich queries --> Firestore
+-- Presence system (online/offline status) --> Realtime Database
+-- Multi-region availability --> Firestore
+-- Very frequent small updates (typing indicators) --> Realtime Database
+-- For most new projects --> Firestore (recommended default)
```
### Auth Method Selection
```
What auth flow does the user need?
+-- Email + Password --> createUserWithEmailAndPassword / signInWithEmailAndPassword
+-- Social login (Google, GitHub, etc.) --> signInWithPopup / signInWithRedirect
+-- Phone + SMS --> signInWithPhoneNumber (requires reCAPTCHA)
+-- Email link (passwordless) --> sendSignInLinkToEmail
+-- Custom backend auth --> Admin SDK createCustomToken + client signInWithCustomToken
+-- Anonymous (guest) --> signInAnonymously (upgrade later with linkWithCredential)
```
### Cloud Functions: onRequest vs onCall
```
Who is calling the function?
+-- External webhooks, third-party services --> onRequest (raw HTTP)
+-- Your own client app (web/mobile) --> onCall (automatic auth, input validation)
+-- Firestore document changes --> onDocumentCreated / onDocumentUpdated / onDocumentDeleted
+-- Scheduled/cron tasks --> onSchedule
+-- Authentication events --> onUserCreated / onUserDeleted (from firebase-functions/v2/identity)
```
### Client SDK vs Admin SDK
```
Where is the code running?
+-- Browser / Client-side --> Client SDK (firebase) -- security rules enforced
+-- Cloud Functions --> Admin SDK (firebase-admin) -- bypasses security rules
+-- API server / backend --> Admin SDK (firebase-admin) -- use service account
+-- NEVER use Admin SDK in client code --> It bypasses all security
```
### Storage: When to Use Firebase Storage
```
What kind of files?
+-- User-generated content (avatars, uploads) --> Firebase Storage with security rules
+-- Public static assets (CSS, images) --> Firebase Hosting (faster CDN)
+-- Large files with progress tracking --> Firebase Storage with uploadBytesResumable
+-- Server-generated files (reports, exports) --> Firebase Storage via Admin SDK
```
</decision_framework>
---
<integration>
## Integration Guide
**Firebase ecosystem integration:**
- **Firebase Hosting + Cloud Functions**: Rewrite rules in `firebase.json` route requests to functions
- **App Check**: Protect your backend resources from abuse by verifying requests come from your app (`initializeAppCheck` with reCAPTCHA Enterprise)
- **Firebase Extensions**: Pre-built Cloud Functions for common tasks (payments, image resizing, email sending)
**Client framework integration:**
- Use `onAuthStateChanged` in your framework's lifecycle (e.g., context provider, composable, store) to track auth state
- Firestore `onSnapshot` listeners require cleanup when components unmount -- use your framework's cleanup mechanism
- Wrap Firestore reads in your data fetching solution's query functions for caching and real-time invalidation
**Replaces / Conflicts with:**
- Other BaaS platforms -- don't use two BaaS solutions for the same purpose
- Custom auth providers -- Firebase Auth can replace third-party auth, or vice versa -- don't mix auth providers
</integration>
---
<red_flags>
## RED FLAGS
**High Priority Issues:**
- **Wide-open security rules in production** -- The default test-mode rules (`allow read, write: if true`) give everyone full access to your entire database. This is the single most common Firebase security vulnerability.
- **Admin SDK credentials in client code** -- Service account keys or Admin SDK imports in browser bundles give attackers full bypass of all security rules.
- **Using the compat/namespace API** -- `firebase/compat/*` imports prevent tree-shaking, bundling the entire SDK. The compat layer will be removed in a future major version.
- **Not handling auth state changes** -- Calling Firestore without waiting for `onAuthStateChanged` can result in unauthenticated requests that fail silently against security rules.
**Medium Priority Issues:**
- **Using v1 Cloud Functions API** -- v1 (`functions.https.onRequest`) lacks concurrency, traffic splitting, and longer timeouts. All new functions should use v2 (`firebase-functions/v2/https`).
- **Not unsubscribing from `onSnapshot`** -- Leaked listeners keep WebSocket connections open, consume bandwidth, and cause memory leaks.
- **Unbounded queries** -- Queries without `limit()` can fetch thousands of documents, causing performance issues and high read costs.
- **Monotonically increasing document IDs** -- Sequential IDs like `user1`, `user2` create hotspots. Use Firestore auto-generated IDs or UUIDs.
- **Using `functions.config()`** -- Deprecated and will fail after March 2027. Use Cloud Secret Manager (`defineSecret()`) or environment variables.
**Common Mistakes:**
- **Not adding `.select()` after Admin SDK queries** -- Without `select()`, all document fields are returned, increasing data transfer.
- **Calling `getFirestore()` on every operation** -- Initialize once and reuse the instance. Each call creates overhead.
- **Missing composite indexes** -- Compound queries fail at runtime if the required composite index doesn't exist. Check error messages for the auto-generated index creation link.
- **Deploying without testing security rules** -- Use the emulator to test rules before deploying. Use `firebase emulators:exec "npm test"` in CI.
- **Using `enableIndexedDbPersistence`** -- Deprecated. Use `initializeFirestore` with `persistentLocalCache` instead.
**Gotchas & Edge Cases:**
- **Firestore queries are "all or nothing" with security rules** -- If a query could potentially return documents the user isn't allowed to read, the entire query fails (not just the unauthorized documents).
- **Firestore limits** -- 1 MB max document size, 20,000 fields per document, 500 writes per batch, 1 write per second per document sustained.
- **Security rules propagation delay** -- Rule updates take up to 1 minute to affect new queries, and up to 10 minutes for active listeners.
- **`serverTimestamp()` returns `null` in `onSnapshot` pending writes** -- Until the server confirms the write, the timestamp field is `null` locally. Handle this with `{ serverTimestamps: 'estimate' }` in snapshot options.
- **Firebase Hosting has a 60-second timeout** -- Even if your Cloud Function has a longer timeout, requests through Hosting rewrites timeout at 60 seconds.
- **`onAuthStateChanged` fires on page load** -- It fires with `null` initially, then with the user if a session exists. Always handle the initial `null` state.
- **Firestore `in` queries are limited to 30 values** -- `where("field", "in", array)` supports a maximum of 30 elements in the array (increased from 10 in recent versions).
- **Cloud Functions cold starts** -- First invocation after idle has additional latency. Use `onInit()` for lazy initialization and keep dependencies minimal.
- **Admin SDK `initializeApp()` should be called once** -- Multiple calls throw an error unless you provide a unique app name. Guard with a try-catch or check `getApps().length`.
</red_flags>
---
<critical_reminders>
## CRITICAL REMINDERS
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST use the modular Firebase SDK imports (`firebase/app`, `firebase/firestore`, `firebase/auth`) -- NEVER use the deprecated `firebase/compat` namespace API)**
**(You MUST write Firestore security rules for EVERY collection -- a collection without rules is wide open in production)**
**(You MUST NEVER expose Firebase Admin SDK credentials or service account keys in client-side code)**
**(You MUST use Cloud Functions v2 API (`firebase-functions/v2/https`, `firebase-functions/v2/firestore`) -- NOT the deprecated v1 API)**
**(You MUST handle all Firestore operations with error checking -- never assume reads/writes succeed)**
**Failure to follow these rules will create security vulnerabilities, bloated bundles, deprecated code paths, and silent runtime failures.**
</critical_reminders>More Security skills
entra-app-registration
microsoft/azure-skills
Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.
azure-messaging
microsoft/azure-skills
Troubleshoot and resolve issues with Azure Messaging SDKs for Event Hubs and Service Bus. Covers connection failures, authentication errors, message processing issues, and SDK configuration problems. WHEN: event hub SDK error, service bus SDK issue, messaging connection failure, AMQP error, event processor host issue, message lock lost, message lock expired, lock renewal, lock renewal batch, send timeout, receiver disconnected, SDK troubleshooting, azure messaging SDK, event hub consumer, service bus queue issue, topic subscription error, enable logging event hub, service bus logging, eventhub python, servicebus java, eventhub javascript, servicebus dotnet, event hub checkpoint, event hub not receiving messages, service bus dead letter, batch processing lock, session lock expired, idle timeout, connection inactive, link detach, slow reconnect, session error, duplicate events, offset reset, receive batch.
azure-compliance
microsoft/azure-skills
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.

