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.
Co-Founder Taliferro
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.
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.
AppModule (or a feature module), which imported whatever services and other modules it needed. As an app grew, that module file grew with 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.
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
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.
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.
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.
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 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.
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.
Yes. AngularFire remains a clean way to wire Firebase services (Auth, Firestore, Storage, Messaging) into Angular’s standalone architecture via app.config.ts.
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.
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.
More from the blog