Personalization Reference
The Inbox can be personalized at every level — from swapping the bell icon, to per-row layout, to fully custom popovers and routing. This reference covers render props, click handling, conditional display, HTML content, and composing the Inbox primitives inside your own UI.Render props
Render props let you replace specific parts of the Inbox while keeping the surrounding chrome (default actions, hover states, animations, accessibility).| Prop | Replaces | Keep default actions? |
|---|---|---|
renderBell | Bell icon | N/A |
renderAvatar | Notification avatar | ✅ |
renderSubject | Subject line | ✅ |
renderBody | Body text | ✅ |
renderDefaultActions | Mark-as-read / archive / snooze buttons | ❌ (you implement them) |
renderCustomActions | Primary + secondary action buttons | ✅ |
renderNotification | Entire notification row | ❌ (you implement everything) |
renderBell
Receives the unread count broken down by severity:
renderAvatar
renderSubject / renderBody
renderDefaultActions
Replaces the built-in mark-as-read / archive / snooze affordances. You’re responsible for re-implementing them.
renderCustomActions (primary / secondary buttons)
Useful for matching brand button styles without re-implementing default actions:
renderNotification (full takeover)
Use sparingly — you lose all built-in affordances:
Conditional display
renderNotification receives the full notification object, including tags, data, severity, and workflow. Branch on whichever signal best fits the UI.
By workflow tag
By workflow identifier
By data object
By severity
HTML in notification content
By default Novu sanitizes thesubject and body to prevent XSS. To allow rich HTML:
- In the workflow — open the In-App step editor and toggle on Disable content sanitization.
- In the Inbox — render the field with
dangerouslySetInnerHTML.
Only enable this if you fully control the trigger payload. Raw HTML opens an XSS surface area.
Body only
Subject only
Both subject and body
Notification click behavior
routerPush integration
When a notification has a redirect.url defined in the workflow, Novu calls routerPush(url) so navigation stays inside your SPA router.
onNotificationClick
Override click behavior entirely (open a drawer, modal, etc.):
onPrimaryActionClick / onSecondaryActionClick
Custom popover
The<Inbox> component is composable. When passed children, it acts as a context provider — drop the feed into any popover, drawer, or page.
| Component | Renders |
|---|---|
<Bell /> | Bell icon trigger |
<Notifications /> | Header + scrollable list + footer (no Preferences page) |
<InboxContent /> | Same as <Notifications /> plus the Preferences page |
<Preferences /> | Standalone preferences |
Standalone notification feed (no popover)
Popover with Radix UI
Custom popover with shadcn Drawer
Full-page notification center
appearance, localization, tabs, routerPush, render props, context) flow through the <Inbox> provider and apply to children automatically.
Localization
Override Inbox UI text per locale. Localization changes UI chrome only — to translate notification content, use Workflow Translations.defaultLocalization.ts.
Localizing workflow names
localization.dynamic is a Record<workflowId, string> used to display friendly workflow names in the Preferences UI:
Multi-language switching pattern
Tabs
Group notifications into filtered tabs:tags: workflow-level. Multiple tags useORlogic.severity: from the In-App step’s severity. Accepts a single value or an array.data: matches keys defined in the In-App step’s data object.- Combine
tags+data+severityfor narrower filters.
useCounts hook.