How to Add Push Notifications in a React + Capacitor App with Firebase (Android & iOS)
Push notifications are a powerful tool to keep your users engaged in real-time. In this guide, you’ll learn how to implement push notifications in a React + Capacitor mobile app, using Firebase Cloud Messaging (FCM) and an optional FastAPI backend.
We’ll walk through the entire process—covering both Android and iOS platforms—from Firebase setup to frontend integration and backend communication.
🚧 Prerequisites
A working React + Capacitor app
Firebase account
Xcode (for iOS builds)
Android Studio (for Android builds)
Python FastAPI backend (optional but recommended)
🔧 Step 1: Set Up Firebase
1.1 Create a Firebase Project
Go to the Firebase Console.
Click “Add Project” and follow the prompts.
Note the Project ID—you’ll need it later.
1.2 Add an Android App
In your Firebase project, go to Project Settings > General.
Click “Add App” → Select Android.
Enter your app’s package name (e.g.,
).com.example.app
Download
.google-services.json
Place it in your project at:
.android/app/google-services.json
1.3 Add an iOS App
In Project Settings > General, click “Add App” → Select iOS.
Enter your app’s bundle ID (e.g.,
).com.example.app
Download
.GoogleService-Info.plist
Place it in:
.ios/App/App/GoogleService-Info.plist
1.4 Set Up iOS APNs
Go to Project Settings > Cloud Messaging.
Upload your APNs authentication key (recommended) or certificate.
Get this key from the Apple Developer Portal.
⚙️ Step 2: Configure Capacitor
2.1 Install Required Packages
yarn add @capacitor/push-notifications firebase
2.2 Update Capacitor Config
// capacitor.config.ts
const config: CapacitorConfig = {
plugins: {
PushNotifications: {
presentationOptions: ["badge", "sound", "alert"]
}
}
};
📱 Step 3: Android Setup
3.1 Update Android Permissions
In
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
3.2 Add Firebase SDK
In
android/app/build.gradle
dependencies {
implementation platform('com.google.firebase:firebase-bom:33.1.0')
implementation 'com.google.firebase:firebase-messaging'
}
apply from: 'capacitor.build.gradle'
try {
def servicesJSON = file('google-services.json')
if (servicesJSON.text) {
apply plugin: 'com.google.gms.google-services'
}
} catch(Exception e) {
logger.info("google-services.json not found.")
}
In
android/build.gradle
gradleCopyEditbuildscript {
dependencies {
classpath 'com.google.gms:google-services:4.4.0'
}
}
🍏 Step 4: iOS Setup
4.1 Open the Project in Xcode
cd ios/App open App.xcworkspace
4.2 Enable Push Notifications
Select your app target in Xcode.
Go to Signing & Capabilities.
Add Push Notifications.
Add Background Modes > Remote notifications.
4.3 Update Podfile
target 'App' do
capacitor_pods
pod 'Firebase/Core'
pod 'Firebase/Messaging'
end
Then run:
cd ios/App
pod install
4.4 Update AppDelegate.swift
Ensure your AppDelegate.swift includes:
import Firebase
import UserNotifications
FirebaseApp.configure()
Messaging.messaging().delegate = self
Add delegate methods for token management and notification handling.
💡 Step 5: Implement Frontend Push Logic
5.1 Create a Custom Hook
// src/hooks/usePushNotifications.ts
import { useEffect } from 'react';
import { PushNotifications } from '@capacitor/push-notifications';
import { getToken } from 'firebase/messaging';
export function usePushNotifications() {
useEffect(() => {
const registerNotifications = async () => {
const permissionResult = await PushNotifications.requestPermissions();
if (permissionResult.receive === 'granted') {
await PushNotifications.register();
}
PushNotifications.addListener('registration', async (token) => {
console.log('FCM Token:', token.value);
// Optional: Send token to backend
});
PushNotifications.addListener('pushNotificationReceived', (notification) => {
console.log('Notification Received:', notification);
});
};
registerNotifications();
}, []);
}
5.2 Use the Hook in Your App
// App.tsx
import { usePushNotifications } from './hooks/usePushNotifications';
function App() {
usePushNotifications();
return <MainRouter />;
}
🧠 Step 6: Backend (FastAPI Example)
6.1 Initialize Firebase Admin
# firebase_config.py
from firebase_admin import credentials, initialize_app
cred = credentials.Certificate("serviceAccountKey.json")
initialize_app(cred)
6.2 Save Device Token
# device_routes.py
@router.post("/api/users/{user_id}/device-token")
async def save_device_token(user_id: str, token: str):
# Store the token in your database
6.3 Send Push Notification
# push_service.py
from firebase_admin import messaging
def send_push_notification(token: str, title: str, body: str):
message = messaging.Message(
notification=messaging.Notification(title=title, body=body),
token=token
)
response = messaging.send(message)
return response
✅ Step 7: Test Your Setup
Build and Sync
yarn capacitor:sync
yarn capacitor:run:android
yarn capacitor:run:ios
Testing Checklist
Permissions are granted
FCM token is generated
Token is stored in backend (if used)
Notifications are received
Actions work correctly
🚀 Step 8: Production Deployment
iOS
Use a production provisioning profile
Upload production APNs key to Firebase
Archive and upload with Xcode
Android
Sign with production keystore
Upload to Google Play Console
Backend
Switch to production Firebase project
Use secure environment variables
Enable logging for delivery analytics
🔍 Troubleshooting
Problem | Solution |
FCM token not generated | Use a real device, check Firebase config files |
Notifications not received | Check APNs config, use Firebase Console to test |
Backend token registration fails | Confirm endpoint and network are working |
📊 Monitoring and Logging
Frontend Logs: Use
in your custom hookconsole.log
Backend Logs: Log responses from FCM SDK
Firebase Console: View delivery stats, errors, and usage analytics
🔐 Security Tips
Validate tokens before saving them
Authorize users properly for push registration
Limit payload content to essential data
Enable rate limiting on backend endpoints
✨ Conclusion
Setting up push notifications in a cross-platform app can feel overwhelming, but once configured, they offer a seamless way to stay connected with your users. With Capacitor, Firebase, and a robust backend, you’re fully equipped to deliver notifications reliably on both iOS and Android.


Kiran Chaulagain
kkchaulagain@gmail.com
I am a Full Stack Software Engineer and DevOps expert with over 6 years of experience. Specializing in creating innovative, scalable solutions using technologies like PHP, Node.js, Vue, React, Docker, and Kubernetes, I have a strong foundation in both development and infrastructure with a BSc in Computer Science and Information Technology (CSIT) from Tribhuvan University. I’m passionate about staying ahead of industry trends and delivering projects on time and within budget, all while bridging the gap between development and production. Currently, I’m exploring new opportunities to bring my skills and expertise to exciting new challenges.