<!-- skill: Firebase Backend | version: 1.0.0 | description: Firebase Auth, Firestore, Storage, Functions and Hosting setup | category: Web -->
## Instructions
- Project setup: `firebase init` (firestore/functions/hosting/storage/emulators), separate `dev/staging/prod` projects + `.firebaserc` aliases; never share prod keys with dev; `firebase use prod` explicit before deploys.
- Auth: Email/password + Google/OAuth providers, `onAuthStateChanged` client, Admin SDK `verifyIdToken()` in Functions/API; custom claims `admin:true` for RBAC, `revokeRefreshTokens()` on role change.
- Firestore modeling: collections `users/{uid}` + `projects/{id}` + subcollection `tasks`; denormalize read-hot fields, reference by id, paginate with `startAfter(lastDoc).limit(25)` cursors, never unbounded `get()` on large sets.
- Security rules: deny-by-default `allow read, write: if false;`, per-collection `request.auth != null && request.auth.uid == resource.data.ownerId`; validate types with `request.resource.data.name is string`; test with emulator rules unit tests.
- Queries/indexes: equality + range need composite indexes (`firebase firestore:indexes` JSON committed); use `where('ownerId','==',uid).orderBy('createdAt','desc')`; `onSnapshot` only for live widgets, `getDocs` for static lists.
- Storage: `users/{uid}/{file}` paths, rules mirror Firestore ownership, `getDownloadURL` after `uploadBytesResumable` with progress; image resize via `images` extension or FunctionSharp on finalize trigger.
- Cloud Functions gen2: `onRequest({cors:true, region})` HTTPS + `onDocumentCreated('projects/{id}')` triggers; `defineSecret('STRIPE_KEY')` for secrets, min-instances for latency paths, idempotency keys on webhooks.
- Hosting: `firebase.json` rewrites `/api/** → function`, SPA fallback `** → /index.html`, `headers Cache-Control` for `/assets/*` immutable; preview channels `firebase hosting:channel:deploy pr123` per PR.
- Emulators: `firebase emulators:start --import=./seed` for auth/firestore/functions/storage; seed script creates users/docs; CI runs rules + functions tests against `127.0.0.1:8080` before deploy.
- Batching/limits: `writeBatch` ≤500 ops, transactions for counters (`runTransaction`), `FieldValue.serverTimestamp()` + `increment()`; respect 1 write/sec/doc sustained, shard hot counters.
- Observability: structured `logger.info({uid})` in Functions, `functions:log`, Firestore usage tab alerts, Hosting release history rollback via `hosting:clone` or prior release promote.
- Billing guard: Blaze plan budgets + alerts, `firestore delete --recursive` only with backup (`gcloud firestore export gs://bucket`), retention TTL policy on logs/ephemeral collections.
## Examples
- SaaS tasks: `users/{uid}` + `projects/{ownerId}` rules, `onSnapshot` kanban realtime, `onDocumentCreated` Function sends invite email, Hosting SPA + `/api` rewrite.
- UGC photos: Storage `users/{uid}/photos` with owner rules, finalize Function generates 400px thumb via Sharp, Firestore doc updated with `thumbUrl`, client shows progress bar.
- Multi-tenant: custom claim `orgId`, rules `resource.data.orgId == request.auth.token.orgId`, scheduled Function cleans expired invites nightly, preview channel per PR.
## Workflows
1. Init: `firebase init`, `.firebaserc` aliases, emulator seed, `firestore.rules` deny-default + per-collection allows.
2. Auth: providers + custom claims, client `onAuthStateChanged`, server `verifyIdToken` gate.
3. Data: model collections, composite indexes JSON, paginated queries, `onSnapshot` only where live.
4. Functions: gen2 HTTPS + triggers, `defineSecret`, idempotent webhooks, structured logs.
5. Host + store: Hosting rewrites/headers, Storage rules + resumable uploads, thumb pipeline.
6. Ship: emulator tests green, `firebase deploy --only firestore:rules,functions,hosting`, preview channel QA, budget alerts on.
## Templates
- Rules + client query:
```
// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{db}/documents {
    match /projects/{id} {
      allow read: if request.auth != null && resource.data.ownerId == request.auth.uid;
      allow create: if request.auth != null && request.resource.data.ownerId == request.auth.uid
        && request.resource.data.name is string;
      allow update, delete: if request.auth != null && resource.data.ownerId == request.auth.uid;
    }
  }
}
```
```ts
import { collection, query, where, orderBy, limit, getDocs } from 'firebase/firestore';
const q = query(collection(db, 'projects'), where('ownerId', '==', uid), orderBy('createdAt', 'desc'), limit(25));
const snap = await getDocs(q);
```
- Gen2 function + Hosting:
```ts
import { onRequest } from 'firebase-functions/v2/https';
import { defineSecret } from 'firebase-functions/params';
const stripeKey = defineSecret('STRIPE_KEY');
export const api = onRequest({ cors: true, secrets: [stripeKey] }, async (req, res) => {
  if (req.method !== 'POST') { res.status(405).end(); return; }
  res.json({ ok: true });
});
```
```json
{ "hosting": { "public": "dist",
  "rewrites": [{ "source": "/api/**", "function": "api" }, { "source": "**", "destination": "/index.html" }],
  "headers": [{ "source": "/assets/**", "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }] }] } }
```
- Auth + upload:
```ts
import { onAuthStateChanged } from 'firebase/auth';
import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage';
onAuthStateChanged(auth, (u) => console.log(u?.uid));
const task = uploadBytesResumable(ref(storage, `users/${uid}/a.jpg`), file);
task.on('state_changed', (s) => console.log(s.bytesTransferred / s.totalBytes));
await task; const url = await getDownloadURL(task.snapshot.ref);
```
## Tools
- SARAH shell_run for `firebase emulators:start`, `firebase deploy --only`, `firebase hosting:channel:deploy`, rules tests.
- SARAH file_write for rules/indexes/functions/hosting-config; web_fetch for Firebase docs + Admin SDK.
## Advanced
- Sharding counters: `counters/{docId}/shards/{n}` random shard `increment(1)`, sum on read; scheduled aggregator hourly; TTL `expireAt` + delete policy for ephemeral docs.
- Multi-region: `region: 'europe-west1'` Functions near users, Firestore multi-region `eur3`, Hosting `kubectl`-free rollback via release pin, App Check enforcement on Functions + Storage.
- CI: GitHub Action starts emulators, runs `mocha` rules tests + `jest` functions tests, `firebase deploy --only` on main with `--project prod`, preview channels on PRs with expiry 7d.
## Documentation
- https://firebase.google.com/docs/auth
- https://firebase.google.com/docs/firestore/security/rules-structure
- https://firebase.google.com/docs/functions
- https://firebase.google.com/docs/hosting
- https://firebase.google.com/docs/emulator-suite
