Firebase Setup
Relevant source files
The following files were used as context for generating this wiki page:- README.md
- apps/api/package.json
- apps/api/src/module/firebase/firebase.bootstrap.ts
- apps/api/src/module/firebase/firebase.module.ts
- apps/api/src/module/firebase/services/firebase-admin.service.ts
- apps/api/src/module/auth/services/user.service.ts
- apps/api/src/services/firebase/firebase.client.ts
- apps/api/src/module/firebase/services/firebase-rest.service.ts
Firebase serves as the core backend-as-a-service (BaaS) for the Ever Rec platform, providing essential services for authentication, data storage, and file management. The integration is primarily handled within the apps/api NestJS application, which uses the Firebase Admin SDK for privileged server-side operations and the Firebase client SDK for certain authentication flows.
The platform leverages several Firebase products:
- Firebase Authentication: Manages user identity through email/password and Google OAuth providers.
- Firebase Realtime Database: Stores application data, such as user profiles, teams, and other metadata.
- Firebase Storage: Used for storing user-generated content like avatars, images, and videos.
This document outlines the configuration, architecture, and key components of the Firebase integration within the Ever Rec project.
Sources: README.md:46-47, README.md:144-162
Configuration
Proper configuration is crucial for connecting the application to the correct Firebase project and enabling its services. This is managed through environment variables and project-level configuration files.
Environment Variables
The API server (apps/api) requires a set of environment variables to initialize the Firebase Admin SDK and other Firebase services. These variables should be placed in an .env.dev or .env.prod file within the apps/api directory.
| Variable | Description |
|---|---|
FIREBASE_API_KEY | The API key for your Firebase project. |
FIREBASE_AUTH_DOMAIN | The authentication domain (e.g., your_project.firebaseapp.com). |
FIREBASE_DATABASE_URL | The URL for the Firebase Realtime Database. |
FIREBASE_PROJECT_ID | The unique identifier for your Firebase project. |
FIREBASE_STORAGE_BUCKET | The Cloud Storage bucket name (e.g., your_project.appspot.com). |
FIREBASE_MESSAGING_SENDER_ID | The sender ID for Firebase Cloud Messaging. |
FIREBASE_APP_ID | The ID for your Firebase web app. |
FIREBASE_MEASUREMENT_ID | The ID for Google Analytics measurement. |
FIREBASE_ADMIN_PRIVATE_KEY | The private key from the Firebase service account JSON file. |
FIREBASE_ADMIN_CLIENT_EMAIL | The client email from the Firebase service account JSON file. |
Sources: README.md:100-114, apps/api/src/services/firebase/firebase.client.ts:18-29, apps/api/src/module/firebase/firebase.bootstrap.ts:15-19
Firebase Project Setup
Before running the application, a Firebase project must be created and configured.
- Create Firebase Project: Add a new project in the Firebase Console.
- Web App Setup: Add a web app (</>) to the project and copy the configuration details into the environment files.
- Authentication: Enable
GoogleandEmail/Passwordsign-in providers in the Authentication section. - Realtime Database: Create a Realtime Database. The security rules should be updated using the contents of
database.rules.json. - Storage: Enable Firebase Storage and configure its security rules using
storage.rules.
Sources: README.md:145-162
Backend Integration (API)
The apps/api application contains a dedicated FirebaseModule to manage all interactions with Firebase services. This module is marked as @Global to make its providers available throughout the application.
Sources: apps/api/src/module/firebase/firebase.module.ts:11
Firebase Module
The FirebaseModule is the central hub for all Firebase-related services. It imports necessary configurations and exports several services for dependency injection across the application.
This diagram illustrates the providers within the FirebaseModule and their dependencies.
Admin SDK Initialization
The Firebase Admin SDK is initialized at application startup. The bootstrapFirebase function is responsible for this process. It reads the necessary credentials from the ConfigService and initializes the admin app.
The initialization flow is as follows:
- Check if a Firebase app is already initialized to prevent re-initialization.
- Retrieve
projectId,clientEmail,privateKey,databaseURL, andstorageBucketfrom the configuration. - Validate that the required admin credentials (
projectId,clientEmail,privateKey) are present. - Create a
ServiceAccountobject and anAppOptionsobject. - Initialize the Firebase Admin SDK using
admin.initializeApp().
Core Services
FirebaseAdminService
This service acts as a wrapper around the initialized Firebase Admin SDK, providing convenient methods for interacting with Firebase Auth, Realtime Database, and Storage. It is injected into other services that require administrative access to Firebase.
The class diagram below shows the structure of FirebaseAdminService.
FirebaseRestService
This service provides methods to interact with the Firebase Identity Toolkit REST API. It is used for authentication-related operations that might be performed via client-side SDKs but are handled on the backend here, such as signing in with a custom token or exchanging a refresh token. It uses nestjs-http-promise for making HTTP requests.
Key methods include:
signInWithCustomToken(customToken: string)exchangeRefreshTokenForIdToken(refreshToken: string)getAccountInfo(idToken: string)
Sources: apps/api/src/module/firebase/services/firebase-rest.service.ts:12-167
FirebaseClient Service
Interestingly, the project also includes a FirebaseClient service that initializes the client-side Firebase SDK (firebase/app). This service is used to interact with Firebase as a client would, providing access to Auth, Database, and Storage instances from the client SDK. This is typically used for flows that require a client-like authentication state.
// apps/api/src/services/firebase/firebase.client.ts:16-18
constructor(private readonly configService: ConfigService) {
this.initFirebaseClient();
}
// apps/api/src/services/firebase/firebase.client.ts:32-36
this.firebaseApp ??= initializeApp(firebaseConfig);
this.firebaseAuth ??= getAuth(this.firebaseApp);
this.firebaseGoogleAuthProvider ??= new GoogleAuthProvider();
this.firebaseDb ??= getDatabase(this.firebaseApp);
this.firebaseStorage ??= getStorage(this.firebaseApp);
Sources: apps/api/src/services/firebase/firebase.client.ts:1-38
Service Interaction Example
Services across the application, particularly within the AuthModule, rely on the FirebaseAdminService to manage user data.
User Creation Flow
The UserService utilizes FirebaseAdminService to create and manage users in Firebase Authentication and the Realtime Database. The sequence diagram below illustrates the process of creating a new user.
This diagram shows how UserService first calls FirebaseAdminService to create the user in Firebase Auth, and then separately uses a database reference from the same service to add the user's profile to the Realtime Database.
Sources: apps/api/src/module/auth/services/user.service.ts:49-62, apps/api/src/module/auth/services/user.service.ts:67-94
Database and Storage
Realtime Database
The Realtime Database is used for storing structured data like user profiles and application settings. Access control is managed by security rules defined in database.rules.json. The FirebaseAdminService provides direct, admin-level access to the database, bypassing these rules, which is essential for server-side logic. Services like WhiteboardTeamService interact directly with the database using the admin SDK.
Sources: README.md:156-162, apps/api/src/module/whiteboards/services/teams.service.ts:32-39
Cloud Storage
Firebase Cloud Storage is used for storing binary files, such as user avatars. The FirebaseAdminService provides a getStorageBucket() method to get a reference to the default storage bucket. The UserProfileService, for example, uses this to upload user avatars.
// apps/api/src/module/auth/services/user-profile.service.ts:182-184
async uploadAvatar(uid: string, avatar: Express.Multer.File): Promise<IDataResponse> {
// ...
const bucket = this.firebaseAdminService.getStorageBucket();
const avaRef = bucket.file(`users/${uid}/tools/avatar`);
// ...
}
Sources: apps/api/src/module/auth/services/user-profile.service.ts:184-185, apps/api/src/module/firebase/services/firebase-admin.service.ts:151-156, README.md:164-168
Summary
The Firebase integration in Ever Rec is robust and central to its backend architecture. It uses the Firebase Admin SDK for secure server-side operations, managed through a dedicated NestJS module (FirebaseModule). Configuration is handled via environment variables, allowing for easy setup across different environments. By encapsulating Firebase logic within specific services like FirebaseAdminService, the application maintains a clean separation of concerns while leveraging the full power of Firebase for authentication, database management, and file storage.