<Inbox />

Learn how to use and customize the Inbox component in your React application

By default, the <Inbox /> renders a bell button, that opens a popover on click. The popover contains the notifications list and the user preferences.

Basic Usage

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox applicationIdentifier="YOUR_APPLICATION_IDENTIFIER" subscriberId="YOUR_SUBSCRIBER_ID" />
  );
}

The Inbox component uses the routerPush prop to make your notifications navigatable. We will automatically pass the redirect.url from your workflow definitions to the routerPush prop.

To make the navigation work, you will need to specify the routerPush behaviour depending on your routing library.

import { Inbox } from '@novu/nextjs';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
    />
  );
}

Event Handling

Notification Click

You can handle notification clicks without navigation by using the onNotificationClick prop. This is useful for opening modals or drawers instead of navigating to a page.

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      onNotificationClick={(notification) => {
        // your logic to handle notification click
      }}
    />
  );
}

Action Clicks

Handle action button clicks without navigation using the onPrimaryActionClick and onSecondaryActionClick props:

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      onPrimaryActionClick={(notification) => {
        // your logic to handle primary action click
      }}
      onSecondaryActionClick={(notification) => {
        // your logic to handle secondary action click
      }}
    />
  );
}

Customization

Controlled Popover State

import { Inbox } from '@novu/react';
import { useState } from 'react';
 
function Novu() {
  const [open, setOpen] = useState(false);
 
  return (
    <>
      <Inbox
        applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
        subscriberId="YOUR_SUBSCRIBER_ID"
        open={open}
      />
      <button onClick={() => setOpen(!open)}>Toggle Inbox</button>
    </>
  );
}

Custom Notification Item

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      renderNotification={(notification) => (
        <div>
          <h3>{notification.subject}</h3>
          <p>{notification.body}</p>
        </div>
      )}
    />
  );
}

Custom Notification Subject

Render a custom subject for the notification, while keeping the default notification component.

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      renderSubject={(notification) => (
        <div>
          <p>{notification.subject}</p>
        </div>
      )}
    />
  );
}

Custom Notification Body

Render a custom body for the notification, while keeping the default notification component.

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      renderBody={(notification) => (
        <div>
          <p>{notification.body}</p>
        </div>
      )}
    />
  );
}

Custom Bell

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      renderBell={(unreadCount) => (
        <div>
          <span>{unreadCount}</span>
        </div>
      )}
    />
  );
}

Filtering Preferences

Customize visible preferences using the preferencesFilter prop to display only relevant preferences to your users. The filtering works by matching workflow tags with the specified filter tags value.

import { Inbox } from '@novu/react';
 
function Novu() {
  return (
    <Inbox
      applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
      subscriberId="YOUR_SUBSCRIBER_ID"
      preferencesFilter={{ tags: ['general', 'admin', 'security'] }}
    />
  );
}

Data object

The data object is a key-value store within each notification, used to extend <Inbox /> notifications by embedding step-specific metadata. It provides flexible notification handling, supporting both static and dynamic values:

  • Static Values: These are hardcoded into the notification step—for example, a string like "status": "merged" or "icon": "heart". These values don’t change based on the recipient or context.
  • Dynamic Values: These values are derived from subscriber or payload data. For instance, they can reference subscriber.firstName or payload.issueId to tailor notifications for individual users.

You can pass data such as:

  • reactionType: To display specific icons such as 👍, ❤️, or a comment bubble.
  • entityId (like pullRequestId or issueId): Create direct links or show relevant badges (e.g., a GitHub logo linking to the PR).
  • status or actionType: To show visual cues such as colored dots or status icons (e.g., green for 'merged', orange for 'commented').
Data object for in-app Inbox step

The data object is defined within a workflow's in-app step in the Novu dashboard. Each key-value pair, referred to as a property, can be static or dynamic, and you get up to 10 properties per in-app step. These properties are accessible on the frontend via the notification.data property.

import { Inbox } from '@novu/react';
 
<Inbox
  applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
  subscriberId="YOUR_SUBSCRIBER_ID"
  renderNotification={(notification) => (
    <div>
      <p>{notification.data?.customKey}</p>
      <p>{notification.data?.dataId}</p>
    </div>
  )}
/>

notification.data is included in the client response, so do not store any sensitive data in it.

By default, notification.data is untyped. To ensure type safety, declare the NotificationData interface globally.

declare global {
  interface NotificationData {
    customKey?: string;
    dataId?: number;
  }
}

This lets TypeScript infer the structure of notification.data, preventing errors when accessing properties. However, as not all notifications include the same keys, check properties for existence before usage.

On this page