Blog
PRODUCT NEWS
ENGINEERING

Inbox SDKs for Vue and Angular: a native in-app notification center

MM

Mike Miller

June 19, 2026

Inbox SDKs for Vue and Angular: a native in-app notification center — cover

The same drop-in inbox that powers React and JavaScript apps, now with first-class Angular and Vue components.

Courier Inbox now has native SDKs for Angular and Vue. You get the full notification center, toasts, and a preferences center as real components that fit your framework's conventions, not a generic web component you have to wrap yourself.

Building an in-app notification feed from scratch is more work than it looks. You need real-time updates over a WebSocket, read and unread state, archiving, pagination, tabs, theming, and a preferences UI so users can control what they receive. Until now, Angular and Vue teams either hand-rolled all of that or wrapped our framework-agnostic web components by hand. These SDKs do that wrapping for you, the right way for each framework.

What the Angular and Vue SDKs give you

Both SDKs wrap Courier Inbox, our drop-in in-app notification center, in idiomatic components and a programmatic layer. You install one package and get the inbox, toasts, and preferences, plus a way to build custom UIs when the defaults aren't enough.

A real-time inbox in a few lines

The headline component is the inbox itself. Import it, authenticate your user, and you have a working notification center with real-time updates, read and unread state, archiving, and infinite-scroll pagination.

In Angular, the components are standalone, so there's no NgModule to wire up. Import the component class, inject CourierService, and sign in:

import { AfterViewInit, Component, inject } from "@angular/core";
import { CourierInboxComponent, CourierService } from "@trycourier/courier-angular";
@Component({
selector: "app-root",
standalone: true,
imports: [CourierInboxComponent],
template: `<courier-inbox></courier-inbox>`,
})
export class AppComponent implements AfterViewInit {
private readonly courier = inject(CourierService);
ngAfterViewInit(): void {
// Generate this JWT on your backend, never in client-side code
const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
this.courier.signIn({ userId: "your-user-id", jwt });
}
}

In Vue 3, the components are normal Vue components and the useCourier() composable handles auth:

<script setup lang="ts">
import { onMounted } from "vue";
import { CourierInbox, useCourier } from "@trycourier/courier-vue";
const courier = useCourier();
onMounted(() => {
// Generate this JWT on your backend, never in client-side code
const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
courier.shared.signIn({ userId: "your-user-id", jwt });
});
</script>
<template>
<CourierInbox />
</template>

The same JWT auth flow applies in both: your backend calls Courier's issue-token endpoint, returns the token to your client, and the SDK takes it from there. Your API keys never touch the browser.

Tabs, feeds, and filtering

Organize messages with feeds and tabs. A feed is a container that groups related tabs, and each tab is a filtered view. You can filter by tags, read or unread status, and archived state, and the filters combine with AND logic.

In Angular you pass them with the [feeds] input:

feeds: CourierInboxFeed[] = [
{
feedId: "notifications",
title: "Notifications",
tabs: [
{ datasetId: "all-notifications", title: "All", filter: {} },
{ datasetId: "unread-notifications", title: "Unread", filter: { status: "unread" } },
{ datasetId: "important", title: "Important", filter: { tags: ["important"] } },
{ datasetId: "archived", title: "Archived", filter: { archived: true } },
],
},
];

Vue takes the same structure through the :feeds prop. If there's only one feed, the feed dropdown hides itself. If a feed has one tab, the tab bar disappears and the unread count sits next to the feed title. The defaults stay out of your way until you need the structure.

Toasts and a preferences center

Both SDKs include more than the feed. CourierToast (<courier-toast> in Angular, <CourierToast /> in Vue) shows short-lived notifications for time-sensitive alerts, with optional auto-dismiss and a countdown bar. It's connected to the same inbox message feed, so a toast and the inbox stay in sync.

CourierPreferences gives your users a built-in preferences center to manage which topics they're subscribed to and how each one is delivered, including per-channel routing and digest schedules. It needs a JWT with the read:preferences and write:preferences scopes, and that's the whole setup. You don't build a preferences UI, you embed one.

Theming that matches your app

Every component takes a theme object for light and dark modes. Pass it directly; the component serializes it for you. The theme covers the popup trigger button, the inbox header, feeds, tabs, the message list, and the loading, empty, and error states.

theme: CourierInboxTheme = {
inbox: {
header: { filters: { unreadIndicator: { backgroundColor: "#8B5CF6" } } },
list: { item: { unreadIndicatorColor: "#8B5CF6" } },
},
};

The theme object is identical across every Courier Inbox SDK, so a theme you tuned for your React app drops straight into Angular or Vue. Helpers like defaultLightTheme, defaultDarkTheme, and mergeTheme let you start from the defaults and override only what you care about.

Building custom UIs

The ready-made components cover most cases. When you need full control, both SDKs expose the same data and actions the components use.

Angular ships an injectable CourierService that exposes auth, inbox, and toast state as RxJS observables, plus imperative methods for reading, archiving, and paginating messages. Vue ships the useCourier() composable, which returns the same shape with auth, inbox, and toast as Vue refs.

Here's the Vue composable driving a custom list:

<script setup lang="ts">
import { onMounted } from "vue";
import { useCourier, defaultFeeds } from "@trycourier/courier-vue";
const { auth, inbox } = useCourier();
onMounted(async () => {
auth.value.signIn({ userId: "your-user-id", jwt: "eyJhbGci..." });
inbox.value.registerFeeds(defaultFeeds());
await inbox.value.listenForUpdates(); // required for real-time updates
await inbox.value.load();
});
</script>
<template>
<div>Total unread: {{ inbox.totalUnreadCount ?? 0 }}</div>
<ul>
<li v-for="message in inbox.feeds['all_messages']?.messages ?? []" :key="message.messageId">
{{ message.title }}
</li>
</ul>
</template>

One thing worth calling out: after you authenticate, call listenForUpdates() to open the WebSocket connection. Without it, the inbox shows only the messages from the initial load and won't update in real time. It's the most common reason a custom inbox looks frozen.

You can also mix the two approaches. Use the service or composable for state and the components for rendering. And when you need an imperative method that isn't exposed directly, you can reach the underlying web component: a @ViewChild ElementRef in Angular, or the getElement() method off a template ref in Vue.

What you can build

  • A notification bell with a popup feed. Use CourierInboxPopupMenu with a custom menu button that shows the unread count, aligned wherever your header needs it.
  • A full-page activity feed. Drop in CourierInbox with feeds for "All," "Mentions," and "Archived," and let pagination load more as the user scrolls.
  • Real-time toasts for live events. Render CourierToast for time-sensitive alerts with auto-dismiss, while the same messages collect in the inbox for later.
  • A self-serve preferences page. Embed CourierPreferences so users manage topics, channels, and digest schedules without a support ticket or a custom settings screen.

Each of these would normally mean building real-time sync, state management, and a theming system yourself. Here they're a component and a sign-in call.

Works with your setup

Both SDKs render client-side only and wire up after mount (ngAfterViewInit in Angular, onMounted in Vue), so they work with Angular Universal, Nuxt, and other SSR setups without extra configuration. They render once on the client and skip the server entirely.

Angular needs @angular/core, @angular/common (both 17 or later), and rxjs 7+. Vue needs Vue 3.3 or later. If your workspace runs on Courier's EU datacenter, both packages re-export getCourierApiUrlsForRegion so you can point signIn at the right endpoints.

Available now

The Angular and Vue inbox SDKs are available today on npm.

  1. Install the package for your framework:
# Angular
npm install @trycourier/courier-angular
# Vue
npm install @trycourier/courier-vue
  1. Generate a JWT for your user on your backend with the inbox:read:messages and inbox:write:events scopes.
  2. Add the inbox component and call signIn.

Read the Angular SDK docs or the Vue SDK docs for the full component and API reference.

Already using a different framework? Nothing changes for you. The React SDK and the framework-agnostic @trycourier/courier-ui-inbox web components are still fully supported. The Angular and Vue packages share the same backend and theme system, so you can mix frameworks across apps and keep one consistent inbox experience.


Get started: Courier Inbox docs or the Angular and Vue SDK references.

Similar resources

Journeys Experiments cover
Product News

Experiments: A/B test your messages inside Journeys

Experiments bring A/B testing into Journeys. On any send node, run 2 to 10 message variants, split traffic by weight, and Courier buckets each recipient deterministically, keeping them in the same variant across sends. Compare sent, delivered, open, and click rates per variant, then promote the one you want, without leaving your journey or bolting on a separate testing tool.

By Thomas Schiavone

July 09, 2026

AI Translation: localize any template in seconds — cover
Product News

AI Translation: localize any template in seconds

Courier AI Translation brings built-in localization to Design Studio. Add a language to any template and AI translates every string in seconds. Works across email, SMS, push, in-app, and chat. Review side by side, override anything, and publish from the same editor you already use.

By Thomas Schiavone

June 26, 2026

What we shipped this month: May 2026 Edition — cover
Product News
Courier Updates
AI

What we shipped this month: May 2026 Edition

Courier shipped five launches in May 2026: AI Agent in Journeys (GA), the new Journeys API for code-driven flows, Custom Environments, Design Studio styling controls, and Courier Console v3. Each one closes a gap between writing software and shipping the messages that go with it.

By Kyle Seyler

May 20, 2026

Multichannel Notifications Platform for SaaS

Products

Platform

Integrations

Customers

Blog

API Status

Subprocessors

© 2026 Courier. All rights reserved.