Embed a customizable in-app notification center and toasts in your web app using Web Components. Works with any JavaScript framework.
The Courier Web Components SDK provides drop-in components for building notification experiences in any JavaScript project:
<courier-inbox> — full-featured inbox for displaying and managing messages
<courier-inbox-popup-menu> — popup menu version of the inbox
<courier-toast> — toast notifications for time-sensitive alerts
This is the latest version of the Courier Web Components SDK, recommended for new and existing apps.Coming from an earlier version? We recommend upgrading — check out the
migration guide for the React SDK, which
is a thin wrapper around these Web Components and exposes a similar API.
Available on GitHub and npm:
Inbox ·
Inbox ·
Toast ·
ToastThe Courier SDKs work with any JavaScript build system and do not require any additional build configuration.
Using React? Check out the Courier React SDK, which provides React components and hooks built on top of these Web Components.
To use the SDK, you need to generate a JWT (JSON Web Token) for your user. This JWT should always be generated by your backend server, never in client-side code.
Inbox and Toast share the same Courier.shared authentication instance and connection to the Courier backend. Authenticate once and both components work.
JWT Authentication Flow
1
Your client calls your backend
When your app needs to authenticate a user, your client
should make a request to your own backend (ex. GET https://your-awesome-app.com/api/generate-courier-jwt).
Development Authentication with cURLTo quickly test JWT generation for development only, you can use cURL to call the Courier Issue Token Endpoint directly.
Do not call the Issue Token API from client-side code. Always keep your Courier API keys secure.
Importing the Courier SDK registers Courier’s Web Components (<courier-inbox>, <courier-inbox-popup-menu>).
Copy
Ask AI
<body> <courier-inbox id="inbox"></courier-inbox> <script type="module"> import { Courier } from '@trycourier/courier-ui-inbox'; // Generate a JWT for your user on your backend server const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Authenticate the user with the inbox Courier.shared.signIn({ userId: $YOUR_USER_ID, jwt: jwt }); </script></body>
For the full reference of sign in parameters, see the Courier JS docs.
<courier-inbox-popup-menu>
Copy
Ask AI
<body> <div style="padding: 24px;"> <courier-inbox-popup-menu id="inbox"></courier-inbox-popup-menu> </div> <script type="module"> import { Courier } from '@trycourier/courier-ui-inbox'; // Generate a JWT for your user on your backend server const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Authenticate the user with the inbox Courier.shared.signIn({ userId: $YOUR_USER_ID, jwt: jwt }); </script></body>
Tabs and FeedsTabs and feeds allow you to organize and filter messages in your inbox. A feed is a container that groups related tabs together. Each tab represents a filtered view of messages.
If there is only one feed, the feed selection dropdown is hidden. If a feed has only one tab, the tab bar is hidden and the unread count appears next to the feed.
Filter Property
Type
Description
tags
string[]
Messages that have any of the specified tags
archived
boolean
Whether to include archived messages (defaults to false if unset)
Handle Clicks and PressesUse the onMessageClick(), onMessageActionClick(), and onMessageLongPress() methods to handle clicks and presses in the inbox.
onMessageLongPress() is only applicable on devices that support touch events.
Copy
Ask AI
<body> <courier-inbox id="inbox"></courier-inbox> <!-- Uncomment the line below to use the popup menu instead --> <!-- <courier-inbox-popup-menu id="inbox"></courier-inbox-popup-menu> --> <script type="module"> import { Courier } from '@trycourier/courier-ui-inbox'; // Generate a JWT for your user on your backend server const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Authenticate the user with the inbox Courier.shared.signIn({ userId: $YOUR_USER_ID, jwt: jwt }); const inbox = document.getElementById('inbox'); // Handle message clicks inbox.onMessageClick(({ message, index }) => { alert("Message clicked at index " + index + ":\n" + JSON.stringify(message, null, 2)); }); // Handle message action clicks (these are buttons on individual messages) inbox.onMessageActionClick(({ message, action, index }) => { alert( "Message action clicked at index " + index + ":\n" + "Action: " + JSON.stringify(action, null, 2) + "\n" + "Message: " + JSON.stringify(message, null, 2) ); }); // Handle message long presses (useful for mobile web) inbox.onMessageLongPress(({ message, index }) => { alert("Message long pressed at index " + index + ":\n" + JSON.stringify(message, null, 2)); }); </script></body>
Styles and ThemingThe fastest way to style the Courier Inbox to match your app is with a custom theme.
Call removeHeader() to remove the header entirely.The setHeader callback receives a props object with a feeds array. Each feed includes selection state, tabs with unread counts, and filter information.
Show Custom loading, empty, error, and pagination states
Subsequent pages of messages are loaded automatically when the user scrolls to the bottom of the inbox,
so the pagination component may only be visible briefly.
Programmatic ControlThe <courier-inbox> component exposes methods for programmatic control, allowing you to dynamically manage feeds, tabs, actions, and data refresh.Feed and Tab Selection
Method
Description
selectFeed(feedId)
Switch to the specified feed and load its data.
selectTab(tabId)
Switch to the specified tab within the current feed.
getFeeds()
Returns the current array of configured feeds.
currentFeedId (getter)
Returns the ID of the currently selected feed.
refresh()
Forces a reload of inbox data, bypassing the cache. Returns Promise<void>.
Header Actions
Method
Description
setActions(actions)
Set header actions. Action IDs: 'readAll', 'archiveRead', 'archiveAll'.
setListItemActions(actions)
Set list item actions. Action IDs: 'read_unread', 'archive_unarchive'.
Popup Menu Control (on <courier-inbox-popup-menu>)
Method
Description
showPopup()
Open the popup programmatically with transition animation.
closePopup()
Close the popup programmatically with transition animation.
Toasts are short-lived notifications that notify users and prompt them to take action.
The Toast component is connected to the feed of Courier Inbox messages.
Toasts are synced with the Inbox message feed. You can use both components together to provide persistent and temporary notifications.
<courier-toast>
Importing @trycourier/courier-ui-toast registers Courier’s Web Components (<courier-toast>).
Copy
Ask AI
<body> <courier-toast></courier-toast> <script type="module"> import { Courier } from "@trycourier/courier-ui-toast"; // Generate a JWT for your user on your backend server const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // Authenticate the user Courier.shared.signIn({ userId: $YOUR_USER_ID, jwt: jwt }); </script></body>
A note on terminology: toast refers to the entire stack of toasts managed by <courier-toast>, while toast item refers to a single toast displayed for a message.
Attribute
Type
Default
Description
auto-dismiss
boolean
false
Whether toast items should auto-dismiss.
auto-dismiss-timeout-ms
integer
5000
If auto-dismiss is enabled, the timeout in milliseconds before dismissal.
dismiss-button
"visible" | "hidden" | "hover" | "auto"
"auto"
Display option for the dismiss button. "auto" makes the button always visible if auto-dismiss is false, and visible on hover if auto-dismiss is true.
light-theme
json
undefined
JSON-stringified CourierToastTheme applied in light mode. Merged with defaults.
dark-theme
json
undefined
JSON-stringified CourierToastTheme applied in dark mode. Merged with defaults.
mode
"light" | "dark" | "system"
"system"
Theme mode for the toast component.
If the auto-dismiss attribute is set, the dismiss button (x) will only be visible on hover
and each toast item will automatically be dismissed. A countdown bar is shown to indicate the time
remaining before the toast disappears.Handle Clicks
API Method
Description
onToastItemClick(handler)
Called when a toast item is clicked.
onToastItemActionClick(handler)
Called when an action button on a toast item is clicked.
If a message contains actions, toast items
will include a button for each. By default, these buttons do not implement any functionality.
auto-dismiss and auto-dismiss-timeout-ms remain valid when using custom items. If auto-dismiss is true, custom items are automatically removed after the timeout.
Disable auto-dismiss. Items remain visible until manually dismissed.
setAutoDismissTimeoutMs(ms)
Set the auto-dismiss timeout in milliseconds.
setDismissButton(option)
Set dismiss button visibility: 'visible', 'hidden', 'hover', or 'auto'.
setMode(mode)
Set theme mode: 'light', 'dark', or 'system'.
setLightTheme(theme)
Set the light theme programmatically.
setDarkTheme(theme)
Set the dark theme programmatically.
Toast DatastoreCourierToastDatastore is the central repository of Inbox messages from which
<courier-toast> listens for messages to display and dismiss. It is a singleton accessed through CourierToastDatastore.shared.
Method
Description
addMessage(message)
Add a message to display as a toast. Messages must include messageId.
removeMessage(message)
Remove a message, dismissing any displayed toast for it.
Copy
Ask AI
import { CourierToastDatastore } from "@trycourier/courier-ui-toast";// Add a test message (useful for prototyping)CourierToastDatastore.shared.addMessage({ title: "Lorem ipsum dolor sit", body: "Lorem ipsum dolor sit amet", messageId: "abcd-1234-abcd-1234", actions: [{ "content": "Click me!" }]});// Remove a message (dismiss its toast)CourierToastDatastore.shared.removeMessage(message);