BarberApp uses Firebase as its backend platform, providing authentication, database, and hosting services. This guide walks you through the complete Firebase setup process.
Firebase Services Used
Authentication Email/password authentication for users
Firestore NoSQL database for appointments and user data
Hosting Static web hosting with SPA support
Initial Firebase Setup
Create Firebase Project
Go to the Firebase Console
Click Add project
Enter your project name (e.g., “barber-shop”)
Choose whether to enable Google Analytics (optional)
Click Create project
Register Web App
In your Firebase project, click the Web icon (</>)
Register your app with a nickname (e.g., “BarberApp Web”)
Check “Also set up Firebase Hosting” if you plan to deploy
Click Register app
Copy the Firebase configuration object
Install Firebase CLI
Install the Firebase CLI globally: npm install -g firebase-tools
Login to Firebase:
Initialize Firebase in Your Project
In your project root: Select:
Firestore : Configure security rules and indexes
Hosting : Configure files for Firebase Hosting
The project already includes firebase.json with the correct configuration. The init command will detect and use it.
Firebase Configuration
Understanding firebase.json
BarberApp’s Firebase configuration is defined in firebase.json:
{
"firestore" : {
"database" : "(default)" ,
"location" : "southamerica-east1" ,
"rules" : "firestore.rules" ,
"indexes" : "firestore.indexes.json"
},
"hosting" : {
"site" : "barber-shop-guy" ,
"public" : "dist/barber-shop/browser" ,
"ignore" : [
"firebase.json" ,
"**/.*" ,
"**/node_modules/**"
],
"rewrites" : [
{
"source" : "**" ,
"destination" : "/index.html"
}
]
}
}
database : Uses the default Firestore database
location : southamerica-east1 - Choose the region closest to your users
rules : Security rules file (see below)
indexes : Composite indexes for complex queries
site : Your Firebase hosting site ID (update this to your site name)
public : Points to Angular’s production build output
rewrites : Ensures all routes redirect to index.html for SPA routing
Update the site value in firebase.json to match your Firebase hosting site name.
Application Configuration
The Firebase SDK is configured in src/app/app.config.ts:
src/app/app.config.ts (Line 24-34)
export const appConfig : ApplicationConfig = {
providers: [
// ... other providers
// Firebase configuration and services
provideFirebaseApp (() => initializeApp ( environment . firebaseConfig )),
provideAuth (() => getAuth ()),
provideFirestore (() => getFirestore ()),
provideHttpClient (),
// ... repository providers
]
};
Key points:
Firebase is initialized with configuration from environment files
Auth and Firestore are provided at the application level
Services are injected via dependency injection tokens
Firebase Authentication
Enable Authentication
Navigate to Authentication
In the Firebase Console, go to Authentication → Get started
Enable Email/Password Provider
Click on Sign-in method tab
Click Email/Password
Enable Email/Password (first toggle)
Click Save
BarberApp does not use Email link (passwordless) authentication, so you can leave the second toggle disabled.
Configure Settings
Optionally configure:
Authorized domains : Add your production domain
Email templates : Customize password reset and verification emails
Authentication Implementation
BarberApp implements authentication through FirebaseAuthService:
src/app/services/firebase/firebase-auth.service.ts
@ Injectable ({ providedIn: 'root' })
export class FirebaseAuthService implements AuthRepository {
private auth : Auth = inject ( Auth );
private userService = inject ( FirebaseUserService );
async register ( email : string , password : string ) : Promise < string > {
const userCredential = await createUserWithEmailAndPassword (
this . auth ,
email ,
password
);
return userCredential . user . uid ;
}
async login ( email : string , password : string ) : Promise < void > {
await signInWithEmailAndPassword ( this . auth , email , password );
}
async logout () : Promise < void > {
await signOut ( this . auth );
}
async isAuthenticated () : Promise < boolean > {
return new Promise (( resolve ) => {
onAuthStateChanged ( this . auth , ( user ) => resolve ( !! user ));
});
}
}
Features:
Email/password registration and login
Auth state observation
Integration with Firestore for user profiles
Default profile picture from Cloudinary
Firestore Database
Database Structure
BarberApp uses the following Firestore collections:
Users Collection
Appointments Collection
Specialties Collection
users/
{userId}/
- id: string
- email: string
- firstName: string
- lastName: string
- dni: string
- sex: Sex (enum)
- birthDate: Timestamp
- phone: string
- profilePictureUrl: string
- role: UserRoles (CLIENT | SPECIALIST)
- status: UserStatus (ACTIVE | DISABLED)
- registrationDate: Timestamp
Security Rules
Create firestore.rules in your project root:
rules_version = '2' ;
service cloud . firestore {
match / databases / { database } / documents {
// Helper functions
function isAuthenticated () {
return request . auth != null ;
}
function isOwner ( userId ) {
return request . auth . uid == userId ;
}
function hasRole ( role ) {
return isAuthenticated () &&
get ( / databases / $ ( database ) / documents / users / $ ( request . auth . uid )). data . role == role ;
}
// Users collection
match / users / { userId } {
// Anyone can read user profiles (needed for appointments)
allow read : if isAuthenticated ();
// Users can only write their own profile
allow create : if isAuthenticated () && isOwner ( userId );
allow update , delete : if isAuthenticated () && isOwner ( userId );
}
// Appointments collection
match / appointments / { appointmentId } {
// Users can read their own appointments
allow read : if isAuthenticated () &&
( resource . data . clientId == request . auth . uid ||
resource . data . specialistId == request . auth . uid );
// Clients can create appointments
allow create : if isAuthenticated () &&
request . resource . data . clientId == request . auth . uid ;
// Clients and specialists can update their appointments
allow update : if isAuthenticated () &&
( resource . data . clientId == request . auth . uid ||
resource . data . specialistId == request . auth . uid );
// Only specialists can delete appointments
allow delete : if hasRole ( 'SPECIALIST' );
}
// Specialties collection
match / specialties / { specialtyId } {
// Everyone can read specialties
allow read : if true ;
// Only specialists can manage specialties
allow write : if hasRole ( 'SPECIALIST' );
}
}
}
Always test your security rules thoroughly before deploying to production. Use the Firebase Console’s Rules Playground to simulate requests.
Deploying Security Rules
firebase deploy --only firestore:rules
Creating Indexes
For complex queries, create firestore.indexes.json:
{
"indexes" : [
{
"collectionGroup" : "appointments" ,
"queryScope" : "COLLECTION" ,
"fields" : [
{ "fieldPath" : "clientId" , "order" : "ASCENDING" },
{ "fieldPath" : "date" , "order" : "DESCENDING" }
]
},
{
"collectionGroup" : "appointments" ,
"queryScope" : "COLLECTION" ,
"fields" : [
{ "fieldPath" : "specialistId" , "order" : "ASCENDING" },
{ "fieldPath" : "status" , "order" : "ASCENDING" },
{ "fieldPath" : "date" , "order" : "ASCENDING" }
]
}
],
"fieldOverrides" : []
}
Deploy indexes:
firebase deploy --only firestore:indexes
Firebase Hosting
Building for Production
Build the Application
Create an optimized production build: This creates the build output in dist/barber-shop/browser/ as configured in angular.json:43 and firebase.json:10.
Test Locally
Preview your build locally with Firebase hosting: The app will be available at http://localhost:5000
Deploy to Firebase
Deploy to Firebase Hosting: firebase deploy --only hosting
Your app will be live at: https://your-site-name.web.app
Custom Domain Setup
In Firebase Console, go to Hosting → Add custom domain
Enter your domain name
Follow the DNS verification steps
Add the required DNS records to your domain provider
Wait for SSL certificate provisioning (can take up to 24 hours)
Hosting Configuration Details
"rewrites" : [
{
"source" : "**" ,
"destination" : "/index.html"
}
]
This ensures all routes are handled by Angular’s router, enabling deep linking in your SPA.
Environment Variables in Production
The production build uses src/environments/environment.prod.ts automatically due to file replacement:
"fileReplacements" : [
{
"replace" : "src/environments/environment.ts" ,
"with" : "src/environments/environment.prod.ts"
}
]
Make sure your production environment file contains the correct Firebase project credentials.
Firebase Service Integration
Dependency Injection Pattern
BarberApp uses injection tokens for loose coupling:
src/app/app.config.ts:37-40
// Service providers
{ provide : AUTH_REPOSITORY , useClass : FirebaseAuthService },
{ provide : USER_REPOSITORY , useClass : FirebaseUserService },
{ provide : SPECIALTY_REPOSITORY , useClass : FirebaseSpecialtyService },
{ provide : APPOINTMENT_REPOSITORY , useClass : FirebaseAppointmentService }
This allows you to swap Firebase services with other implementations without changing your components.
Using Firebase Services
Inject services using tokens in your components:
import { inject } from '@angular/core' ;
import { AUTH_REPOSITORY } from '@core/interfaces/auth.repository.token' ;
export class LoginComponent {
private authService = inject ( AUTH_REPOSITORY );
async login ( email : string , password : string ) {
await this . authService . login ( email , password );
}
}
Complete Deployment Workflow
Here’s the complete workflow for deploying BarberApp:
Full Deployment
Selective Deployment
View Deployment
# 1. Build the application
npm run build
# 2. Deploy everything
firebase deploy
Monitoring and Analytics
Firebase Console Monitor authentication, database usage, and hosting traffic in the Firebase Console
Performance Monitoring Enable Firebase Performance Monitoring to track real user performance metrics
Crashlytics Optional: Add Firebase Crashlytics for error reporting in production
Google Analytics Track user behavior and conversions with Google Analytics integration
Troubleshooting
Authentication errors in production
Make sure your production domain is added to Authorized domains in Firebase Authentication settings:
Go to Authentication → Settings → Authorized domains
Add your custom domain
Save changes
Firestore permission denied
Check your security rules: firebase deploy --only firestore:rules
Use the Rules Playground in Firebase Console to test specific operations.
Ensure your firebase.json has the rewrite rule: "rewrites" : [
{ "source" : "**" , "destination" : "/index.html" }
]
Verify the build output path matches in both files:
angular.json (builder output)
firebase.json:10 ("public": "dist/barber-shop/browser")
Next Steps
Architecture Overview Learn about BarberApp’s clean architecture and service layers
Authentication Service Deep dive into the authentication implementation
Data Models Understand the Firestore data models and schemas
Configuration Guide Environment setup and application configuration