<CourierInbox />: inbox for displaying and managing messages<CourierInboxPopupMenu />: popup menu version of the inbox<CourierToast />: toast notifications for time-sensitive alerts<CourierPreferences />: preference center for topic subscriptions and deliveryuseCourier(): composable for custom UIs
Installation
Available on GitHub and npm.vue (>= 3.3) is a peer dependency.
Not using Vue? Use the
instead. Its elements work in any JavaScript project.
Authentication
Courier authenticates with a JWT that your backend mints with your Courier API key, never in client code. is the full guide: the token flow, scope strings, reading auth state, signing out, and token refresh. Using the EU datacenter? See .Quick start
Add the inbox component to your app. Courier components are normal Vue components. Import them and use them in your template.Component reference
Each component’s props, theme, callbacks, and custom-render surface live with the feature. These links open on the Vue tab.
Bind a render prop in kebab-case. Vue lowercases attribute names, so
:render-list-item reaches the component and :renderListItem doesn’t. A custom render must also return a Vue node built with h(), not a string of markup. A string renders nothing.
The CourierInboxTheme, CourierToastTheme, and CourierPreferencesTheme objects are the same on React, Vue, Angular, and the Web Components, so each is documented once: , , .
useCourier composable
TheuseCourier() composable gives you programmatic access to Courier. Use it to build custom UIs. It returns the same shape as the React hook, but auth, inbox, and toast are Vue shallowRefs. Access them with .value in <script setup>. They auto-unwrap in templates.
When to use the composable vs components
- Components (
<CourierInbox />,<CourierToast />): quick integration with the default UI - Composable (
useCourier()): custom UIs, programmatic control, state management - Both together: the composable manages state, components render
Composable return value
inbox.value.listenForUpdates() after authentication to open the realtime connection. Without it, the inbox loads once from the initial fetch and doesn’t update again.
Complete example: authentication, inbox setup, real-time updates, and displaying messages. Templates auto-unwrap the refs (inbox.totalUnreadCount, inbox.feeds[...]):
inbox slice exposes is in . Read them off inbox.value in <script setup>, and off inbox in a template.
Advanced
Server-side rendering
Courier Inbox and Toast render client-side only. They mount inonMounted, which never runs during SSR. They work with Nuxt and other SSR setups without extra configuration, rendering once on the client.
Troubleshooting
Inbox not updating in real-time
Inbox not updating in real-time
Call
inbox.value.listenForUpdates() after authentication. It opens the WebSocket connection required for real-time updates.Messages not loading
Messages not loading
Possible causes:
- Not authenticated: call
signIn() - Feeds not registered: call
registerFeeds()beforeload() - Network errors: check
inbox.value.errorfor details - JWT expired: generate a new token
Authentication errors
Authentication errors
- Invalid JWT: generate the JWT correctly on your backend
- Expired JWT: JWTs expire. Generate a new one
- Missing scopes: include
inbox:read:messagesandinbox:write:eventsin the JWT - Wrong user ID: the
userIdmust match the user the JWT was issued for
Custom slots not rendering
Custom slots not rendering
Custom render props must return a Vue node built with
h() (imported from vue), not a raw string of markup. Bind the render prop with :render-list-item="..." (kebab-case) on the component.TypeScript errors
TypeScript errors
Import types directly from the package:
Best practices
- JWT security: always generate JWTs server-side. Cache on the client, refresh before expiration (standard:
'1d'), and include only the scopes you need. - Performance:
canUseCache: true(default) serves cached data. Set a suitablesetPaginationLimit(). The composable’sshallowRefs update on their own, so avoid unnecessary re-renders. - Testing: mock
useCourier()in tests to return test data: