Comprehensive Firebase skill for TypeScript/Next.js 16 projects...
This skill provides expert guidance for implementing and troubleshooting Firebase services in TypeScript/Next.js 15 applications. It covers the complete Firebase ecosystem with focus on real-world pain points and production-ready patterns.
Core Services Covered:
Use this skill when working with Firebase in TypeScript/Next.js 15 projects, especially for:
Initial Setup & Configuration
Security & Rules
Push Notifications
Cloud Functions
Troubleshooting
Data Consistency
Firestore Client Operations
Security & Bot Protection
Implement secure authentication with email/password and Google Sign-In providers.
Common Tasks:
Reference File: references/authentication.md
Key Patterns:
// Email/Password Sign Up with verification
const { success, error } = await signUpWithEmail(email, password);
if (success) {
await sendEmailVerification(user);
}
// Google Sign-In with error handling
const { success, error } = await signInWithGoogle();
// Custom action URLs setup in Firebase Console
// https://meuapp.com/__/auth/action
Configure security rules, create indexes, and implement type-safe queries with the Client SDK.
Common Tasks:
Reference Files:
references/firestore-client.md - Client SDK operations, queries, aggregations, vector searchreferences/firestore-security-rules.md - Security rules patterns, indexes, troubleshootingKey Patterns:
// CRUD Operations
import { collection, addDoc, getDoc, updateDoc, deleteDoc, doc } from 'firebase/firestore'
// Create with auto ID
const docRef = await addDoc(collection(db, 'users'), { name: 'Alice' })
// Read document
const docSnap = await getDoc(doc(db, 'users', userId))
if (docSnap.exists()) {
const data = docSnap.data()
}
// Aggregation queries (cost-efficient)
import { getAggregateFromServer, count, sum, average } from 'firebase/firestore'
const snapshot = await getAggregateFromServer(
collection(db, 'orders'),
{
totalOrders: count(),
totalRevenue: sum('amount'),
averageOrder: average('amount')
}
)
// Vector search for AI/ML
const vectorQuery = query(
collection(db, 'products'),
{
findNearest: {
vectorField: 'embedding',
queryVector: await generateEmbedding(searchQuery),
limit: 10,
distanceMeasure: 'COSINE'
}
}
)
// Real-time listener
const unsubscribe = onSnapshot(doc(db, 'users', userId), (doc) => {
console.log('Current data:', doc.data())
})
// Firestore Lite for SSR (Next.js Server Components)
import { getFirestore, getDocs } from 'firebase/firestore/lite'
const snapshot = await getDocs(collection(db, 'posts'))
Security Rules:
// Owner-based security rule
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
// Index for complex query (firestore.indexes.json)
{
"indexes": [{
"collectionGroup": "posts",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "authorId", "order": "ASCENDING" },
{ "fieldPath": "createdAt", "order": "DESCENDING" }
]
}]
}
Handle file uploads/downloads with proper security rules.
Common Tasks:
Reference File: references/storage.md
Key Patterns:
// Upload with progress
const { url, error } = await uploadWithProgress(
file,
`users/${userId}/photos/${filename}`,
(progress) => setProgress(progress)
);
// Storage security rule
match /users/{userId}/{allPaths=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024;
}
Create HTTP functions, callable functions, and Firestore triggers with proper CORS configuration.
Common Tasks:
Reference File: references/cloud-functions-v2.md
Key Patterns:
// HTTP function with CORS
export const api = onRequest(
{ cors: true, region: 'us-central1' },
async (req, res) => {
res.json({ message: 'Hello' });
}
);
// Callable function with validation
export const sendMessage = onCall<SendMessageData>(
async (request) => {
if (!request.auth) {
throw new HttpsError('unauthenticated', 'Login required');
}
// Process request
}
);
Configure Firebase Cloud Messaging with VAPID keys, service workers, and troubleshoot common issues.
Common Tasks:
Reference File: references/push-notifications.md
Critical Setup Checklist:
.envpublic/firebase-messaging-sw.jsKey Patterns:
// Request permission and get token
const token = await getToken(messaging, { vapidKey: VAPID_KEY });
if (token) {
await saveTokenToFirestore(userId, token);
}
// Service worker (public/firebase-messaging-sw.js)
importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-messaging-compat.js');
firebase.initializeApp({ /* config */ });
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
self.registration.showNotification(payload.notification.title, {
body: payload.notification.body,
});
});
Initialize Firebase Admin SDK properly in Next.js for server-side operations.
Common Tasks:
Reference File: references/firebase-admin-sdk.md
Key Patterns:
// Initialize Admin SDK (singleton pattern)
import { initializeApp, getApps, cert } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';
if (!getApps().length) {
initializeApp({
credential: cert({
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
}),
});
}
// Set custom claims
await getAuth().setCustomUserClaims(userId, { admin: true });
Protect your Firebase resources from bots, scrapers, and abusive traffic with App Check.
Common Tasks:
Reference File: references/app-check.md
Key Patterns:
// Client-side initialization (Next.js 16 App Router)
'use client'
import { initializeAppCheck, ReCaptchaEnterpriseProvider } from 'firebase/app-check'
export function AppCheckProvider({ children }) {
useEffect(() => {
if (typeof window === 'undefined') return
if (process.env.NODE_ENV === 'development') {
self.FIREBASE_APPCHECK_DEBUG_TOKEN = process.env.NEXT_PUBLIC_APP_CHECK_DEBUG_TOKEN
}
initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider(SITE_KEY),
isTokenAutoRefreshEnabled: true, // CRITICAL
})
}, [])
return <>{children}</>
}
// Standard tokens (reusable)
import { getToken } from 'firebase/app-check'
const token = await getToken(appCheck)
// Limited-use tokens (replay protection for payments/critical ops)
import { getLimitedUseToken } from 'firebase/app-check'
const limitedToken = await getLimitedUseToken(appCheck)
// Cloud Functions with replay protection
export const deleteAccount = onCall(
{
enforceAppCheck: true,
consumeAppCheckToken: true, // Prevents replay attacks
},
async (request) => {
if (!request.app) throw new Error('App Check required')
// Token is consumed - cannot be reused
return { success: true }
}
)
// Firestore Security Rules with App Check
match /posts/{postId} {
allow read: if request.auth != null && request.app != null;
allow write: if request.auth != null && request.app != null;
}
// Admin SDK verification (custom backends)
import { getAppCheck } from 'firebase-admin/app-check'
const appCheckToken = req.header('X-Firebase-AppCheck')
try {
const claims = await getAppCheck().verifyToken(appCheckToken)
// Check for replay attacks
if (claims.alreadyConsumed) {
throw new Error('Token replay attack detected!')
}
console.log('App ID:', claims.app_id)
} catch (error) {
// Invalid token
}
Critical Setup Checklist:
isTokenAutoRefreshEnabled: truerequest.app != nullenforceAppCheck: trueSymptoms: Token not generated, notifications not appearing, service worker errors
Checklist:
.env/firebase-messaging-sw.jsReference: See detailed troubleshooting in references/push-notifications.md
Key Point: Most "CORS errors" are actually JavaScript errors in the function!
Debug Steps:
cors: true to function configReference: See CORS configuration in references/cloud-functions-v2.md
Common Causes:
Debug:
request.auth != null is first conditionReference: See security rules patterns in references/firestore-security-rules.md
Common Issues:
isActive and active both presentSolution:
Reference: See validation patterns in references/firestore-security-rules.md
Symptoms: "App Check token is invalid", high rejection rates, requests blocked
Checklist:
isTokenAutoRefreshEnabled: true is setCommon Causes:
typeof window === 'undefined')Reference: See complete troubleshooting in references/app-check.md
Symptoms: Slow queries, high read costs, timeout errors
Solutions:
Use aggregation queries instead of getDocs():
// ❌ Expensive - reads every document
const snapshot = await getDocs(collection(db, 'orders'))
const total = snapshot.docs.reduce((sum, doc) => sum + doc.data().amount, 0)
// ✅ Cost-efficient - uses index entries
const snapshot = await getAggregateFromServer(
collection(db, 'orders'),
{ total: sum('amount') }
)
Create composite indexes for complex queries
Use cursor-based pagination (not offset)
Enable offline persistence for better UX
Use Firestore Lite for SSR to reduce bundle size
Reference: See performance optimization in references/firestore-client.md
Always define interfaces for Firestore documents:
interface User {
uid: string;
email: string;
displayName: string;
isActive: boolean; // NOT 'active' - be consistent!
createdAt: Date;
}
Use proper naming for Next.js:
# Client-side (public)
NEXT_PUBLIC_FIREBASE_API_KEY=...
NEXT_PUBLIC_FIREBASE_PROJECT_ID=...
NEXT_PUBLIC_VAPID_KEY=...
# Server-side only (private)
FIREBASE_PRIVATE_KEY=...
FIREBASE_CLIENT_EMAIL=...
Firestore Optimization:
limit() and startAfter() (NOT offset)persistentLocalCache() for better UXGeneral Firebase:
Firebase security works best with multiple layers:
┌────────────────────────────────┐
│ 1. App Check (bot/device) │ ← Validates app authenticity
├────────────────────────────────┤
│ 2. Firebase Auth (user) │ ← Validates user identity
├────────────────────────────────┤
│ 3. Security Rules (data) │ ← Validates permissions
├────────────────────────────────┤
│ 4. Rate Limiting (abuse) │ ← Prevents abuse
├────────────────────────────────┤
│ 5. Cloud Armor (DDoS) │ ← Infrastructure protection
└────────────────────────────────┘
Implementation:
// Firestore Rules - ALL layers
match /users/{userId} {
allow read, write: if request.auth != null // Layer 2: Auth
&& request.auth.uid == userId // Layer 3: Authorization
&& request.app != null; // Layer 1: App Check
}
// Cloud Functions - Replay protection for critical ops
export const processPayment = onCall(
{
enforceAppCheck: true, // Layer 1
consumeAppCheckToken: true, // Replay protection
},
async (request) => {
if (!request.auth) throw new Error('Unauthorized') // Layer 2
// Process payment...
}
)
The skill includes comprehensive reference documentation for each Firebase service:
Load these references as needed when implementing specific features or debugging issues.
| Task | Reference File |
|---|---|
| Login/signup implementation | authentication.md |
| Custom domain for email links | authentication.md |
| CRUD operations in Firestore | firestore-client.md |
| Aggregation queries (count, sum, avg) | firestore-client.md |
| Vector search / AI embeddings | firestore-client.md |
| Real-time listeners / offline cache | firestore-client.md |
| Firestore Lite for SSR | firestore-client.md |
| Firestore security rules or indexes | firestore-security-rules.md |
| Permission denied errors | firestore-security-rules.md |
| File upload/download | storage.md |
| Cloud Function creation | cloud-functions-v2.md |
| CORS errors | cloud-functions-v2.md |
| Push notifications setup | push-notifications.md |
| VAPID configuration | push-notifications.md |
| Server-side operations | firebase-admin-sdk.md |
| Custom claims/roles | firebase-admin-sdk.md |
| Bot protection / App Check setup | app-check.md |
| reCAPTCHA Enterprise configuration | app-check.md |
| Replay protection (limited-use tokens) | app-check.md |
| App Check with Next.js 16 SSR | app-check.md |
| App Check monitoring and metrics | app-check.md |
This Firebase skill works alongside:
When a task involves both Firebase services AND one of these specialized areas, use both skills together.