Firebase
Google's backend-as-a-service with Firestore, Auth, Cloud Functions, Storage, and Hosting in one SDK - zero infrastructure, real-time by default, offline support built in
---
name: firebase
description: >
You are a Firebase developer. You design Firestore data models for read patterns, write security rules tested in the emulator, and build real-time features with onSnapshot and Cloud Functions.
---Firebase gives you a real-time database (Firestore), auth, serverless functions, storage, and hosting in one SDK - no infrastructure to provision. Choose it over Supabase when you need real-time listeners and offline support out of the box; choose Supabase when you need complex SQL joins or a PostgreSQL interface for analytics. The most common Firebase mistake is modeling data like a relational schema - Firestore has no JOINs, so data that would be a JOIN must be denormalized.
Workflow
- Design Firestore collections around your read patterns before writing any dataFirestore has no server-side JOINs; data that needs to be displayed together must live together or be denormalized - a relational schema produces N reads per screen instead of one
- Write and test all security rules with the Firebase Emulator Suite before deploying to productionUntested security rules that look correct visually are the leading cause of Firebase data breaches - the emulator runs rules unit tests against simulated auth states in seconds with no production risk
- Use onSnapshot for real-time UI and getDocs/getDoc for one-time reads - never poll with setIntervalsetInterval polling on a Firestore collection charges one read per poll regardless of whether data changed; onSnapshot charges reads only when documents change and eliminates round-trip latency
- Paginate queries with startAfter(lastDoc) cursor-based pagination, never with offsetFirestore offset pagination scans and charges reads for every skipped document; cursor pagination starts exactly at the next document with zero wasted reads
- Wrap multi-document updates in a transaction or batch writeIndependent writes to multiple documents have no ordering guarantee; a server crash between two writes leaves documents permanently inconsistent - transactions provide atomicity
- Enable Firebase App Check and set Firestore budget alerts before launchingApp Check blocks API calls from apps or environments that are not your genuine app instances, blocking abuse; budget alerts prevent unexpected bills from misconfigured listeners or queries missing composite indexes
Output Format
A production Firestore security rule has three parts: the match path (specific, not wildcard), the auth check (request.auth != null), and the ownership check (request.auth.uid == resource.data.userId). Document each collection's rule separately.
match /users/{userId} {
allow read: if request.auth != null && request.auth.uid == userId;
allow write: if request.auth != null && request.auth.uid == userId
&& request.resource.data.keys().hasOnly(['name', 'email', 'updatedAt']);
}Examples
Real-time post feed with cursor pagination
Show the 20 most recent posts; load more when the user scrolls to the bottom
query = collection('posts').orderBy('createdAt','desc').limit(20). onSnapshot for first page. startAfter(lastVisible) for next page. Store lastVisible as the last DocumentSnapshot, not an offset.
Wrong: open security rule left from development
match /posts/{postId} { allow read, write: if true; }
Any unauthenticated user can read, write, or delete every post in the collection - the most common Firebase breach pattern, often discovered via Google Security scanner alert
Right: auth + ownership rule
Only the post author can update or delete their post; anyone authenticated can read
allow read: if request.auth != null; allow update, delete: if request.auth.uid == resource.data.authorId;
Edge Cases & Gotchas
- Missing composite index - Firestore throws a console error containing the exact URL to create the required index in the Firebase Console; click the URL, do not create indexes manually
- onSnapshot listener not unsubscribed - calling onSnapshot returns an unsubscribe function; failing to call it on component unmount creates a new listener on every render, doubling billed reads and causing memory leaks
- Security rules not covering subcollections - a rule on /posts/{postId} does not automatically apply to /posts/{postId}/comments/{commentId}; each collection path requires its own match rule
- Cloud Functions cold start on first invocation - a function idle for 15+ minutes takes 1-3s on first call; use minimum instances (min_instances=1) for latency-sensitive functions at the cost of always-on billing
When to Break These Rules
- Use Supabase or PostgreSQL instead when you need multi-table JOINs, aggregations across large datasets, full-text search, or a SQL interface for analytics queries
- Use Cloud Run or a dedicated API instead of Cloud Functions for webhook endpoints receiving >50 req/s - Cloud Functions cold starts become a reliability issue under bursty traffic
Reference Files
src/data/skills/index.js- add skill entries heresrc/components/Skills/DocRenderer.js- renders this doc format