plugins/devkit/skills/developing-firebase/SKILL.md
Firebase platform development guide covering Authentication (email/social/session), Firestore & Realtime Database (modeling/queries/security rules), Cloud Storage, Cloud Functions (triggers/scheduling), Hosting, Analytics (events/BigQuery), FCM push notifications, Remote Config, Test Lab, Performance Monitoring, Dynamic Links, App Distribution, AdMob, and Extensions. MUST load when firebase, @firebase, or firebase-admin packages detected, or firebaseConfig/firebase.json/firestore.rules files present. For GCP infra→developing-google-cloud. For Next.js integration→developing-nextjs. For REST API design→developing-web-apis.
npx skillsauth add sumik5/sumik-claude-plugin developing-firebaseInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Firebase は Google が提供する BaaS(Backend-as-a-Service)プラットフォーム。3つの柱でアプリ開発を支援する。
| 柱 | 主要サービス | |----|-------------| | Build | Authentication, Firestore, RTDB, Storage, Functions, Hosting | | Release & Monitor | Crashlytics, Performance Monitoring, Test Lab, App Distribution | | Engage | Analytics, FCM, In-App Messaging, Remote Config, Dynamic Links |
データ永続化が必要?
├─ リアルタイム同期・シンプル構造 → Realtime Database
├─ 複雑なクエリ・スケーラブル → Cloud Firestore ← 基本的にこちら
└─ ファイル(画像・動画等) → Cloud Storage
ロジック実行が必要?
├─ Firebase イベントトリガー → Cloud Functions
├─ HTTP API エンドポイント → Cloud Functions (HTTPS)
└─ スケジューリング → Cloud Functions (Scheduled)
ユーザー管理が必要?
└─ Firebase Authentication(必須)
Web公開が必要?
└─ Firebase Hosting(CDN + SSL自動)
Web (JS/TS)
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
const app = initializeApp({
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
});
export const auth = getAuth(app);
export const db = getFirestore(app);
export const storage = getStorage(app);
Android (Kotlin)
// build.gradle (app)
implementation(platform("com.google.firebase:firebase-bom:32.7.0"))
implementation("com.google.firebase:firebase-auth-ktx")
implementation("com.google.firebase:firebase-firestore-ktx")
iOS (Swift)
import FirebaseCore
// AppDelegate.swift
FirebaseApp.configure()
| 方式 | SDK呼び出し | 主なユースケース |
|------|------------|----------------|
| Email/Password | createUserWithEmailAndPassword / signInWithEmailAndPassword | 一般的なサインアップ |
| Google | signInWithPopup(new GoogleAuthProvider()) | ワンクリックログイン |
| GitHub / Twitter / Facebook | signInWithPopup(new GithubAuthProvider()) | 開発者向け・SNS系 |
| 電話番号 (SMS) | signInWithPhoneNumber | モバイル優先アプリ |
| 匿名 | signInAnonymously | ゲストユーザー→後でアカウント昇格 |
| カスタム | signInWithCustomToken | 既存の認証システム連携 |
// Email/Password サインアップ例
import { createUserWithEmailAndPassword, sendEmailVerification } from 'firebase/auth';
const { user } = await createUserWithEmailAndPassword(auth, email, password);
await sendEmailVerification(user); // メール認証送信
// ソーシャルログイン(Google)
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
const provider = new GoogleAuthProvider();
const result = await signInWithPopup(auth, provider);
// 認証状態監視
import { onAuthStateChanged } from 'firebase/auth';
onAuthStateChanged(auth, (user) => {
if (user) {
// ログイン済み: user.uid, user.email, user.displayName
}
});
詳細: references/AUTHENTICATION.md — セッション管理・MFA・カスタムクレーム
| 比較軸 | Cloud Firestore | Realtime Database | |--------|----------------|-------------------| | データ構造 | コレクション/ドキュメント | JSONツリー | | クエリ | 複合クエリ・インデックス対応 | 単純な絞り込みのみ | | スケーラビリティ | 自動スケーリング | リージョン単一・制限あり | | オフライン | ✅ Web/iOS/Android | ✅ iOS/Android のみ | | コスト | 読書き回数課金 | 帯域幅/ストレージ課金 | | 推奨用途 | 新規アプリ(基本こちら) | リアルタイムチャット・IoT |
// Firestore CRUD
import { collection, doc, setDoc, getDoc, updateDoc, deleteDoc, query, where, getDocs } from 'firebase/firestore';
// 作成・更新
await setDoc(doc(db, 'users', userId), { name: 'Alice', age: 30 });
await updateDoc(doc(db, 'users', userId), { age: 31 });
// 読み込み
const snap = await getDoc(doc(db, 'users', userId));
if (snap.exists()) console.log(snap.data());
// クエリ
const q = query(collection(db, 'users'), where('age', '>', 18));
const querySnap = await getDocs(q);
querySnap.forEach(doc => console.log(doc.id, doc.data()));
// リアルタイムリスナー
import { onSnapshot } from 'firebase/firestore';
const unsubscribe = onSnapshot(collection(db, 'messages'), (snap) => {
snap.docChanges().forEach(change => {
if (change.type === 'added') console.log('New:', change.doc.data());
});
});
// Android (Kotlin) Firestore
val db = Firebase.firestore
db.collection("users").document(userId)
.set(hashMapOf("name" to "Alice", "age" to 30))
.addOnSuccessListener { Log.d("TAG", "DocumentSnapshot written") }
詳細: references/DATABASE.md — データモデリング・トランザクション・インデックス設計
import { ref, uploadBytes, getDownloadURL, deleteObject } from 'firebase/storage';
// アップロード
const storageRef = ref(storage, `images/${userId}/profile.jpg`);
const snapshot = await uploadBytes(storageRef, file);
const downloadURL = await getDownloadURL(snapshot.ref);
// 削除
await deleteObject(ref(storage, `images/${userId}/profile.jpg`));
// iOS (Swift)
let storageRef = Storage.storage().reference().child("images/\(uid)/profile.jpg")
storageRef.putData(imageData, metadata: nil) { metadata, error in
storageRef.downloadURL { url, error in /* use url */ }
}
詳細: references/STORAGE-AND-HOSTING.md
| トリガー種別 | 記述例 | 主なユースケース |
|------------|--------|----------------|
| HTTP | onRequest | REST API・Webhook |
| Firestore | onDocumentCreated / onDocumentUpdated | データ変換・通知送信 |
| Auth | beforeUserCreated / onUserDeleted | プロファイル初期化・クリーンアップ |
| Storage | onObjectFinalized | 画像リサイズ・ウイルススキャン |
| Pub/Sub | onMessagePublished | 非同期処理パイプライン |
| Scheduled | onSchedule | 定期バッチ処理 |
// functions/src/index.ts
import { onRequest } from 'firebase-functions/v2/https';
import { onDocumentCreated } from 'firebase-functions/v2/firestore';
import { onSchedule } from 'firebase-functions/v2/scheduler';
import * as admin from 'firebase-admin';
admin.initializeApp();
// HTTP トリガー
export const api = onRequest({ region: 'asia-northeast1' }, (req, res) => {
res.json({ message: 'Hello from Firebase!' });
});
// Firestore トリガー(新規ユーザー作成時)
export const onUserCreated = onDocumentCreated('users/{userId}', async (event) => {
const userId = event.params.userId;
const data = event.data?.data();
// ウェルカムメール送信等の処理
});
// スケジュールトリガー(毎日午前2時)
export const dailyCleanup = onSchedule('0 2 * * *', async () => {
// 期限切れデータのクリーンアップ
});
詳細: references/FUNCTIONS.md — 環境変数・エラーハンドリング・デプロイ設定
# セットアップ
npm install -g firebase-tools
firebase login
firebase init hosting # public dir, SPA rewrite設定
# デプロイ
firebase deploy --only hosting
# プレビューチャンネル(PR確認用)
firebase hosting:channel:deploy preview-branch
// firebase.json
{
"hosting": {
"public": "out",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [{ "source": "**", "destination": "/index.html" }],
"headers": [
{ "source": "**/*.@(js|css)", "headers": [{ "key": "Cache-Control", "value": "max-age=31536000" }] }
]
}
}
詳細: references/STORAGE-AND-HOSTING.md — カスタムドメイン・リライト・CI/CD統合
| パターン | 用途 | ルール例 |
|---------|------|---------|
| 認証必須 | すべての操作で認証要求 | request.auth != null |
| 所有権チェック | 自分のデータのみ操作 | request.auth.uid == userId |
| ロールベース | カスタムクレームで権限管理 | request.auth.token.admin == true |
| データ検証 | 書き込みデータのバリデーション | request.resource.data.age is int |
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// ヘルパー関数
function isAuthenticated() {
return request.auth != null;
}
function isOwner(userId) {
return request.auth.uid == userId;
}
function isAdmin() {
return request.auth.token.admin == true;
}
// ユーザープロフィール: 本人のみ読み書き
match /users/{userId} {
allow read: if isAuthenticated() && isOwner(userId);
allow write: if isOwner(userId) && request.resource.data.keys().hasAll(['name', 'email']);
}
// 投稿: 認証済みユーザーは全員読み取り可、作成者のみ編集・削除
match /posts/{postId} {
allow read: if isAuthenticated();
allow create: if isAuthenticated() && request.resource.data.authorId == request.auth.uid;
allow update, delete: if resource.data.authorId == request.auth.uid;
}
// 管理者専用
match /admin/{document=**} {
allow read, write: if isAdmin();
}
}
}
{
"rules": {
"users": {
"$userId": {
".read": "auth != null && auth.uid == $userId",
".write": "auth != null && auth.uid == $userId"
}
},
"posts": {
".read": "auth != null",
"$postId": {
".write": "auth != null && (!data.exists() || data.child('authorId').val() == auth.uid)"
}
}
}
}
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// ユーザー固有の画像: 本人のみ操作可
match /images/{userId}/{allPaths=**} {
allow read: if request.auth != null;
allow write: if request.auth != null
&& request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024 // 5MB制限
&& request.resource.contentType.matches('image/.*');
allow delete: if request.auth.uid == userId;
}
}
}
# Emulator起動(開発中は必ずローカルで完結させる)
firebase emulators:start --import=./emulator-data --export-on-exit
# Emulator接続(アプリ側)
import { connectFirestoreEmulator } from 'firebase/firestore';
import { connectAuthEmulator } from 'firebase/auth';
import { connectStorageEmulator } from 'firebase/storage';
import { connectFunctionsEmulator } from 'firebase/functions';
if (process.env.NODE_ENV === 'development') {
connectAuthEmulator(auth, 'http://localhost:9099');
connectFirestoreEmulator(db, 'localhost', 8080);
connectStorageEmulator(storage, 'localhost', 9199);
connectFunctionsEmulator(functions, 'localhost', 5001);
}
| Emulator | ポート | 用途 | |---------|--------|------| | Authentication | 9099 | 認証テスト(実際のメール不要) | | Firestore | 8080 | データ操作テスト | | Storage | 9199 | ファイル操作テスト | | Functions | 5001 | トリガー動作確認 | | Hosting | 5000 | デプロイ前確認 | | UI | 4000 | 全体ダッシュボード |
| 対策 | 対象 | 方法 |
|------|------|------|
| クエリ絞り込み | Firestore | limit() で取得件数を制限 |
| インデックス | Firestore | 複合クエリには firestore.indexes.json で事前定義 |
| オフラインキャッシュ | Firestore/RTDB | enableIndexedDbPersistence() |
| 遅延ロード | Functions | Cold start対策: 最小依存・メモリ設定 |
| CDNキャッシュ | Hosting | 静的アセットに長期 Cache-Control を設定 |
| サービス | 無料枠(Spark) | 注意点 | |---------|--------------|--------| | Firestore | 読み取り5万回/日、書き込み2万回/日 | 不要なリスナー解除を徹底 | | Storage | 5GB, 1GB/日ダウンロード | 大容量ファイルはCDN経由で配信 | | Functions | 呼び出し200万回/月 | 無限ループに注意(トリガーの連鎖) | | Hosting | 10GB/月 | 静的アセットの圧縮で削減 |
// Firestore: 不要なリスナー解除
const unsubscribe = onSnapshot(query, callback);
// コンポーネントアンマウント時
return () => unsubscribe();
| ファイル | カバー内容 | 主なトピック |
|---------|-----------|------------|
| references/AUTHENTICATION.md | 認証詳細 | Email/Social実装・セッション管理・MFA・カスタムクレーム・匿名→昇格 |
| references/DATABASE.md | Firestore + RTDB | データモデリング・複合クエリ・トランザクション・バッチ・インデックス・RTDB構造設計 |
| references/STORAGE-AND-HOSTING.md | Storage + Hosting | アップロード/ダウンロード・メタデータ・カスタムドメイン・リライト・プレビューChannel |
| references/FUNCTIONS.md | Cloud Functions | 全トリガー詳細・環境変数・シークレット管理・エラーハンドリング・Gen2移行 |
| references/ANALYTICS-AND-MONITORING.md | Analytics + 監視 | カスタムイベント・BigQuery連携・Crashlytics・Performance Monitoring |
| references/MESSAGING.md | FCM + Remote Config | プッシュ通知送信・トピック購読・Remote Config A/Bテスト・Dynamic Links |
| references/TESTING-AND-DISTRIBUTION.md | テスト + 配布 | Test Lab・Emulatorテスト戦略・App Distribution・CI/CD統合 |
| references/EXTENSIONS-AND-ADVANCED.md | 拡張機能・応用 | Firebase Extensions・AdMob・クロスプラットフォーム固有パターン |
tools
FastAPI (Python) web API development guide covering fundamentals (routing, path/query params, Pydantic models, request/response, error handling), data persistence (SQLAlchemy, SQLModel, async DB, MongoDB, CRUD, Alembic migrations), dependency injection (Depends, dependency_overrides, scopes/lifespan), auth & security (OAuth2, JWT, CORS), async & concurrency (async/await, Starlette, BackgroundTasks, WebSocket, SSE/streaming), testing (TestClient, pytest, httpx, mocking), production deployment & scaling (uvicorn/gunicorn, Docker, optimization), generative-AI services (model serving, streaming, concurrency), and microservice/GraphQL/OpenAPI patterns. MUST load when fastapi is in pyproject.toml/requirements.txt or .py files import fastapi. For Python language/tooling fundamentals (uv/ruff/mypy, packaging, non-FastAPI patterns), use lang:developing-python. For REST/HTTP-spec design, versioning, and API test strategy, use developing-web-apis. For Node.js/Fastify backend services, use building-nodejs-services.
development
studying(スタディング, member.studying.jp)のコースレッスン一覧URLから、配下の「スマート問題集」 「セレクト過去問集(学科試験対策・実技試験対策)」の全問題(問題文・選択肢・正解・解説)を科目単位で 取得し、1科目1JSONファイルに保存する。出力は creating-flashcards スキルへ渡して科目ごとに Anki フラッシュカード化できる。 Use when studying のコースレッスン一覧URL(https://member.studying.jp/course/id/<course_id>/ 形式) を渡され「問題を全部保存したい」「Anki カードにしたい」等と言われたとき。 補足トリガー: studying, スタディング, 資格試験, スマート問題集, セレクト過去問集, 問題集, JSON 保存, Anki 連携。 ブラウザ操作自体の汎用ガイドは web:automating-browser、E2E テストは web:testing-e2e-with-playwright を使う。本スキルは studying 専用の収集ワークフロー + bundled script(scripts/collect-studying.sh) +ログイン認証を提供する。
development
Whizlabs のコース practice test 一覧URLから、配下の全クイズ(Free Test・Practice Test 1〜N 等)を practice mode で巡回し、各問題(問題文・選択肢・正解・解説・参考資料)を取得して 1 クイズ 1 JSON ファイルに 保存する。出力は creating-flashcards スキルへ渡してクイズごとに Anki フラッシュカード化できる。 Use when Whizlabs のコースURL(/learn/course/<slug>/<course-id>/pt 形式)を渡され 「問題を全部保存したい」「Anki カードにしたい」等と言われたとき。 補足トリガー: whizlabs, ホイズラボ, 資格試験, 問題集, practice test, quiz 収集, JSON 保存, Anki 連携。 ブラウザ操作自体の汎用ガイドは web:automating-browser、E2E テストは web:testing-e2e-with-playwright を使う。 本スキルは Whizlabs 専用の収集ワークフロー + bundled script(scripts/collect-whizlabs.sh)+ ログイン認証(agent-browser Auth Vault)を提供する。
development
Guides production Flutter app development with Dart targeting iOS, Android, web, and desktop from a single codebase, including project setup, the widget system (Stateless/Stateful, Material and Cupertino), layout, theming and animation, state management (setState, Provider, Riverpod, BLoC/Cubit, Redux, GetX), navigation and routing (Navigator, go_router, auto_route), networking and backends (http, dio, REST, Firebase, GraphQL), local persistence, responsive multi-platform design, architecture patterns (Clean Architecture, BLoC, MVVM), the pub.dev package ecosystem, widget and integration testing, performance optimization, and build and store release. REQUIRED when creating, implementing, modifying, testing, or shipping a Flutter app, or when pubspec.yaml lists the flutter SDK. For the Dart language itself (types, null safety, OOP, async, collections), use developing-dart. For native iOS/iPadOS apps in Swift/SwiftUI, use developing-ios-apps. For Apple HIG UI/UX decisions, use applying-apple-hig.