Send push notification with Firebase Cloud Messaging
This is a simple example of how to send push notifications with Firebase Cloud Messaging (FCM) using Node.js and Express.
First, you need to set up a Firebase project and enable FCM in the Firebase console. Go to https://console.firebase.google.com/ and click on Create a Project.

Then choose a project name
Choose the type of project
On register, you will see your credentials and setup instructions:
Generate new private key
You can also generate new Private key by going to Service Accounts and Generate New Private Key section of the Firebase console..

Note:Save your key, which will be in json format somewhere in your project directory.
Express server
Now, you can create a Typescript Express server that sends push notifications using FCM. Here's an example of how you can do it:
npm install express firebase-admin mongoose
npm i nodemon -g
tsc --init
Create a app.ts file
touch /app.ts
Create your Models and Schemas to hold the device tokens
import { Schema, model, Document } from "mongoose";
export interface IDeviceToken extends Document {
identifierId: string; // the unique identifier for the user (e.g userId, adminId)
token: string;
userType: string;
}
export enum UserType {
USER = "USER",
ADMIN = "ADMIN"
}
const DeviceTokenSchema = new Schema<IDeviceToken>(
{
identifierId: { type: String, required: true },
token: { type: String, required: true, unique: true },
userType: { type: String, required: true, enum: Object.values(UserType) }
},
{ timestamps: true }
);
const DeviceToken = model<IDeviceToken>("DeviceToken", DeviceTokenSchema);
export default DeviceToken;
Configure database
// db/db.ts
import mongoose from "mongoose";
const connectDB = async () => {
try {
await mongoose.connect("mongodb://localhost:27017/fireproj");
console.log("MongoDB connected");
} catch (error) {
console.error(error);
process.exit(1);
}
};
export default connectDB;
Configure your firebase admin
import admin from "firebase-admin";
import path from "path"
if (!admin.apps.length) {
try {
const serviceAccount = require(path.resolve(__dirname, "./firebase.json")); //firebase.json file we downloaded earlier
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
console.log("Firebase initialized successfully.");
} catch (error) {
console.error("Failed to initialize Firebase:", error);
throw new Error("Firebase initialization failed.");
}
}
const fcm = admin.messaging();
export default fcm;
The keys you downloaded earlier are stored in the firebase.json file.
Write a service to save and update your deviceToken
import DeviceToken from "./device.model";
import { NotificationPayload, NotificationService, PushNotification } from "./firebaseservice";
export const saveDeviceToken = async (
identifierId: string,
token: string,
userType: string
): Promise<void> => {
const existingToken = await DeviceToken.findOne({ token });
if (!existingToken) {
await DeviceToken.create({ identifierId, token, userType });
} else if (existingToken.identifierId !== identifierId) {
existingToken.identifierId = identifierId;
await existingToken.save();
}
};
Write a service to send push notifications
import fcm from "./firebase.config";
export interface NotificationPayload {
title: string;
body: string;
data?: Record<string, string>;
}
export interface PushNotification {
token: string;
payload: NotificationPayload;
}
export class NotificationService {
static async sendNotification(notification: PushNotification): Promise<void> {
const message = {
token: notification.token,
notification: {
title: notification.payload.title,
body: notification.payload.body,
},
data: notification.payload.data || {},
};
try {
const response = await fcm.send(message);
console.log("Notification sent successfully:", response);
} catch (error) {
console.error("Error sending notification:", error);
throw new Error("Failed to send notification");
}
}
}
Write a controller to handle save deviceToken and send push notifications
import { Request, Response } from "express";
import { UserType } from "../model/devicetoken";
import { NotificationPayload, NotificationService } from "../services/push.service";
import { saveDeviceToken } from "../services/devicetoken.service";
export class NotificationController {
static async saveDeviceToken(req: Request, res: Response) {
const { token } = req.body;
try {
if (!token) return res.status(400).json({ message: "Token is required" });
await saveDeviceToken("000000000000000000000000", token, UserType.USER)
res.status(200).json({ message: "Device token saved successfully" });
} catch (error) {
return res.status(500).json({ message: "Failed to save device token" });
}
}
static async sendNotification(req: Request, res: Response) {
const { title, body, token } = req.body;
try {
const userNotificationPayload: NotificationPayload = {
title,
body
};
await NotificationService.sendNotification({
token,
payload: userNotificationPayload,
});
res.status(200).json({ message: "Notification sent successfully" });
} catch (error) {
res.status(500).json({ message: "Failed to send notification" });
}
}
}
In this example, we have two methods in the NotificationController class: saveDeviceToken and sendNotification. The saveDeviceToken method takes a token from the request body and saves it to the database using the DeviceToken model. The sendNotification method takes a title, body, and data from the request body and sends a push notification using the NotificationService class.
To use this controller, you can create a new instance of the NotificationController class and pass it to the Express app:
import express from 'express';
import { NotificationController } from './controller/notification.controller';
import connectDB from './db/db';
const app = express();
app.use(express.json());
connectDB();
app.post('/save-device-token', NotificationController.saveDeviceToken);
app.post('/send-notification', NotificationController.sendNotification);
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Package.json
{
"name": "push-notification-server",
"version": "1.0.0",
"description": "A simple push notification server using Node.js and Firebase Cloud Messaging",
"main": "app.js",
"scripts": {
"start": "node dist/app.js",
"dev":"nodemon app.ts"
},
"dependencies": {
"express": "^4.21.1",
"firebase-admin": "^13.0.1",
"mongoose": "^8.8.3"
}
}
Start your app
npm run dev
Create a test.http file and add the following content
POST http://localhost:3000/send-notification
Content-Type: application/json
{
"title": "Hello",
"body": "This is a test notification",
"token": ["YOUR_DEVICE_TOKEN"]
}
POST http://localhost:3000/save-device-token
Content-Type: application/json
{
"token": "YOUR_DEVICE_TOKEN"
}






Top comments (0)