Prerequisites:
- Node.js and npm installed
- Angular CLI installed (
npm install -g @angular/cli)- A Google account
- Basic familiarity with Angular
Scaffold a Fresh Angular Project
Kick things off by creating a new Angular 19 workspace:
ng new angular-fcm-demo
cd angular-fcm-demo
Pick the options that fit your needs. For this example, I usually go with "CSS" for styling and decline server-side rendering (SSR).
Create a Firebase Project
- Head over to the Firebase Console and authenticate with your Google account.
- Select "Add project".
- Provide a project name (like "Angular FCM Demo").
- Work through the setup, enabling Google Analytics if you like (it's recommended).
- Hit "Create project".
Once it's ready, you'll land on the Firebase project overview page.
Link Your Web App to Firebase
- In the Firebase Console, tap the web icon (
</>) to register a web app. - Assign a nickname to your app (e.g., "Angular Web App").
- Optionally enable "Set up Firebase Hosting".
- Click "Register app".
Firebase then gives you a config object that looks like this:
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID",
measurementId: "YOUR_MEASUREMENT_ID"
};
Note: Save this
firebaseConfigobject — you'll need it shortly.
Add Firebase to Your Angular App
Set up the required Firebase package:
npm install @angular/fire
Make a new file called src/environments/environment.ts and put your Firebase settings there:
export const environment = {
production: false,
firebaseConfig: {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID",
measurementId: "YOUR_MEASUREMENT_ID"
}
};
Bring in @angular/fire and wire up Firebase inside app.config.ts:
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideMessaging, getMessaging } from '@angular/fire/messaging';
import { routes } from './app.routes';
import { environment } from '../environments/environment';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideFirebaseApp(() => initializeApp(environment.firebaseConfig)),
provideMessaging(() => getMessaging()),
],
};
Add a Service Worker
Service workers are required to handle push notifications in the background.
Select the appropriate Service Worker package:
npm i @angular/service-worker
Create a firebase-messaging-sw.js file in the src folder.
importScripts(
"https://www.gstatic.com/firebasejs/11.4.0/firebase-app-compat.js"
);
importScripts(
"https://www.gstatic.com/firebasejs/11.4.0/firebase-messaging-compat.js"
);
const firebaseConfig = {
apiKey: "----",
authDomain: "----",
projectId: "----",
storageBucket: "----",
messagingSenderId: "----",
appId: "----",
};
const app = firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
Navigate to the project root and locate angular.json.
Insert this line under assets:
"src/firebase-messaging-sw.js"
Service Worker Notes:
- Service workers must be delivered over HTTPS (except on
localhostin development).- This file isn't transpiled, so it must be written as valid plain JavaScript.
Set Up @angular/fire
Next, we'll leverage @angular/fire to manage tokens and incoming notifications.
Here's a minimal setup in app.component.ts.
For added security, FCM requires a VAPID key to support web push.
- In the Firebase Console, navigate to "Project settings" > "Cloud Messaging".
- Scroll to "Web push certificates".
- If no key pair exists, hit "Generate Key Pair". Your VAPID key will then be generated and displayed.
import { Component, OnInit } from '@angular/core';
import { initializeApp } from '@angular/fire/app';
import { getMessaging, getToken, onMessage } from '@angular/fire/messaging';
import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
standalone: true,
imports: [],
template: `<p>Hi!</p>`,
})
export class AppComponent implements OnInit {
private messaging: any;
ngOnInit(): void {
const app = initializeApp(environment.firebaseConfig);
this.messaging = getMessaging(app);
this.requestPermission();
onMessage(this.messaging, (payload) => {
alert(JSON.stringify(payload));
// ...
});
}
requestPermission() {
console.log('Requesting permission...');
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.');
getToken(this.messaging, {
vapidKey: environment.firebaseConfig.vapidKey,
})
.then((currentToken: string) => {
if (currentToken) {
console.log(currentToken);
} else {
console.log(
'No registration token available. Request permission to generate one.'
);
}
})
.catch((err: any) => {
console.log(err);
});
}
});
}
}
Run Your App
npm start
Open localhost:4200 to see your app and grant notification permissions.
Send a Test Push
- Go to the Firebase Console.
- Click on "Cloud Messaging".
- Press "Send your first message".
- Write a notification title and body.
- Choose "Send test message".
- Paste the registration token you saw in the browser console.
- Press "Test".
A push notification should now pop up in your browser!
Troubleshooting Common Issues
- Permissions: Verify that the user has explicitly granted notification permission before expecting delivery.
- Clear Cache: Regularly clear the browser's cache and cookies so the latest version of the service worker is loaded and executed.
Wrapping Up
This walkthrough has covered the full process of adding Firebase Cloud Messaging to an Angular 19 project.
By applying the described steps, you can activate push notifications and boost user engagement.
Access the complete source code here.
Best of luck, and enjoy building! 🎉
Stuck on something? Drop your questions in the comments below!
