Files
LearnIT/docs/FIREBASE_CONFIGURATION.md
2026-05-06 20:16:11 +01:00

31 KiB

Firebase Configuration - AI Study Assistant

🔥 COMPLETE FIREBASE SETUP GUIDE


📋 OVERVIEW

This document provides comprehensive instructions for setting up Firebase for the AI Study Assistant project, including authentication, database, storage, cloud functions, and security configurations.


🚀 STEP 1: FIREBASE PROJECT SETUP

1.1 Create Firebase Project

  1. Go to Firebase Console

  2. Create New Project

    # Using Firebase CLI (recommended)
    firebase projects create teachit-ai-assistant
    firebase use teachit-ai-assistant
    
  3. Configure Project Settings

    • Project ID: teachit-ai-assistant
    • Display Name: AI Study Assistant
    • Organization: Select appropriate organization

1.2 Enable Required Services

Firebase Services to Enable:

  • Firebase Authentication
  • Cloud Firestore
  • Cloud Storage
  • Cloud Functions
  • Firebase Analytics
  • Firebase Crashlytics
  • Firebase Performance Monitoring
  • Firebase Remote Config

Enable Commands:

# Enable Authentication
firebase auth --enable

# Enable Firestore
firebase firestore:databases:create

# Enable Storage
firebase storage:buckets:create teachit-content

# Enable Functions
firebase functions:config:set

# Enable Analytics (automatically enabled)

🔐 STEP 2: AUTHENTICATION CONFIGURATION

2.1 Firebase Auth Setup

Sign-in Methods to Enable:

  1. Email/Password

    • Go to Authentication → Sign-in method
    • Enable Email/Password
    • Set up email templates
  2. Google Sign-In

    • Enable Google provider
    • Configure OAuth consent screen
    • Add authorized domains
  3. Apple Sign-In (if supporting iOS)

    • Enable Apple provider
    • Configure with Apple Developer account

Authentication Configuration:

// Firebase Console → Authentication → Settings
{
  "sign_in_method": {
    "email": true,
    "google": true,
    "apple": false
  },
  "password_policy": {
    "min_length": 6,
    "require_uppercase": false,
    "require_lowercase": false,
    "require_numbers": false,
    "require_special_chars": false
  },
  "email_verification": {
    "required": true,
    "template": "default"
  }
}

2.2 User Management Configuration

Custom Claims Setup:

// Cloud Function to set custom claims
exports.setCustomClaims = functions.auth.user().onCreate(async (user) => {
  const customClaims = {
    role: 'student', // Default role
    schoolId: 'default',
    permissions: ['basic_access']
  };
  
  await admin.auth().setCustomUserClaims(user.uid, customClaims);
});

🗄️ STEP 3: FIRESTORE DATABASE SETUP

3.1 Database Configuration

Create Firestore Database:

  1. Go to Firestore Database
  2. Create database in test mode (initially)
  3. Choose location (e.g., europe-west1)
  4. Set up security rules

Database Structure:

// Collections Structure
schools/{schoolId}
├── users/{userId}
├── learningStates/{studentId}
├── contentChunks/{chunkId}
├── quizzes/{quizId}
├── quizAttempts/{attemptId}
├── interactions/{interactionId}
└── auditLogs/{logId}

3.2 Security Rules

Complete Security Rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Helper functions
    function isAuthenticated() {
      return request.auth != null;
    }
    
    function isSameSchool(schoolId) {
      return isAuthenticated() && 
             get(/databases/$(database)/documents/users/$(request.auth.uid)).data.schoolId == schoolId;
    }
    
    function hasRole(role) {
      return isAuthenticated() && 
             get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == role;
    }
    
    function isOwner(userId) {
      return isAuthenticated() && request.auth.uid == userId;
    }
    
    // Schools collection - admin only
    match /schools/{schoolId} {
      allow read, write: if hasRole('admin');
      allow create: if hasRole('admin') && request.resource.data.keys().hasAll(['name', 'email']);
    }
    
    // Users collection
    match /users/{userId} {
      allow read: if isAuthenticated() && 
                     (isOwner(userId) || isSameSchool(resource.data.schoolId));
      allow write: if isAuthenticated() && 
                     (isOwner(userId) || hasRole('admin'));
      allow create: if isAuthenticated() && 
                     isOwner(userId) &&
                     request.resource.data.keys().hasAll(['schoolId', 'role', 'email']);
    }
    
    // Learning states - students own their data, teachers can read class data
    match /learningStates/{studentId} {
      allow read: if isAuthenticated() && 
                     (isOwner(studentId) || isSameSchool(resource.data.schoolId));
      allow write: if isAuthenticated() && 
                     (isOwner(studentId) || hasRole('teacher') || hasRole('admin'));
      allow create: if isAuthenticated() && 
                     isOwner(studentId);
    }
    
    // Content chunks - authenticated users from same school
    match /contentChunks/{chunkId} {
      allow read: if isAuthenticated() && isSameSchool(resource.data.schoolId);
      allow write: if isAuthenticated() && 
                     (hasRole('teacher') || hasRole('admin')) &&
                     isSameSchool(resource.data.schoolId);
      allow create: if isAuthenticated() && 
                     hasRole('teacher') &&
                     isSameSchool(request.resource.data.schoolId);
      allow update: if isAuthenticated() && 
                     (hasRole('teacher') || hasRole('admin')) &&
                     isSameSchool(resource.data.schoolId);
      allow delete: if isAuthenticated() && 
                     (hasRole('teacher') || hasRole('admin')) &&
                     isSameSchool(resource.data.schoolId);
    }
    
    // Quizzes
    match /quizzes/{quizId} {
      allow read: if isAuthenticated() && isSameSchool(resource.data.schoolId);
      allow write: if isAuthenticated() && 
                     (request.auth.uid == resource.data.teacherId || hasRole('admin'));
      allow create: if isAuthenticated() && 
                     hasRole('teacher') &&
                     request.auth.uid == request.resource.data.teacherId &&
                     isSameSchool(request.resource.data.schoolId);
    }
    
    // Quiz attempts
    match /quizAttempts/{attemptId} {
      allow read: if isAuthenticated() && 
                     (isOwner(resource.data.studentId) || isSameSchool(resource.data.schoolId));
      allow write: if isAuthenticated() && 
                     (isOwner(resource.data.studentId) || hasRole('teacher'));
      allow create: if isAuthenticated() && 
                     isOwner(resource.data.studentId);
    }
    
    // Interactions
    match /interactions/{interactionId} {
      allow read: if isAuthenticated() && 
                     (isOwner(resource.data.studentId) || hasRole('teacher'));
      allow write: if isAuthenticated() && 
                     (isOwner(resource.data.studentId) || hasRole('teacher'));
      allow create: if isAuthenticated() && 
                     isOwner(resource.data.studentId);
    }
    
    // Audit logs - read only for admins
    match /auditLogs/{logId} {
      allow read: if hasRole('admin');
      allow write: if hasRole('admin');
      allow create: if hasRole('admin');
    }
  }
}

3.3 Indexes Configuration

Create Required Indexes:

// firestore.indexes.json
{
  "indexes": [
    {
      "collectionGroup": "contentChunks",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "schoolId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "concept",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "pedagogy.difficulty",
          "order": "ASCENDING"
        }
      ]
    },
    {
      "collectionGroup": "contentChunks",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "schoolId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "subject",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "unit",
          "order": "ASCENDING"
        }
      ]
    },
    {
      "collectionGroup": "contentChunks",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "schoolId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "metadata.qualityScore",
          "order": "DESCENDING"
        },
        {
          "fieldPath": "createdAt",
          "order": "DESCENDING"
        }
      ]
    },
    {
      "collectionGroup": "interactions",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "studentId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "createdAt",
          "order": "DESCENDING"
        }
      ]
    },
    {
      "collectionGroup": "quizAttempts",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "studentId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "completedAt",
          "order": "DESCENDING"
        }
      ]
    },
    {
      "collectionGroup": "quizAttempts",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "quizId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "score",
          "order": "DESCENDING"
        }
      ]
    },
    {
      "collectionGroup": "learningStates",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "schoolId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "metadata.dailyActiveDays",
          "order": "DESCENDING"
        }
      ]
    }
  ],
  "fieldOverrides": []
}

Deploy Indexes:

firebase deploy --only firestore:indexes

📦 STEP 4: CLOUD STORAGE SETUP

4.1 Storage Bucket Configuration

Create Storage Buckets:

# Main content bucket
firebase storage:buckets:create teachit-content

# User avatars bucket
firebase storage:buckets:create teachit-avatars

# Temporary files bucket
firebase storage:buckets:create teachit-temp

4.2 Storage Security Rules

Complete Storage Rules:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    // Helper functions
    function isAuthenticated() {
      return request.auth != null;
    }
    
    function isSameSchool(schoolId) {
      return isAuthenticated() && 
             get(/databases/$(database)/documents/users/$(request.auth.uid)).data.schoolId == schoolId;
    }
    
    function hasRole(role) {
      return isAuthenticated() && 
             get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == role;
    }
    
    // Content files - teachers can upload, authenticated users can read
    match /content/{schoolId}/{allPaths=**} {
      allow read: if isAuthenticated() && isSameSchool(schoolId);
      allow write: if isAuthenticated() && 
                     (hasRole('teacher') || hasRole('admin')) &&
                     isSameSchool(schoolId);
      allow create: if isAuthenticated() && 
                     (hasRole('teacher') || hasRole('admin')) &&
                     isSameSchool(schoolId) &&
                     request.resource.size < 50 * 1024 * 1024; // 50MB limit
    }
    
    // User avatars - users can upload their own
    match /avatars/{userId}/{fileName} {
      allow read: if isAuthenticated();
      allow write: if isAuthenticated() && 
                     request.auth.uid == userId &&
                     request.resource.size < 5 * 1024 * 1024; // 5MB limit
    }
    
    // Temporary files - authenticated users can upload
    match /temp/{userId}/{fileName} {
      allow read: if isAuthenticated() && request.auth.uid == userId;
      allow write: if isAuthenticated() && 
                     request.auth.uid == userId &&
                     request.resource.size < 10 * 1024 * 1024; // 10MB limit
      allow delete: if isAuthenticated() && request.auth.uid == userId;
    }
  }
}

STEP 5: CLOUD FUNCTIONS SETUP

5.1 Functions Configuration

Initialize Functions:

# Initialize functions in project
firebase init functions

# Choose TypeScript
# Choose ESLint
# Choose npm

Package.json Configuration:

{
  "name": "teachit-functions",
  "description": "Cloud Functions for AI Study Assistant",
  "scripts": {
    "build": "tsc",
    "build:watch": "tsc --watch",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "18"
  },
  "main": "lib/index.js",
  "dependencies": {
    "@google-cloud/firestore": "^6.7.0",
    "@google-cloud/storage": "^6.11.0",
    "firebase-admin": "^11.10.1",
    "firebase-functions": "^4.4.1",
    "openai": "^4.20.1",
    "anthropic": "^0.6.3",
    "sentence-transformers": "^0.0.1",
    "faiss-node": "^0.5.1",
    "pdf-parse": "^1.1.1",
    "mammoth": "^1.6.0",
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "helmet": "^7.0.0",
    "express-rate-limit": "^6.10.0",
    "joi": "^17.9.2",
    "winston": "^3.10.0",
    "dotenv": "^16.3.1",
    "uuid": "^9.0.0",
    "bcryptjs": "^2.4.3",
    "jsonwebtoken": "^9.0.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/cors": "^2.8.13",
    "@types/uuid": "^9.0.2",
    "@types/bcryptjs": "^2.4.2",
    "@types/jsonwebtoken": "^9.0.2",
    "typescript": "^5.1.6",
    "@typescript-eslint/eslint-plugin": "^6.2.1",
    "@typescript-eslint/parser": "^6.2.1",
    "eslint": "^8.46.0",
    "eslint-config-google": "^0.14.0",
    "eslint-plugin-import": "^2.28.0",
    "firebase-functions-test": "^3.1.0"
  }
}

5.2 Environment Configuration

Environment Variables:

# functions/.env
OPENAI_API_KEY=your_openai_api_key
ANTHROPIC_API_KEY=your_anthropic_api_key
FIREBASE_PROJECT_ID=teachit-ai-assistant
STORAGE_BUCKET=teachit-content.appspot.com
NODE_ENV=production
LOG_LEVEL=info

Functions Configuration:

// functions/config/firebase.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

// Initialize Firebase Admin
admin.initializeApp();

// Configuration
export const config = {
  firestore: admin.firestore(),
  storage: admin.storage(),
  auth: admin.auth(),
  
  // Environment variables
  openaiApiKey: functions.config().openai.api_key,
  anthropicApiKey: functions.config().anthropic.api_key,
  
  // App settings
  maxFileSize: 50 * 1024 * 1024, // 50MB
  maxQuizDuration: 60, // minutes
  defaultBloomLevel: 2,
  
  // Rate limiting
  rateLimits: {
    apiCalls: 100, // per minute
    uploads: 10,    // per minute
    llmCalls: 20,   // per minute
  }
};

5.3 CORS Configuration

CORS Setup:

// functions/middleware/cors.ts
import cors from 'cors';
import { config } from '../config/firebase';

export const corsHandler = cors({
  origin: [
    'http://localhost:3000',
    'https://teachit.web.app',
    'https://teachit.firebaseapp.com'
  ],
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
});

📊 STEP 6: ANALYTICS & MONITORING

6.1 Firebase Analytics Setup

Analytics Configuration:

// Flutter app analytics setup
import 'package:firebase_analytics/firebase_analytics.dart';

class AnalyticsService {
  static FirebaseAnalytics? _analytics;
  
  static FirebaseAnalytics get analytics {
    _analytics ??= FirebaseAnalytics.instance;
    return _analytics!;
  }
  
  static Future<void> logScreenView(String screenName) async {
    await analytics.logScreenView(screenName: screenName);
  }
  
  static Future<void> logEvent(String name, {Map<String, Object>? parameters}) async {
    await analytics.logEvent(name, parameters: parameters);
  }
  
  static Future<void> setUserProperty(String name, String value) async {
    await analytics.setUserProperty(name: name, value: value);
  }
}

Custom Events to Track:

// User engagement events
analytics.logEvent('tutor_question_asked');
analytics.logEvent('quiz_completed');
analytics.logEvent('content_uploaded');

// Learning events
analytics.logEvent('concept_mastered');
analytics.logEvent('misconception_identified');
analytics.logEvent('learning_goal_achieved');

// Performance events
analytics.logEvent('rag_response_generated');
analytics.logEvent('content_processed');
analytics.logEvent('user_session_completed');

6.2 Crashlytics Setup

Error Reporting Configuration:

// Flutter crashlytics setup
import 'package:firebase_crashlytics/firebase_crashlytics.dart';

class CrashlyticsService {
  static Future<void> initialize() async {
    await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
  }
  
  static Future<void> recordError(dynamic error, StackTrace? stackTrace) async {
    await FirebaseCrashlytics.instance.recordError(error, stackTrace);
  }
  
  static Future<void> recordFlutterError(FlutterErrorDetails details) async {
    await FirebaseCrashlytics.instance.recordFlutterError(details);
  }
  
  static Future<void> setUserIdentifier(String userId) async {
    await FirebaseCrashlytics.instance.setUserIdentifier(userId);
  }
}

6.3 Performance Monitoring

Performance Setup:

// Flutter performance monitoring
import 'package:firebase_performance/firebase_performance.dart';

class PerformanceService {
  static Trace? _currentTrace;
  
  static Future<void> startTrace(String traceName) async {
    _currentTrace = await FirebasePerformance.instance.newTrace(traceName);
    await _currentTrace?.start();
  }
  
  static Future<void> stopTrace() async {
    await _currentTrace?.stop();
    _currentTrace = null;
  }
  
  static Future<void> setMetric(String metricName, int value) async {
    await _currentTrace?.setMetric(metricName, value);
  }
}

🔧 STEP 7: REMOTE CONFIGURATION

7.1 Remote Config Setup

Configuration Parameters:

// Firebase Console → Remote Config
{
  "feature_flags": {
    "enable_rag_engine": true,
    "enable_voice_chat": false,
    "enable_analytics": true,
    "enable_crashlytics": true
  },
  "app_config": {
    "max_quiz_questions": 20,
    "max_file_upload_size": 50,
    "session_timeout_minutes": 30,
    "default_language": "en"
  },
  "llm_config": {
    "default_model": "claude-3-5-sonnet-20241022",
    "max_tokens": 500,
    "temperature": 0.7,
    "rate_limit_per_minute": 20
  },
  "ui_config": {
    "theme_mode": "auto",
    "enable_animations": true,
    "enable_haptic_feedback": true,
    "default_font_size": 16
  }
}

Remote Config Service:

// Flutter remote config setup
import 'package:firebase_remote_config/firebase_remote_config.dart';

class RemoteConfigService {
  static FirebaseRemoteConfig? _remoteConfig;
  
  static FirebaseRemoteConfig get remoteConfig {
    _remoteConfig ??= FirebaseRemoteConfig.instance;
    return _remoteConfig!;
  }
  
  static Future<void> initialize() async {
    try {
      await remoteConfig.setConfigSettings(RemoteConfigSettings(
        fetchTimeout: const Duration(minutes: 1),
        minimumFetchInterval: const Duration(hours: 1),
      ));
      
      await remoteConfig.setDefaults({
        'enable_rag_engine': true,
        'max_quiz_questions': 20,
        'session_timeout_minutes': 30,
      });
      
      await remoteConfig.fetchAndActivate();
    } catch (e) {
      print('Failed to initialize remote config: $e');
    }
  }
  
  static bool getBool(String key) {
    return remoteConfig.getBool(key);
  }
  
  static int getInt(String key) {
    return remoteConfig.getInt(key);
  }
  
  static String getString(String key) {
    return remoteConfig.getString(key);
  }
  
  static Future<void> refresh() async {
    try {
      await remoteConfig.fetchAndActivate();
    } catch (e) {
      print('Failed to refresh remote config: $e');
    }
  }
}

📱 STEP 8: FLUTTER FIREBASE CONFIGURATION

8.1 Flutter Firebase Setup

pubspec.yaml Dependencies:

dependencies:
  firebase_core: ^2.24.2
  firebase_auth: ^4.15.3
  cloud_firestore: ^4.13.6
  firebase_storage: ^11.5.6
  firebase_analytics: ^10.7.4
  firebase_messaging: ^14.7.6
  firebase_crashlytics: ^3.4.8
  firebase_remote_config: ^4.4.7
  firebase_performance: ^0.9.3+8

8.2 Firebase Initialization

Main.dart Configuration:

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:firebase_performance/firebase_performance.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  
  // Initialize Firebase services
  await _initializeFirebaseServices();
  
  runApp(MyApp());
}

Future<void> _initializeFirebaseServices() async {
  // Analytics
  await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
  
  // Crashlytics
  await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
  
  // Remote Config
  final remoteConfig = FirebaseRemoteConfig.instance;
  await remoteConfig.setConfigSettings(RemoteConfigSettings(
    fetchTimeout: const Duration(minutes: 1),
    minimumFetchInterval: const Duration(hours: 1),
  ));
  
  // Performance
  await FirebasePerformance.instance.setPerformanceCollectionEnabled(true);
}

8.3 Firebase Configuration Files

Android Configuration:

<!-- android/app/google-services.json -->
<!-- Download from Firebase Console -->

iOS Configuration:

<!-- ios/Runner/GoogleService-Info.plist -->
<!-- Download from Firebase Console -->

🔐 STEP 9: SECURITY BEST PRACTICES

9.1 API Keys Management

Secure API Key Storage:

// Never hardcode API keys in client code
// Use Firebase Remote Config or environment variables

// Cloud Functions environment variables
const openaiApiKey = process.env.OPENAI_API_KEY;
const anthropicApiKey = process.env.ANTHROPIC_API_KEY;

// Firebase Remote Config for client-side keys
final apiKey = RemoteConfigService.getString('api_key');

9.2 Data Validation

Input Validation Functions:

// Cloud Functions validation
import Joi from 'joi';

const userSchema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(6).required(),
  name: Joi.string().min(2).max(50).required(),
  role: Joi.string().valid('student', 'teacher', 'admin').required(),
  schoolId: Joi.string().required(),
});

const contentSchema = Joi.object({
  text: Joi.string().min(100).max(10000).required(),
  concept: Joi.string().required(),
  subject: Joi.string().required(),
  difficulty: Joi.number().min(0).max(1).required(),
});

9.3 Rate Limiting

Rate Limiting Implementation:

// Cloud Functions rate limiting
import rateLimit from 'express-rate-limit';

const apiLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP',
  standardHeaders: true,
  legacyHeaders: false,
});

const uploadLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 10, // limit uploads
  message: 'Too many upload requests',
});

const llmLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 20, // limit LLM calls
  message: 'Too many AI requests',
});

🚀 STEP 10: DEPLOYMENT CONFIGURATION

10.1 Firebase Hosting Setup

firebase.json Configuration:

{
  "hosting": {
    "public": "build/web",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {
        "source": "**/*.@(js|css)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=31536000"
          }
        ]
      },
      {
        "source": "**",
        "headers": [
          {
            "key": "X-Content-Type-Options",
            "value": "nosniff"
          },
          {
            "key": "X-Frame-Options",
            "value": "DENY"
          },
          {
            "key": "X-XSS-Protection",
            "value": "1; mode=block"
          }
        ]
      }
    ]
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "storage": {
    "rules": "storage.rules"
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ],
    "source": "functions"
  }
}

10.2 Deployment Scripts

Deploy Commands:

#!/bin/bash
# deploy.sh

echo "Deploying AI Study Assistant..."

# Deploy Firestore rules and indexes
echo "Deploying Firestore configuration..."
firebase deploy --only firestore

# Deploy Storage rules
echo "Deploying Storage configuration..."
firebase deploy --only storage

# Deploy Functions
echo "Deploying Cloud Functions..."
firebase deploy --only functions

# Deploy Hosting
echo "Deploying Web App..."
firebase deploy --only hosting

echo "Deployment completed!"

📊 STEP 11: MONITORING & LOGGING

11.1 Logging Configuration

Winston Logger Setup:

// functions/utils/logger.ts
import winston from 'winston';

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { service: 'teachit-functions' },
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
    new winston.transports.Console({
      format: winston.format.simple()
    })
  ]
});

export default logger;

11.2 Health Checks

Health Check Function:

// functions/health.ts
import * as functions from 'firebase-functions';
import { config } from './config/firebase';

export const healthCheck = functions.https.onRequest(async (req, res) => {
  try {
    // Check Firestore connectivity
    await config.firestore.collection('health').doc('check').get();
    
    // Check Storage connectivity
    const bucket = config.storage.bucket();
    await bucket.exists();
    
    // Check dependencies
    const dependencies = {
      firestore: 'ok',
      storage: 'ok',
      openai: config.openaiApiKey ? 'ok' : 'missing',
      anthropic: config.anthropicApiKey ? 'ok' : 'missing'
    };
    
    res.status(200).json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      dependencies
    });
  } catch (error) {
    res.status(500).json({
      status: 'unhealthy',
      error: error.message,
      timestamp: new Date().toISOString()
    });
  }
});

🧪 STEP 12: TESTING CONFIGURATION

12.1 Firebase Emulators

Emulator Configuration:

# firebase.json
{
  "emulators": {
    "auth": {
      "port": 9099
    },
    "firestore": {
      "port": 8080
    },
    "storage": {
      "port": 9199
    },
    "functions": {
      "port": 5001
    },
    "ui": {
      "enabled": true,
      "port": 4000
    },
    "singleProjectMode": true
  }
}

Start Emulators:

firebase emulators:start

12.2 Test Configuration

Test Setup:

// test/firebase_test_setup.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

void setupFirebaseTests() {
  setUpAll(() async {
    await Firebase.initializeApp();
    
    // Use emulators for testing
    FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080);
    FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
  });
}

📋 CHECKLIST

Pre-Launch Checklist:

  • Firebase project created and configured
  • Authentication methods enabled and tested
  • Firestore security rules deployed
  • Firestore indexes created
  • Storage security rules deployed
  • Cloud Functions deployed
  • Environment variables configured
  • Remote Config parameters set
  • Analytics tracking implemented
  • Crashlytics configured
  • Performance monitoring enabled
  • Rate limiting implemented
  • Error handling implemented
  • Health checks configured
  • Emulators configured for testing
  • Integration tests passing
  • Security audit completed

Production Checklist:

  • Production Firebase project created
  • Production API keys configured
  • Production security rules deployed
  • Performance monitoring enabled
  • Error reporting configured
  • Backup strategy implemented
  • Monitoring alerts configured
  • Documentation updated
  • Team training completed

🔧 TROUBLESHOOTING

Common Issues:

1. Firebase Initialization Error

# Solution: Check google-services.json (Android) and GoogleService-Info.plist (iOS)
firebase apps:list

2. Firestore Permission Denied

# Solution: Check security rules and user authentication
firebase deploy --only firestore:rules

3. Storage Upload Failed

# Solution: Check storage rules and bucket permissions
firebase deploy --only storage:rules

4. Functions Not Working

# Solution: Check function logs and environment variables
firebase functions:log

5. Analytics Not Tracking

# Solution: Check initialization and data collection settings
firebase analytics:debug

📚 RESOURCES

Documentation:

Tools:

Support:


Last Updated: 2026-05-06 Version: 1.0.0 Firebase Configuration Lead: Backend Development Team