Notifee (React Native)
A feature-rich Android and iOS notifications library for React Native, covering channels, triggers, styles, and interactive actions behind one typed API.
Repository Health
Technical Analysis
@notifee/react-native gives React Native apps a single, typed interface over Android and iOS’s very different notification systems. Instead of hand-rolling platform branches for channels, categories, and permissions, developers call one validated notifee.displayNotification()-style API and the library normalizes the object for whichever platform it runs on.
The library covers the full range of native notification capabilities: Android channels and channel groups, foreground services for long-running tasks, grouping/sorting, progress indicators, and rich styles (big picture, big text, messaging); on iOS it covers categories, critical alerts, attachments, and interaction handling. Triggers let notifications be scheduled for a future time or on a recurring interval without the host app staying alive.
As of 2026, the maintainers have marked the project as no longer actively maintained, and point users toward expo-notifications or the community fork react-native-notify-kit for ongoing support. The published package and its ~9.x releases remain functional and widely used, but new feature work and fixes are not expected going forward.
What You Get
- A unified
Notificationobject with Android- and iOS-specific sub-fields, validated before it ever reaches native code - Android channels, channel groups, and full-screen/foreground-service notification support
- iOS categories, critical alerts, attachments, and interactive notification actions
- Trigger-based scheduling for one-off and repeating notifications, independent of app lifecycle
- Rich notification styles (big picture, big text, messaging/conversation) on Android
- Foreground and background event handlers wired through React Native’s
AppRegistryheadless task system on Android andNativeEventEmitteron iOS - A
jest-mock.jsmodule shipped in the package specifically for mocking the native bridge in host-app unit tests
Common Use Cases
- Displaying local notifications for background task completion, downloads, or timers without a push service
- Building chat or messaging apps that need grouped, conversation-style Android notifications
- Scheduling reminder or recurring notifications (e.g. daily digests) that fire even when the app isn’t running
- Layering rich, interactive notification actions (reply, snooze, mark-as-read) on top of a push provider like FCM or OneSignal
- Running a foreground service notification for long-running Android background work (location tracking, audio playback)
Under The Hood
Architecture
NotifeeApiModule extends a base NotifeeNativeModule class that owns the React Native bridge connection and event emitter, and implements a Module interface describing the full public surface. Every public method funnels an incoming JS object through a dedicated validate* function (validateNotification, validateTrigger, validateAndroidChannel, validateIOSCategory, and others) that normalizes defaults and throws descriptive errors before the call is passed to this.native.<method>() and bridged to the platform-specific native module (io.invertase.notifee.NotifeeApiModule on Android, RNNotifee/NotifeeApiModule.m on iOS). Background event delivery is wired differently per platform inside the same class: Android registers a headless JS task via AppRegistry.registerHeadlessTask, while iOS listens through NativeEventEmitter. Because every call passes through the shared bridge class and its validators, a change to that base layer or the validation pipeline affects every public method at once.
Tech Stack
The package is TypeScript compiled to dist/ via tsc, published with react-native as a peer dependency ("*") so it targets whatever RN version the host app uses. It lives inside a Lerna- and Yarn-workspace-managed monorepo alongside a Flutter package and a Detox-driven example app (tests_react_native/), sharing a native iOS core (RNNotifeeCore.podspec) and a Gradle-built Android module. Version strings are generated at build time with genversion, and cross-language style is enforced with ESLint/Prettier for JS/TS, google-java-format for Android, and clang-format for iOS.
Code Quality
The packages/react-native/src tree itself has no unit test files; correctness for the validated JS API is instead exercised indirectly through a Jest workflow at the monorepo level and, more heavily, through a Detox end-to-end suite (tests_react_native/specs/notification.spec.ts, api.spec.ts) that runs the compiled library against real Android/iOS builds in CI (tests_e2e_android.yml, tests_e2e_ios.yml), plus a separate JUnit workflow for native Android code. Error handling in the validators is explicit — invalid input throws descriptive Errors rather than failing silently — and native error unwrapping has its own typed helper (NotifeeNativeError.ts). Naming is consistent (validate*, Notifee* prefixes) and the public types carry extensive inline JSDoc, but unit-level coverage for the JS validation logic is thin relative to how much of it there is; most confidence comes from the end-to-end device suite rather than isolated tests.
API Design
The library’s main design win is collapsing two very different native notification models — Android’s channels/groups/foreground-services and iOS’s categories/permissions/critical-alerts — behind one Notification object with android and ios sub-keys, so app code writes one call site instead of branching per platform. Every field on those types carries JSDoc that doubles as the source for the hosted API reference (via typedoc.config.mjs and a gen:reference script), and the shipped jest-mock.js removes the usual friction of mocking a native module in host-app tests. It’s a well-executed normalization layer over existing platform APIs rather than a novel notification mechanism.