Skip to main content
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

1

Create Firebase Project

  1. Go to the Firebase Console
  2. Click Add project
  3. Enter your project name (e.g., “barber-shop”)
  4. Choose whether to enable Google Analytics (optional)
  5. Click Create project
2

Register Web App

  1. In your Firebase project, click the Web icon (</>)
  2. Register your app with a nickname (e.g., “BarberApp Web”)
  3. Check “Also set up Firebase Hosting” if you plan to deploy
  4. Click Register app
  5. Copy the Firebase configuration object
3

Install Firebase CLI

Install the Firebase CLI globally:
npm install -g firebase-tools
Login to Firebase:
firebase login
4

Initialize Firebase in Your Project

In your project root:
firebase init
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:
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

1

Navigate to Authentication

In the Firebase Console, go to AuthenticationGet started
2

Enable Email/Password Provider

  1. Click on Sign-in method tab
  2. Click Email/Password
  3. Enable Email/Password (first toggle)
  4. Click Save
BarberApp does not use Email link (passwordless) authentication, so you can leave the second toggle disabled.
3

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/
  {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:
firestore.rules
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:
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

1

Build the Application

Create an optimized production build:
npm run build
This creates the build output in dist/barber-shop/browser/ as configured in angular.json:43 and firebase.json:10.
2

Test Locally

Preview your build locally with Firebase hosting:
firebase serve
The app will be available at http://localhost:5000
3

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

  1. In Firebase Console, go to HostingAdd custom domain
  2. Enter your domain name
  3. Follow the DNS verification steps
  4. Add the required DNS records to your domain provider
  5. Wait for SSL certificate provisioning (can take up to 24 hours)

Hosting Configuration Details

firebase.json:16-21
"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:
angular.json:74-79
"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:
# 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

Make sure your production domain is added to Authorized domains in Firebase Authentication settings:
  1. Go to Authentication → Settings → Authorized domains
  2. Add your custom domain
  3. Save changes
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

Build docs developers (and LLMs) love