32 KiB
32 KiB
Firebase Configuration - AI Study Assistant
⚠️ ATUALIZADO: Este documento foi corrigido para refletir a configuração REAL do projeto.
Notas Importantes:
- ❌ Cloud Functions: NÃO implementado
- ❌ Performance Monitoring: NÃO implementado
- ❌ Remote Config: NÃO implementado
- ❌ Roles admin/super_admin: NÃO implementados (apenas student/teacher)
- ✅ Estrutura real: users, materials, contentChunks, quizzes, classes, enrollments, userChats
🔥 COMPLETE FIREBASE SETUP GUIDE
📋 OVERVIEW
This document provides instructions for setting up Firebase for the AI Study Assistant project. Note: This is a Flutter + Firebase BaaS architecture without a custom backend.
🚀 STEP 1: FIREBASE PROJECT SETUP
1.1 Create Firebase Project
-
Go to Firebase Console
- Visit https://console.firebase.google.com
- Sign in with your Google account
-
Create New Project
# Using Firebase CLI (recommended) firebase projects create teachit-ai-assistant firebase use teachit-ai-assistant -
Configure Project Settings
- Project ID:
teachit-ai-assistant - Display Name:
AI Study Assistant - Organization: Select appropriate organization
- Project ID:
1.2 Enable Required Services
Firebase Services Actually Used:
- ✅ Firebase Authentication
- ✅ Cloud Firestore
- ✅ Cloud Storage
- ✅ Firebase Analytics
- ✅ Firebase Crashlytics
- ✅ Firebase Cloud Messaging
Firebase Services NOT Used:
- ❌ Cloud Functions (not needed - logic in Flutter)
- ❌ Firebase Performance Monitoring (not implemented)
- ❌ Firebase Remote Config (not implemented)
Enable Commands:
# Enable Authentication
firebase auth --enable
# Enable Firestore
firebase firestore:databases:create
# Enable Storage
firebase storage:buckets:create teachit-content
# Enable Analytics (automatically enabled)
# Note: Cloud Functions not needed
🔐 STEP 2: AUTHENTICATION CONFIGURATION
2.1 Firebase Auth Setup
Sign-in Methods to Enable:
-
Email/Password
- Go to Authentication → Sign-in method
- Enable Email/Password
- Set up email templates
-
Google Sign-In
- Enable Google provider
- Configure OAuth consent screen
- Add authorized domains
-
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
User Roles (Only 2 implemented):
// lib/core/services/auth_service.dart
class AuthService {
static const String studentRole = 'student';
static const String teacherRole = 'teacher';
// ❌ adminRole - NOT IMPLEMENTED
// ❌ superAdminRole - NOT IMPLEMENTED
}
Note: Role assignment is done client-side during signup:
await FirebaseFirestore.instance.collection('users').doc(user.uid).set({
'role': selectedRole, // 'student' or 'teacher'
'email': user.email,
'createdAt': FieldValue.serverTimestamp(),
});
🗄️ STEP 3: FIRESTORE DATABASE SETUP
3.1 Database Configuration
Create Firestore Database:
- Go to Firestore Database
- Create database in test mode (initially)
- Choose location (e.g.,
europe-west1) - Set up security rules
Actual Database Structure:
// Collections Structure (as implemented in code)
// Top-level collections:
users/{userId} // User profiles with role
schools/{schoolId} // Schools/institutions
materials/{materialId} // Teacher uploaded content
contentChunks/{chunkId} // Text chunks with mock embeddings
quizzes/{quizId} // Quiz definitions
classes/{classId} // Teacher-created classes
enrollments/{enrollmentId} // Student class memberships
userChats/{userId}/conversations/{convId}/messages/{msgId} // Chat history
// Collections NOT implemented:
// ❌ learningStates/{studentId} - Not in codebase
// ❌ quizAttempts/{attemptId} - Not implemented
// ❌ interactions/{interactionId} - Replaced by userChats subcollection
// ❌ auditLogs/{logId} - Not implemented
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