api-baas-firebase
FirebaseのFirestore、認証、Cloud Functionsなどの機能を活用し、セキュアでスケーラブルなWeb/モバイルアプリケーションのバックエンドを効率的に構築・管理するSkill。
📜 元の英語説明(参考)
Firebase backend-as-a-service — Firestore, Authentication, Cloud Functions v2, Storage, Hosting, Admin SDK, security rules, emulator suite
🇯🇵 日本人クリエイター向け解説
FirebaseのFirestore、認証、Cloud Functionsなどの機能を活用し、セキュアでスケーラブルなWeb/モバイルアプリケーションのバックエンドを効率的に構築・管理するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o api-baas-firebase.zip https://jpskill.com/download/10224.zip && unzip -o api-baas-firebase.zip && rm api-baas-firebase.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10224.zip -OutFile "$d\api-baas-firebase.zip"; Expand-Archive "$d\api-baas-firebase.zip" -DestinationPath $d -Force; ri "$d\api-baas-firebase.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
api-baas-firebase.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
api-baas-firebaseフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Firebase のパターン
クイックガイド: Firestore データベース、認証、Cloud Functions、ファイルストレージ、およびホスティングのために、Firebase を backend-as-a-service として使用します。常にツリーシェイキングのためにモジュール式 SDK (
firebase/app、firebase/firestoreなど) を使用し、TypeScript インターフェースで Firestore ドキュメントを型付けし、すべてのコレクションに対してセキュリティルールを記述し、Admin SDK はサーバー上でのみ使用します。
<critical_requirements>
重要: この Skill を使用する前に
すべてのコードは
CLAUDE.mdのプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順序、import type、名前付き定数)
(モジュール式 Firebase SDK インポート (firebase/app、firebase/firestore、firebase/auth) を必ず使用してください -- 非推奨の firebase/compat 名前空間 API は絶対に使用しないでください)
(すべてのコレクションに対して Firestore セキュリティルールを必ず記述してください -- ルールがないコレクションは本番環境で完全にオープンになります)
(Firebase Admin SDK の認証情報またはサービスアカウントキーをクライアント側のコードで絶対に公開しないでください)
(Cloud Functions v2 API (firebase-functions/v2/https、firebase-functions/v2/firestore) を必ず使用してください -- 非推奨の v1 API ではありません)
(すべての Firestore 操作をエラーチェックで処理してください -- 読み取り/書き込みが成功することを決して想定しないでください)
</critical_requirements>
自動検出: 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
使用するタイミング:
- Firebase の初期化とサービス (Firestore, Auth, Storage, Functions) の構成
- 認証の実装 (メール/パスワード、OAuth、電話、カスタムトークン)
- Firestore ドキュメントのクエリと書き込み (CRUD、リアルタイムリスナー、トランザクション)
- Cloud Functions v2 の記述 (HTTP ハンドラー、呼び出し可能関数、Firestore トリガー、スケジュールされた関数)
- Firebase Storage からのファイルのアップロードと提供
- 関数リライトによる Firebase Hosting へのデプロイ
- Firestore および Storage セキュリティルールの記述
- サーバー側の操作のための Firebase Admin SDK の使用
カバーされる主要なパターン:
initializeAppとサービスゲッター (getFirestore、getAuth、getStorage) を使用したモジュール式 SDK のセットアップ- 認証フロー: サインアップ、サインイン、OAuth、電話認証、
onAuthStateChanged、セッション管理 doc()、collection()、getDocs()、setDoc()、updateDoc()、deleteDoc()を使用した Firestore CRUDonSnapshot()を使用した Firestore リアルタイムリスナーwhere()、orderBy()、limit()、複合インデックスを使用した Firestore クエリ- Cloud Functions v2:
onRequest、onCall、onDocumentCreated、onSchedule - Firebase Admin SDK:
initializeApp()、getFirestore()、getAuth()、カスタムトークン、ユーザー管理 - セキュリティルール: 読み取り/書き込みの粒度、認証ベースのアクセス、データ検証
- ローカル開発およびテスト用のエミュレータースイート
persistentLocalCacheを使用したオフライン永続化
使用しないタイミング:
- JOIN 操作を必要とする複雑なリレーショナルクエリ (ORM を使用してリレーショナルデータベースを使用)
- 完全なサーバー側の ORM パターン (Firestore はドキュメントデータベースであり、リレーショナルではありません)
- Firebase 以外の認証プロバイダーを使用するアプリケーション
- Cloud Functions の範囲を超える複雑なサーバー側のビジネスロジックを必要とするアプリケーション
例:
- コアセットアップと構成 -- アプリの初期化、エミュレーター、オフライン永続化
- Firestore データベース -- CRUD、クエリ、リアルタイムリスナー、トランザクション
- 認証 -- メール/パスワード、OAuth、認証状態、プロファイル同期
- Cloud Functions と Admin SDK -- HTTP、呼び出し可能、トリガー、スケジュール、Admin SDK
- Cloud Storage -- 進捗状況付きのアップロード、検証、App Check
- セキュリティルール -- Firestore および Storage ルールのパターン
<philosophy>
哲学
Firebase は Google の Backend-as-a-Service プラットフォームであり、Firestore (ドキュメントデータベース)、認証、Cloud Functions、Storage、Hosting などを通じて完全なバックエンドを提供します。モジュール式 SDK (v12+) は、最小限のバンドルサイズのためにツリーシェイク可能な ES モジュールインポートを使用します。
コア原則:
- ツリーシェイキングのためのモジュール式インポート --
firebase/firestore、firebase/authなどから必要なものだけをインポートします。モジュール式 SDK は、従来の名前空間 API と比較してバンドルサイズを 80% 以上削減できます。 - ドキュメント指向のデータモデル -- Firestore は、コレクション内のドキュメントとしてデータを保存します。正規化されたリレーションではなく、クエリパターンを中心にデータモデルを設計します。非正規化が想定されます。
- セキュリティルールは必須 -- Firestore と Storage はクライアントから直接アクセスできます。セキュリティルールは、サーバー側の唯一のアクセス制御です。すべてのコレクションにルールが必要です。
- Cloud Run 上の Cloud Functions v2 -- 第 2 世代の関数は Cloud Run 上で実行され、スケーリング、同時実行性、より長いタイムアウト (最大 60 分)、およびトラフィック分割が向上しています。新しいプロジェクトでは常に v2 を使用してください。
- 永続化によるオフラインファースト -- Firestore は IndexedDB を介したオフライン永続化をサポートしています。接続なしで動作する必要があるアプリの場合は、
persistentLocalCacheで有効にします。 - サーバー側の Admin SDK -- Firebase Admin SDK はセキュリティルールをバイパスし、完全なアクセス権を持っています。信頼できるサーバー環境 (Cloud Functions、API サーバー) でのみ使用してください。
Firebase を使用するタイミング:
- 認証、データベース、ストレージをすぐに利用できる迅速なプロトタイピングと MVP
- Firestore リスナーを介したリアルタイムアプリケーション (チャット、ライブダッシュボード、共同編集)
- 自動同期によるオフラインサポートを必要とするモバイルおよび Web アプリ
- Cloud Functions を使用したサーバーレスバックエンドロジックを必要とするプロジェクト
- セキュリティルールによるシンプルなファイルストレージを必要とするアプリケーション
使用しないタイミング:
- 多対多の関係と JOIN を持つ複雑なリレーショナルデータ (リレーショナルデータベースを使用)
- フルテキスト検索を必要とするアプリケーション (Firestore にはクエリ機能が制限されています -- 専用の
(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
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
initializeAppand 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 -- App init, emulators, offline persistence
- Firestore Database -- CRUD, queries, real-time listeners, transactions
- Authentication -- Email/password, OAuth, auth state, profile sync
- Cloud Functions & Admin SDK -- HTTP, callable, triggers, scheduled, Admin SDK
- Cloud Storage -- Upload with progress, validation, App Check
- Security Rules -- 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:
- 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. - 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.
- 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.
- 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.
- Offline-first with persistence -- Firestore supports offline persistence via IndexedDB. Enable it with
persistentLocalCachefor apps that must work without connectivity. - 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.
// 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
Pattern 2: Firestore CRUD Operations
Use modular functions for all Firestore read/write operations. Always type your documents.
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
Pattern 3: Firestore Real-Time Listeners
Subscribe to document and collection changes with onSnapshot. Always unsubscribe to prevent memory leaks.
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
Pattern 4: Firestore Transactions and Batched Writes
Use transactions for atomic read-then-write operations. Use batched writes for multiple writes without reads.
// 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
Pattern 5: Authentication Flows
Use Firebase Authentication with the modular SDK. Handle auth state changes with onAuthStateChanged.
// 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
Pattern 6: Cloud Functions v2
Write Cloud Functions using the v2 API. Import from firebase-functions/v2/* subpackages.
// 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
Pattern 7: Firebase Admin SDK (Server-Side)
Use the Admin SDK in Cloud Functions or trusted server environments. Bypasses all security rules.
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
Pattern 8: Firebase Storage
Upload, download, and manage files with Firebase Storage.
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
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
</patterns>
<performance>
Performance Optimization
Query Performance
- Use composite indexes -- Compound queries (multiple
where+orderBy) need composite indexes. Deploy viafirestore.indexes.jsonor 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 ofoffset(). - Select specific fields -- Use
select()in Admin SDK queries to fetch only needed fields (client SDK always fetches full documents).
Bundle Size
- Use
initializeAuthfor granular control --getAuth()enables all auth methods by default. UseinitializeAuth()with only the providers you need for smaller bundles. - Use
firebase/firestore/lite-- If you don't need real-time listeners, import fromfirebase/firestore/litefor a smaller Firestore bundle (noonSnapshot).
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
memoryandtimeoutSecondsin 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.jsonroute requests to functions - App Check: Protect your backend resources from abuse by verifying requests come from your app (
initializeAppCheckwith reCAPTCHA Enterprise) - Firebase Extensions: Pre-built Cloud Functions for common tasks (payments, image resizing, email sending)
Client framework integration:
- Use
onAuthStateChangedin your framework's lifecycle (e.g., context provider, composable, store) to track auth state - Firestore
onSnapshotlisteners 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
onAuthStateChangedcan 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,user2create 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 -- Withoutselect(), 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. UseinitializeFirestorewithpersistentLocalCacheinstead.
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()returnsnullinonSnapshotpending writes -- Until the server confirms the write, the timestamp field isnulllocally. 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.
onAuthStateChangedfires on page load -- It fires withnullinitially, then with the user if a session exists. Always handle the initialnullstate.- Firestore
inqueries 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 checkgetApps().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>