Skip to main content
Technology & EngineeringNotification Services308 lines

Notifee

Integrate Notifee for robust local notification management within your React Native applications.

Quick Summary23 lines
You are a React Native developer proficient in building engaging mobile experiences, leveraging Notifee to deliver rich and timely local notifications. Notifee empowers you to control the notification experience across iOS and Android, handling everything from basic alerts to complex interactive messages and deep linking.

## Key Points

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
*   **Provide Clear Press Actions:** Make sure `pressAction` leads users to the most relevant part of your application when they tap a notification. Use `data` to pass context for deep linking.

## Quick Example

```bash
npm install --save @notifee/react-native
# OR
yarn add @notifee/react-native
```

```bash
cd ios && pod install && cd ..
```
skilldb get notification-services-skills/NotifeeFull skill: 308 lines
Paste into your CLAUDE.md or agent config

You are a React Native developer proficient in building engaging mobile experiences, leveraging Notifee to deliver rich and timely local notifications. Notifee empowers you to control the notification experience across iOS and Android, handling everything from basic alerts to complex interactive messages and deep linking.

Core Philosophy

Notifee's core philosophy is to provide a comprehensive, consistent, and highly customizable API for local notifications in React Native. It abstracts away the platform-specific complexities of iOS User Notifications and Android Notification Channels, offering a unified JavaScript interface. You choose Notifee when your application needs to generate notifications directly from the device (e.g., reminders, alarms, progress updates, or background task completion) without necessarily involving a server-side push mechanism like Firebase Cloud Messaging (FCM).

The service emphasizes control and flexibility, allowing you to define rich notification content, action buttons, categories, and deep linking behaviors. It is designed to work seamlessly across different application states – foreground, background, and even when the app is killed – ensuring your users receive critical information reliably. Notifee enhances user engagement by delivering relevant, timely alerts that can drive users back into your application at key moments.

Setup

Integrating Notifee into your React Native project involves installing the library and handling platform-specific configurations, primarily for iOS.

Installation

First, install the Notifee package:

npm install --save @notifee/react-native
# OR
yarn add @notifee/react-native

iOS Configuration

For iOS, you need to install the native modules and ensure background fetching is enabled if you plan to use background events.

cd ios && pod install && cd ..

To handle notifications when your app is in the background or killed, ensure your AppDelegate.m (or AppDelegate.mm) includes the Notifee setup for background message handling.

// AppDelegate.m (or AppDelegate.mm)

#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Notifee/NotifeeReactNativeEventEmitter.h> // Import Notifee

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // ... existing code ...

  // Notifee setup for background notifications
  [NotifeeReactNativeEventEmitter application:application didFinishLaunchingWithOptions:launchOptions];

  return YES;
}

// Required for the notification event. You must call the completion handler after processing the
// notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [NotifeeReactNativeEventEmitter application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

// Required for the registration of the device token.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [NotifeeReactNativeEventEmitter application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

// Required for the notification registration error.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  [NotifeeReactNativeEventEmitter application:application didFailToRegisterForRemoteNotificationsWithError:error];
}

@end

Android Configuration

Android typically requires no additional manual setup beyond package installation. Notifee automatically handles the necessary permissions and service declarations. However, you should ensure your app requests notification permissions at an appropriate time.

Key Techniques

1. Requesting Permissions and Displaying a Basic Notification

Before displaying notifications, you should request user permissions. Once granted, you can display a simple notification using displayNotification. On Android, it's good practice to create a notification channel first.

import notifee, { AndroidImportance, AndroidCategory } from '@notifee/react-native';

async function requestNotificationPermissionsAndDisplay() {
  // Request permissions for iOS and Android T (API 33+)
  const settings = await notifee.requestPermission();

  if (settings.authorizationStatus) { // Check if permissions are granted
    // Create a channel for Android (required for Android 8.0+)
    const channelId = await notifee.createChannel({
      id: 'default',
      name: 'Default Channel',
      importance: AndroidImportance.HIGH,
      sound: 'default', // Optional: 'default' or a custom sound
      vibration: true,
      category: AndroidCategory.REMINDER,
    });

    // Display a notification
    await notifee.displayNotification({
      id: '123', // Unique ID for the notification
      title: 'Hello there!',
      body: 'This is a basic notification from Notifee.',
      android: {
        channelId,
        smallIcon: 'ic_launcher', // Required for Android
        color: '#9c27b0', // Optional: accent color
        pressAction: {
          id: 'default', // Action ID when the notification is pressed
        },
      },
      ios: {
        sound: 'default',
      },
    });
    console.log('Notification displayed successfully!');
  } else {
    console.log('User denied notification permissions.');
  }
}

// Call this function when appropriate, e.g., after user onboarding
// requestNotificationPermissionsAndDisplay();

2. Handling Notification Interactions and Deep Linking

Notifee allows you to listen for user interactions with notifications, both when the app is in the foreground and when it's opened from a notification (background/killed state). This is crucial for deep linking.

import notifee, { EventType } from '@notifee/react-native';
import { Linking } from 'react-native';

// 1. App in foreground: Listen for events while the app is active
notifee.onForegroundEvent(({ type, detail }) => {
  switch (type) {
    case EventType.DISMISSED:
      console.log('User dismissed notification:', detail.notification);
      break;
    case EventType.PRESS:
      console.log('User pressed notification:', detail.notification);
      if (detail.notification?.data?.targetScreen) {
        Linking.openURL(`myapp://${detail.notification.data.targetScreen}`);
      }
      break;
  }
});

// 2. App in background/killed: Get the initial notification that opened the app
async function configureInitialNotification() {
  const initialNotification = await notifee.getInitialNotification();

  if (initialNotification) {
    console.log('App opened by notification:', initialNotification.notification);
    if (initialNotification.notification.data?.targetScreen) {
      Linking.openURL(`myapp://${initialNotification.notification.data.targetScreen}`);
    }
  }
}

// Call this once when your app starts up, e.g., in App.tsx useEffect
// useEffect(() => {
//   configureInitialNotification();
// }, []);

// Example of displaying a notification with deep link data:
async function displayDeepLinkNotification() {
  const channelId = await notifee.createChannel({
    id: 'deep_link',
    name: 'Deep Link Channel',
    importance: AndroidImportance.HIGH,
  });

  await notifee.displayNotification({
    title: 'New message!',
    body: 'You have a new message from Alice.',
    data: { targetScreen: 'chat/alice' }, // Custom data for deep linking
    android: {
      channelId,
      smallIcon: 'ic_launcher',
      pressAction: {
        id: 'open_chat', // Custom action ID
        launchActivity: 'default', // Opens the main activity
      },
    },
    ios: {
      sound: 'default',
      categoryId: 'new_message', // For iOS custom actions
    },
  });
}

3. Rich Notifications with Actions and Images

Notifee supports displaying rich content like large images and adding interactive action buttons to notifications.

import notifee, {
  AndroidImportance,
  AndroidStyle,
  AndroidPressAction,
  NotificationPressActionType,
} from '@notifee/react-native';

async function displayRichNotification() {
  const channelId = await notifee.createChannel({
    id: 'rich_content',
    name: 'Rich Content Channel',
    importance: AndroidImportance.HIGH,
  });

  await notifee.displayNotification({
    title: 'Image Notification',
    body: 'This notification features a large image and action buttons.',
    android: {
      channelId,
      smallIcon: 'ic_launcher',
      color: '#007bff',
      pressAction: {
        id: 'default',
        launchActivity: 'default',
      },
      // Large image attachment
      style: {
        type: AndroidStyle.BIGPICTURE,
        picture: 'https://cdn.notifee.app/images/web-feature-image.png',
      },
      actions: [
        {
          title: 'Reply',
          icon: 'https://cdn-icons-png.flaticon.com/512/107/107147.png', // Or use a local resource
          pressAction: {
            id: 'reply',
            launchActivity: 'default',
            // input: true, // For direct reply input on Android N+
          },
        },
        {
          title: 'View Details',
          pressAction: {
            id: 'view_details',
            launchActivity: 'default',
          },
        },
      ],
    },
    ios: {
      sound: 'default',
      attachments: [
        {
          url: 'https://cdn.notifee.app/images/web-feature-image.png',
          thumbnailClippingRect: { x: 0, y: 0, width: 1, height: 0.5 }, // Optional cropping
        },
      ],
      // For iOS custom actions, you typically define categories in your native project
      // and link them here.
      // categoryId: 'my_custom_category',
    },
  });
}

// Example of handling action button presses:
notifee.onForegroundEvent(({ type, detail }) => {
  if (type === EventType.ACTION_PRESS) {
    console.log('Action pressed:', detail.pressAction?.id, 'Notification:', detail.notification);
    if (detail.pressAction?.id === 'reply') {
      // Handle reply logic, maybe open a specific screen with input
      console.log('Reply button pressed');
      // If input was enabled: console.log('Reply text:', detail.input);
    } else if (detail.pressAction?.id === 'view_details') {
      // Navigate to a details screen
      console.log('View Details button pressed');
    }
    // Optionally dismiss the notification after action
    if (detail.notification?.id) {
      notifee.cancelNotification(detail.notification.id);
    }
  }
});

Best Practices

  • Proactively Request Permissions: Always request notification permissions at an opportune moment, such as after a user explicitly opts in or during a relevant onboarding step, rather than on app launch.
  • Utilize Android Channels: Design a clear channel strategy for Android. Channels allow users fine-grained control over notification preferences (sound, vibration, importance) for different types of messages from your app.
  • Handle All App States: Ensure your notification interaction logic (especially deep linking) correctly handles notifications received when the app is in the foreground, background, or completely killed, using onForegroundEvent and getInitialNotification.
  • Provide Clear Press Actions: Make sure pressAction leads users to the most relevant part of your application when they tap a notification. Use data to pass context for deep linking.
  • Manage Notification IDs: Assign unique, meaningful IDs to your notifications. This allows you to update existing notifications (by calling displayNotification with the same ID) or cancel specific ones using cancelNotification.
  • Keep Content Concise and Actionable: Notifications should be brief, informative, and immediately tell the user why they are being notified and what action they can take. Avoid verbose messages.
  • Test Extensively: Test your notification implementation thoroughly on both iOS and Android, across various device models and OS versions, and in all app states (foreground, background, killed) to ensure reliable delivery and interaction.

Anti-Patterns

  • Ignoring Permissions. You attempt to display a notification without first requesting and confirming notification permissions. Do this instead: Always call notifee.requestPermission() and check its authorizationStatus before displaying any notification.
  • Lack of Android Channel Strategy. You display all notifications on a single, generic Android channel or no channel at all (pre-Android O). Do this instead: Create distinct channels for different notification types, giving users control over their preferences for each.
  • No Deep Link Handling. Notifications are displayed but do not navigate the user to relevant content within the app when pressed. Do this instead: Pass relevant data with your notifications and use onForegroundEvent and getInitialNotification to perform deep linking based on that data.
  • Over-notifying Users. You send too many non-critical notifications, leading to user fatigue and potentially causing users to disable notifications for your app. Do this instead: Be judicious with notifications, prioritize high-value alerts, and

Install this skill directly: skilldb add notification-services-skills

Get CLI access →