Back to list
karthikeyanp-dev

firebase-integration

by karthikeyanp-dev

0🍴 0📅 Jan 22, 2026

SKILL.md


name: firebase-integration description: Guide for Firebase setup, Firestore operations, and client-side data management in TrainTrack

This skill provides comprehensive guidance for working with Firebase, including initialization, Firestore client SDK usage, security rules, and environment configuration.

Firebase Initialization

Singleton Pattern: Firebase is initialized once using a singleton pattern to prevent multiple app instances.

Configuration File: src/lib/firebase.ts

  • Validates Firebase config on initialization
  • Logs configuration status for debugging
  • Exports initialized app and auth instances

Environment Variables Required:

NEXT_PUBLIC_FIREBASE_API_KEY=<key>
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=<domain>
NEXT_PUBLIC_FIREBASE_PROJECT_ID=<project_id>
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=<bucket>
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=<sender_id>
NEXT_PUBLIC_FIREBASE_APP_ID=<app_id>
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=<measurement_id>
NEXT_PUBLIC_FIREBASE_DATABASE_ID=<database_id> # Optional

Note: NEXT_PUBLIC_ prefixed variables are exposed to the browser.

Firestore Client SDK Usage

TrainTrack uses Client-Side Rendering (CSR) with direct Firestore access from the browser.

Core Client Methods

Collection Operations:

import { collection, getDocs, addDoc, query, where } from 'firebase/firestore';

// Get all documents
const snapshot = await getDocs(collection(db, 'bookings'));

// Query with filters
const q = query(collection(db, 'bookings'), where('status', '==', 'pending'));
const snapshot = await getDocs(q);

Document Operations:

import { doc, getDoc, updateDoc, deleteDoc } from 'firebase/firestore';

// Get single document
const docRef = doc(db, 'bookings', bookingId);
const docSnap = await getDoc(docRef);

// Update document
await updateDoc(docRef, { status: 'completed' });

// Delete document
await deleteDoc(docRef);

Real-time Updates:

import { onSnapshot } from 'firebase/firestore';

const unsubscribe = onSnapshot(collection(db, 'bookings'), (snapshot) => {
  snapshot.forEach((doc) => {
    console.log(doc.data());
  });
});

// Clean up on unmount
unsubscribe();

Firestore Collections

Bookings Collection (bookings/)

Stores main booking records with:

  • Source and destination stations
  • Journey date (Firestore Timestamp)
  • Passenger details array
  • Train number and class
  • IRCTC account reference
  • Status tracking

IRCTC Accounts Collection (irctcAccounts/)

Stores IRCTC credentials and wallet information:

  • Username and encrypted password
  • Wallet balance tracking
  • Account status
  • Linked bookings

Booking Records Collection (bookingRecords/)

Stores completion/payment records:

  • Reference to original booking
  • Payment method and amount
  • Completion timestamp
  • Handler information

Handlers Collection (handlers/)

Stores handler/agent names for assignment.

Date Handling

Critical Pattern: Firestore stores dates as Timestamp objects. Always convert to ISO strings for client compatibility:

// When reading from Firestore
journeyDate: booking.journeyDate?.toDate?.()?.toISOString() || booking.journeyDate

// When writing to Firestore (optional, Firestore handles Dates)
journeyDate: new Date(journeyDateString)

React Query Integration

Custom Hooks Pattern: Combine Firestore client SDK with React Query for caching and automatic refetching.

Example Structure:

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { collection, getDocs, addDoc, updateDoc } from 'firebase/firestore';

export function useBookings() {
  return useQuery({
    queryKey: ['bookings'],
    queryFn: async () => {
      const snapshot = await getDocs(collection(db, 'bookings'));
      return snapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
      }));
    },
    staleTime: 60000, // 60 seconds
  });
}

export function useUpdateBooking() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: async ({ id, data }) => {
      await updateDoc(doc(db, 'bookings', id), data);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['bookings'] });
    },
  });
}

Key Hooks: src/hooks/

  • useBookings.ts - Bookings data with infinite scroll
  • useAccounts.ts - IRCTC account management
  • useBookingRecords.ts - Completion records
  • useHandlers.ts - Handler management

Security Rules

Current Status: Rules allow unrestricted read/write for development.

Production Requirements: In production, add:

  • Authentication checks (request.auth != null)
  • User-specific access rules
  • Data validation

Configuration File: firestore.rules

Example production rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /bookings/{booking} {
      allow read: if request.auth != null;
      allow write: if request.auth != null && 
        request.auth.uid == resource.data.userId;
    }
  }
}

Firebase Configuration Files

Project Config: .firebaserc

{
  "projects": {
    "default": "your-project-id"
  }
}

Hosting Config: firebase.json

{
  "hosting": {
    "public": "out",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

Firestore Rules: firestore.rules

Client SDK Setup

Installation: Dependencies in package.json

  • firebase - Firebase client SDK
  • @tanstack/react-query - Data fetching and caching

Initialization: src/lib/firebase.ts

  • Singleton pattern prevents multiple app instances
  • Config validation on startup
  • Exports db, auth, app instances

Usage Pattern:

import { db } from '@/lib/firebase';
import { collection, getDocs } from 'firebase/firestore';

const snapshot = await getDocs(collection(db, 'bookings'));

Common Patterns

Adding a Document

import { collection, addDoc } from 'firebase/firestore';
import { db } from '@/lib/firebase';

const docRef = await addDoc(collection(db, 'bookings'), {
  source: 'Station A',
  destination: 'Station B',
  status: 'pending',
  createdAt: new Date(),
});

Updating a Document

import { doc, updateDoc } from 'firebase/firestore';

await updateDoc(doc(db, 'bookings', bookingId), {
  status: 'completed',
  updatedAt: new Date(),
});

Querying with Filters

import { collection, query, where, getDocs } from 'firebase/firestore';

const q = query(
  collection(db, 'bookings'),
  where('status', '==', 'pending'),
  where('journeyDate', '>=', startDate)
);
const snapshot = await getDocs(q);

Real-time Listener

import { collection, onSnapshot } from 'firebase/firestore';

const unsubscribe = onSnapshot(
  query(collection(db, 'bookings'), where('status', '==', 'pending')),
  (snapshot) => {
    const bookings = snapshot.docs.map(doc => ({
      id: doc.id,
      ...doc.data()
    }));
    // Update state or invalidate React Query
  }
);

Troubleshooting

Timestamp Conversion Errors:

  • Error: "Cannot serialize a BigInt" or similar
  • Solution: Always convert Firestore Timestamps with .toDate().toISOString()

Multiple App Instances:

  • Error: "Firebase: Firebase App named '[DEFAULT]' already exists"
  • Solution: Use singleton pattern in firebase.ts

Permission Denied Errors:

  • Check Firestore rules in firestore.rules
  • Verify Firebase config in environment variables
  • Ensure collection names match exactly

Real-time Updates Not Working:

  • Verify onSnapshot is properly set up
  • Check that query is valid
  • Ensure component properly cleans up listeners

Key Files Reference

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon