Taliferro Group

Angular Changed

Your Firebase setup should too

Angular now favors standalone configuration, Signals, and modern rendering patterns. This guide shows how to connect AngularFire without dragging old project habits into a new architecture.

By Tyrone Showers

Co-Founder Taliferro

Article

If your Angular project still has an AppModule, or you're used to wiring Firebase into a module instead of a config file, Angular 20 is going to feel different. Standalone components are the default now, not an opt-in — and that changes exactly where and how AngularFire gets set up.

Taliferro ran into this directly rebuilding the frontend for TODD, our own product, on Angular 20. The old NgModule-based Firebase setup didn't just need a tweak — it had to move into app.config.ts entirely, or the new rendering features wouldn't work correctly.

This guide walks through that exact migration: creating a standalone Angular 20 project, adding AngularFire, wiring Firebase services into app.config.ts, and confirming the connection actually works.

Standalone components, not NgModule

The biggest architectural change in Angular 20 is that NgModule is no longer the default. With standalone components, each component declares its own imports and dependencies directly, instead of being registered inside a shared module.

  • Angular 8–13: Every component had to be declared inside an AppModule (or a feature module), which imported whatever services and other modules it needed. As an app grew, that module file grew with it.
  • Angular 20: There's no central module. Each component imports exactly what it needs, and nothing else has to know about it.

This matters for Firebase specifically: in the old model, you configured Firebase once inside a module's providers array. In the standalone model, that configuration moves to a dedicated file — app.config.ts — which is what most of this guide is actually about.

Create the project

Start with a fresh Angular 20 project using the CLI:

ng new my-angular20-project

This creates a standalone project by default — there's no AppModule unless you add one yourself. Move into the new project directory before continuing:

cd my-angular20-project

Add AngularFire

From inside the project directory, run:

ng add @angular/fire

The CLI will ask which Firebase features you want — Firestore, Realtime Database, App Check, Cloud Storage, and hosting/deploy support, among others. Pick what you'll actually use; you can add more later with the same command.

Tip (Angular 20): if you're using server rendering, enable route-level render modes and incremental hydration in your router config — that's what actually improves perceived load time, not the Firebase setup itself.

The CLI installs the AngularFire and Firebase packages and updates environment.ts with your project's connection details:

export const environment = {
              production: false,
              firebaseConfig: {
                apiKey: "your-api-key",
                authDomain: "your-project-auth-domain",
                projectId: "your-project-id",
                storageBucket: "your-storage-bucket",
                messagingSenderId: "your-messaging-sender-id",
                appId: "your-app-id",
                measurementId: "your-measurement-id"
              }
            };

That file just holds your Firebase project's connection details. The actual wiring — where Firebase services become available to your app — happens next, in app.config.ts.

Wire it into app.config.ts

This is the part that's genuinely different from the NgModule days. Instead of registering Firebase in a module, you register each service as a provider in app.config.ts:

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
          import { provideRouter } from '@angular/router';
          import { routes } from './app.routes';
          import { provideClientHydration } from '@angular/platform-browser';
          import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
          import { getAuth, provideAuth } from '@angular/fire/auth';
          import { getFirestore, provideFirestore } from '@angular/fire/firestore';
          import { getDatabase, provideDatabase } from '@angular/fire/database';
          import { getMessaging, provideMessaging } from '@angular/fire/messaging';
          import { getStorage, provideStorage } from '@angular/fire/storage';
          
          export const appConfig: ApplicationConfig = {
            providers: [
            // Route-level render modes (SSR/Prerender/CSR) are stable in v20
              provideRouter(routes),
              provideClientHydration(),
              importProvidersFrom(provideFirebaseApp(() => initializeApp({
                projectId: 'your-project-id',
                appId: 'your-app-id',
                databaseURL: 'your-database-url',
                storageBucket: 'your-storage-bucket',
                apiKey: 'your-api-key',
                authDomain: 'your-auth-domain',
                messagingSenderId: 'your-messaging-sender-id',
                measurementId: 'your-measurement-id'
              }))),
              importProvidersFrom(provideAuth(() => getAuth())),
              importProvidersFrom(provideFirestore(() => getFirestore())),
              importProvidersFrom(provideDatabase(() => getDatabase())),
              importProvidersFrom(provideMessaging(() => getMessaging())),
              importProvidersFrom(provideStorage(() => getStorage()))
            ]
          };

Each provideX function initializes one Firebase service and makes it available anywhere in your app through dependency injection — no module imports required. Add only the services you're actually using; each one you skip is one less thing your app has to initialize on load.

Confirm it actually works

Don't just assume the config is correct — pull real data and check. Here's a minimal component that reads from Firestore on load:

import { Component, OnInit } from '@angular/core';
          import { Firestore, getDocs, collection } from '@angular/fire/firestore';
          import { inject } from '@angular/core';
          
          @Component({
            selector: 'app-root',
            templateUrl: './app.component.html',
            styleUrls: ['./app.component.css'],
            standalone: true,
            imports: []
          })
          export class AppComponent implements OnInit {
            firestore = inject(Firestore);
          
            ngOnInit() {
              getDocs(collection(this.firestore, "categories")).then((response) => {
                console.log(response.docs.map(doc => doc.data()));  // This will log the data of each document
              }).catch(error => {
                console.error("Error fetching documents:", error);
              });
            }
          }

This retrieves documents from a collection named "categories" and logs each one's data to the console. If real data shows up, the connection works. If you get an error instead, it's almost always one of two things: the Firebase config in environment.ts doesn't match your actual project, or your Firestore security rules are blocking the read.

Repeat this same check for any other service you added — Auth, Realtime Database, Messaging, Storage — before you build features on top of them.

Deploy it

Once everything works locally, deploying to Firebase Hosting is a few commands:

1. Ensure you have Firebase CLI installed:
             npm install -g firebase-tools
          
          2. Log in to Firebase from the CLI:
             firebase login
          
          3. Initialize your Firebase project:
             firebase init
          
             - Follow the prompts to select Firebase Hosting.
             - Connect the CLI to your Firebase project.
             - Configure as a single-page app and link to your Angular build output directory.
          
          4. Build your Angular project for production:
             ng build --configuration production
          
          5. Deploy your project to Firebase Hosting:
             firebase deploy

The firebase deploy command compiles your app into production files and distributes them across Firebase's CDN. After that, ongoing maintenance is mostly three things:

- Regularly review and update Firebase security rules.
          - Monitor usage and performance through Firebase Console.
          - Stay updated with the latest Firebase SDKs and AngularFire releases.

The takeaway

The mechanics haven't changed much — Firebase still does what it always did. What changed is where the wiring lives: out of NgModule, into app.config.ts, alongside the rest of your standalone, Signals-based app. Once you've made that move once, every Firebase service you add afterward follows the same pattern.

For further learning, refer to the official Angular documentation and Firebase documentation. These resources are invaluable for deepening your understanding and keeping abreast of the latest features and best practices.

See It in Action (Short)

Stuck on your own migration?

Tell us where it's breaking and we'll point you to the fix — whether that's the AngularFire setup itself or something upstream in how the project's structured.

FAQ

Is AngularFire still recommended in Angular 20?

Yes. AngularFire remains a clean way to wire Firebase services (Auth, Firestore, Storage, Messaging) into Angular’s standalone architecture via app.config.ts.

Do I need to migrate old modules?

If you’re on Angular 13 or earlier, create a fresh v20 project, port feature modules to standalone components, then add AngularFire with ng add @angular/fire. Configure providers in app.config.ts and test each Firebase service incrementally.

Tyrone Showers
Need the frontend to move faster?

If you want execution instead of more rework, start with web development that ships clean, connect it to the execution system, or show us the delivery bottleneck.

Want this fixed on your site?

Tell us your URL and what feels slow. We’ll point to the first thing to fix.

Explore Taliferro's free tools: Ask TODD · Find · Email Signature Builder · SayIt · Lead Vault · Meet Maya — or become an affiliate.