How to Add Push Notifications in a React + Capacitor App with Firebase (Android & iOS)

Category: Technology | Published: 23 days ago

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

    console.log
    in your custom hook

  • 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.

How to Add Push Notifications in a React + Capacitor App with Firebase (Android & iOS)
Kiran Chaulagain

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.