---
title: Firebase Cloud Messaging (FCM)
description: Integrate Firebase Cloud Messaging and display notifications with react-native-notify-kit.
---

[Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) (FCM) is a messaging solution for sending remote push notifications to Android and iOS devices. `react-native-notify-kit` ships a first-class integration called **FCM Mode** that handles the Android / iOS asymmetry for you and is the recommended path for new integrations.

> **FCM Mode is the recommended approach for FCM push with `react-native-notify-kit`.** Use the [legacy manual pattern](#legacy-manual-pattern-backward-compatibility-only) at the bottom of this page only if you already have an existing integration and cannot migrate — new integrations should follow FCM Mode.

## Why FCM Mode

FCM has two payload shapes and each has a problem:

- **`notification` payload**: the FCM SDK auto-displays on Android. If you also call `displayNotification` from your background handler you get two tray entries, and custom `data` is routed only to the tap `PendingIntent` so the library's query APIs can't see it.
- **`data`-only payload**: clean on Android, but iOS treats these as silent pushes and drops 30–60% on real devices.

FCM Mode picks the right payload per platform (data-only on Android, alert + `mutable-content: 1` on iOS) but hides the asymmetry behind a single developer API. A Notification Service Extension on iOS reads the shared `notifee_options` blob and reshapes the notification so you keep full display control while getting APNs reliability.

See [FCM Mode](/fcm-mode) for the full architecture, payload schema, migration guide, and troubleshooting.

## Prerequisites

- An active [Firebase](https://console.firebase.google.com/) project.
- [`@react-native-firebase/app`](https://www.npmjs.com/package/@react-native-firebase/app) and [`@react-native-firebase/messaging`](https://www.npmjs.com/package/@react-native-firebase/messaging) installed and configured.

See the [React Native Firebase quick start](https://rnfirebase.io) and the [messaging setup guide](https://rnfirebase.io/messaging/usage) for the Firebase-side configuration.

## Quick start (FCM Mode)

### 1. Server: build the payload

The server SDK ships with the main package under the `react-native-notify-kit/server` subpath export. It has zero runtime dependencies and is meant for Node.js / Firebase Cloud Functions.

```ts
// server/sendNotification.ts
import { buildNotifyKitPayload } from 'react-native-notify-kit/server';
import * as admin from 'firebase-admin';

admin.initializeApp();

export async function sendOrderUpdate(deviceToken: string, orderId: string) {
  const message = buildNotifyKitPayload({
    token: deviceToken,
    notification: {
      id: `order-${orderId}`,
      title: 'Your order is on the way',
      body: 'Tap to see live tracking.',
      data: { orderId },
      android: {
        channelId: 'orders',
        smallIcon: 'ic_notification',
        pressAction: { id: 'open-order', launchActivity: 'default' },
      },
      ios: {
        sound: 'default',
        interruptionLevel: 'timeSensitive',
      },
    },
    options: { ttl: 3600 },
  });

  await admin.messaging().send(message);
}
```

`buildNotifyKitPayload` returns a Firebase Admin-compatible message that is data-only on Android and alert-style on iOS. Firebase Admin serializes it to the FCM HTTP v1 request format. `options.ttl` is expressed in seconds; the builder performs the Android millisecond conversion. Both platforms carry an identical `notifee_options` blob.

### 2. Android client: wire `handleFcmMessage`

`handleFcmMessage` is a one-liner that parses the server payload, reconstructs a `Notification` object, and displays it through the usual Notify Kit pipeline.

```js
// index.js
import { AppRegistry } from 'react-native';
import messaging from '@react-native-firebase/messaging';
import notifee, { AndroidImportance } from 'react-native-notify-kit';
import App from './App';

notifee.setFcmConfig({
  defaultChannelId: 'default',
  defaultPressAction: { id: 'default', launchActivity: 'default' },
});

notifee.createChannel({ id: 'default', name: 'Default', importance: AndroidImportance.HIGH });
notifee.createChannel({ id: 'orders', name: 'Orders', importance: AndroidImportance.HIGH });

messaging().setBackgroundMessageHandler(async remoteMessage => {
  await notifee.handleFcmMessage(remoteMessage);
});

AppRegistry.registerComponent('MyApp', () => App);
```

```tsx
// App.tsx — foreground
import { useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
import notifee from 'react-native-notify-kit';

export default function App() {
  useEffect(() => messaging().onMessage(m => notifee.handleFcmMessage(m)), []);
  // ...
}
```

### 3. iOS client: scaffold the Notification Service Extension

From your project root:

```bash
npx react-native-notify-kit init-nse
```

The CLI patches `.pbxproj` and `Podfile` automatically and generates a `NotifyKitNSE` target using `NotifeeExtensionHelper`. Supports `--dry-run`, `--force`, `--target-name`, `--ios-path`, and `--bundle-suffix` options. Rerun `pod install` and rebuild.

On iOS, `handleFcmMessage` is a no-op in background/killed (the NSE has already displayed the notification); in foreground it displays the banner as usual.

### Next steps

For the full reference (server builders, client config, payload schema, migration from the manual pattern, troubleshooting, known limitations) see the [FCM Mode guide](/fcm-mode).

## Creating and storing device tokens

Independent of FCM Mode, you still need device tokens to target specific devices. React Native Firebase's messaging API handles this:

```js
import messaging from '@react-native-firebase/messaging';

async function registerDeviceToken() {
  await messaging().registerDeviceForRemoteMessages();
  const token = await messaging().getToken();
  await postToApi('/users/me/tokens', { token });
}
```

Fetch and update the token on every app boot in case it has changed, and consider listening to [`onTokenRefresh`](https://rnfirebase.io/reference/messaging#onTokenRefresh) while the app is open.

## Legacy manual pattern (backward compatibility only)

> This section is retained only for users with an **existing** integration built on the upstream Notifee manual pattern who cannot migrate right now. **New integrations should use FCM Mode instead.**
>
> The legacy pattern bypasses FCM Mode's iOS NSE/alert handling, so iOS behavior differs from Android: silent pushes are throttled by APNs (30–60% drop rate is typical), there is no automatic attachment handling, and no foreground customization via NSE. These are inherent trade-offs of the approach and are the reason FCM Mode exists.

The pattern sends a data-only FCM payload with a serialized notification object and calls `displayNotification` on the client:

```js
// Node.js
await admin.messaging().sendMulticast({
  tokens,
  data: {
    notifee: JSON.stringify({
      title: 'Your order has been shipped',
      body: 'This message was sent via FCM!',
      android: {
        channelId: 'default',
        pressAction: { id: 'default', launchActivity: 'default' },
      },
    }),
  },
});
```

```js
// React Native
import notifee from 'react-native-notify-kit';
import messaging from '@react-native-firebase/messaging';

function onMessageReceived(message) {
  notifee.displayNotification(JSON.parse(message.data.notifee));
}

messaging().onMessage(onMessageReceived);
messaging().setBackgroundMessageHandler(onMessageReceived);
```

Every property in FCM `data` must be a string — that's why the notification object is JSON-stringified before sending.

If you're maintaining an existing integration like this and want to migrate, see the [migration from the manual pattern](/fcm-mode#migration-from-the-manual-pattern) section of the FCM Mode guide.

## Further reading

- [FCM Mode](/fcm-mode) — full guide for the recommended path
- [FCM: send messages to specific devices](https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-to-specific-devices)
- [FCM: send messages to topics](https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-to-topics)
- [FCM: batched messages](https://firebase.google.com/docs/cloud-messaging/send-message#send-a-batch-of-messages)
