Claude-skill-registry firebase-integration
Firebase integration for authentication, Firestore database, and real-time data synchronization. Use when working with Firebase services in the LiveMetro app.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/firebase-integration" ~/.claude/skills/majiayu000-claude-skill-registry-firebase-integration && rm -rf "$T"
manifest:
skills/data/firebase-integration/SKILL.mdsource content
Firebase Integration Guidelines
When to Use This Skill
- Setting up Firebase authentication
- Querying Firestore collections
- Implementing real-time data subscriptions
- Managing user data in Firebase
- Handling Firebase errors
Core Services
1. Firestore Database Structure
Collections: - subwayLines/ # Line metadata (color, name) - stations/ # Station info with coordinates - trains/ # Real-time train positions - trainDelays/ # Delay and disruption alerts - congestionData/ # Train car congestion levels - users/ # User preferences and favorites
2. Authentication Pattern
import { auth } from '@/config/firebase'; import { signInAnonymously, onAuthStateChanged } from 'firebase/auth'; // Anonymous authentication for basic features const signIn = async () => { try { const result = await signInAnonymously(auth); return result.user; } catch (error) { console.error('Auth error:', error); throw error; } }; // Listen to auth state changes onAuthStateChanged(auth, (user) => { if (user) { // User is signed in } else { // User is signed out } });
3. Firestore Query Pattern
import { firestore } from '@/config/firebase'; import { collection, query, where, getDocs, orderBy, limit } from 'firebase/firestore'; // Basic query const getStations = async (lineId: string) => { try { const stationsRef = collection(firestore, 'stations'); const q = query( stationsRef, where('lineId', '==', lineId), orderBy('sequence') ); const snapshot = await getDocs(q); return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); } catch (error) { console.error('Firestore query error:', error); return []; } };
4. Real-time Subscription Pattern
import { onSnapshot } from 'firebase/firestore'; // Subscribe to real-time updates const subscribeToTrains = ( stationId: string, callback: (trains: Train[]) => void ): (() => void) => { const trainsRef = collection(firestore, 'trains'); const q = query( trainsRef, where('currentStationId', '==', stationId) ); const unsubscribe = onSnapshot( q, (snapshot) => { const trains = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() } as Train)); callback(trains); }, (error) => { console.error('Snapshot error:', error); } ); return unsubscribe; // Return cleanup function }; // Usage in component useEffect(() => { const unsubscribe = subscribeToTrains(stationId, setTrains); return () => unsubscribe(); // Cleanup on unmount }, [stationId]);
5. Error Handling
import { FirebaseError } from 'firebase/app'; const handleFirebaseError = (error: unknown): string => { if (error instanceof FirebaseError) { switch (error.code) { case 'permission-denied': return 'You do not have permission to access this data'; case 'unavailable': return 'Firebase service is temporarily unavailable'; case 'unauthenticated': return 'Please sign in to continue'; default: return error.message; } } return 'An unexpected error occurred'; };
Service Layer Pattern
trainService.ts Example
class TrainService { private static instance: TrainService; static getInstance(): TrainService { if (!TrainService.instance) { TrainService.instance = new TrainService(); } return TrainService.instance; } async getTrainsByStation(stationId: string): Promise<Train[]> { // Implementation } subscribeToTrainUpdates( stationId: string, callback: (trains: Train[]) => void ): () => void { // Implementation with cleanup } } export const trainService = TrainService.getInstance();
Data Caching Strategy
Multi-tier fallback
/** * Priority: Seoul API → Firebase → Local Cache */ const getTrainData = async (stationId: string): Promise<Train[]> => { try { // 1. Try Seoul API (primary source) const apiData = await seoulApi.getArrivals(stationId); if (apiData.length > 0) { await cacheData(stationId, apiData); return apiData; } } catch (error) { console.log('Seoul API failed, trying Firebase'); } try { // 2. Fallback to Firebase const fbData = await trainService.getTrainsByStation(stationId); if (fbData.length > 0) { return fbData; } } catch (error) { console.log('Firebase failed, using cache'); } // 3. Last resort: Local cache return await getCachedData(stationId); };
Security Rules Considerations
Firestore Rules Pattern
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Public read for subway data match /stations/{stationId} { allow read: if true; allow write: if false; // Only through admin } // User-specific data match /users/{userId} { allow read, write: if request.auth.uid == userId; } } }
Best Practices
1. Subscription Cleanup
Always clean up Firebase subscriptions to prevent memory leaks:
useEffect(() => { const unsubscribe = subscribeToData(callback); return () => unsubscribe(); }, [dependencies]);
2. Batch Operations
For multiple writes, use batch operations:
import { writeBatch } from 'firebase/firestore'; const batch = writeBatch(firestore); batch.set(docRef1, data1); batch.update(docRef2, data2); await batch.commit();
3. Offline Persistence
Handle offline scenarios gracefully:
import { enableNetwork, disableNetwork } from 'firebase/firestore'; // Firestore automatically caches data for offline use // Monitor connectivity and inform users
Common Pitfalls to Avoid
- ❌ Not cleaning up subscriptions (memory leaks)
- ❌ Querying without indexes (slow performance)
- ❌ Exposing Firebase config in client code (security)
- ❌ Not handling permission errors
- ❌ Over-fetching data (use limit and pagination)
Testing
- Mock Firebase services in tests
- Test offline scenarios
- Verify subscription cleanup
- Test error handling paths