useNotifications
Headless notification management built on createRegistry and createQueue. Registry stores the full notification lifecycle. Queue manages the toast display surface with FIFO ordering and auto-dismiss.
Installation
Install the Notifications plugin in your app’s entry point:
import { createApp } from 'vue'
import { createNotificationsPlugin } from '@vuetify/v0'
import App from './App.vue'
const app = createApp(App)
app.use(createNotificationsPlugin())
app.mount('#app')Usage
Once the plugin is installed, use the useNotifications composable in any component:
<script setup lang="ts">
import { useNotifications } from '@vuetify/v0'
const notifications = useNotifications()
function onSave () {
notifications.send({
subject: 'Changes saved',
severity: 'success',
timeout: 3000,
})
}
function onError () {
notifications.send({
subject: 'Build failed',
severity: 'error',
timeout: -1,
})
}
</script>
<template>
<button @click="onSave">
Save
</button>
</template>Architecture
createNotifications layers notification semantics on top of the registry and queue primitives, with plugin installation via createPluginContext:
API
| Method | Description |
|---|---|
send(input) | Create notification + enqueue for toast display |
register(input) | Create notification in registry only (no toast). Use for historical items |
queue | Queue context — queue.values(), queue.pause(), queue.resume() |
read(id) / unread(id) | Toggle read state |
seen(id) | Mark as seen |
archive(id) / unarchive(id) | Toggle archive state |
snooze(id, until) / wake(id) | Snooze with expiry |
readAll() / archiveAll() | Bulk operations |
onboard(items) | Bulk-register enriched notifications into registry (no toast) |
clear() | Remove all notifications from the registry |
dispose() | Tear down event listeners and clear the registry |
Examples
Notification Center
A single createNotifications instance powering four notification surfaces through the data.type field:
| Surface | Type | Behavior |
|---|---|---|
| Banner | 'banner' | Persistent, dismissible, max 1 visible. System announcements, trial expiry |
| Toast | 'toast' | Auto-dismissing via timeout. Action feedback: “Changes saved” |
| Inline | 'inline' | Contextual, embedded in page content. Rate limits, degraded service |
| Inbox | 'inbox' or none | Full lifecycle — read, archive, snooze. Collaboration, CI alerts |
The data bag drives routing — the composable doesn’t care how notifications render. Each surface filters items by data.type.
| File | Role |
|---|---|
context.ts | Wraps createNotifications with createContext for provide/inject |
NotificationProvider.vue | Renders all surfaces: banners, inbox dropdown, snackbar stack |
NotificationConsumer.vue | Triggers notifications — simulates real app events |
inbox.vue | Entry point wiring provider and consumer |
Click Simulate Event repeatedly to cycle through banner, snackbar, and inbox notifications. Open the Inbox to interact with read/archive/snooze. Notice how seen (badge count) and read (visual weight) are distinct — mirroring GitHub and Slack.
Click Simulate Event to push notifications
Adapters
Adapters connect external notification services to useNotifications. Each adapter handles mapping between the service’s SDK and the notification lifecycle. Import adapters from @vuetify/v0/notifications.
Knock
Knock↗ is a notification infrastructure platform with feeds, preferences, and multi-channel delivery. Install their JavaScript SDK↗ to get started. Supports both inbound (feed → notifications) and outbound (read/archive → Knock API).
import { createApp } from 'vue'
import { createNotificationsPlugin } from '@vuetify/v0'
import { createKnockAdapter } from '@vuetify/v0/notifications'
import { feed } from './plugins/knock'
import App from './App.vue'
const app = createApp(App)
app.use(
createNotificationsPlugin({
adapter: createKnockAdapter(feed),
})
)
app.mount('#app')import Knock from '@knocklabs/client'
export const knock = new Knock(import.meta.env.VITE_KNOCK_PUBLIC_KEY)
knock.authenticate(userId)
export const feed = knock.feeds.initialize(
import.meta.env.VITE_KNOCK_FEED_CHANNEL_ID
)Novu
Novu↗ is an open-source notification infrastructure with in-app feeds, digests, and multi-channel delivery. Install their JavaScript SDK↗ to get started. Supports both inbound (feed → notifications) and outbound (read/unread/seen/archive/unarchive → Novu API).
The adapter maps Novu severity strings to NotificationSeverity by default: critical/high → error, medium → warning, low → info. Pass a custom severity function to override.
import { createApp } from 'vue'
import { createNotificationsPlugin } from '@vuetify/v0'
import { createNovuAdapter } from '@vuetify/v0/notifications'
import { novu } from './plugins/novu'
import App from './App.vue'
const app = createApp(App)
app.use(
createNotificationsPlugin({
adapter: createNovuAdapter(novu),
})
)
app.mount('#app')import { Novu } from '@novu/js'
export const novu = new Novu({
subscriberId: userId,
applicationIdentifier: import.meta.env.VITE_NOVU_APP_ID,
})Functions
createNotifications
(options?: NotificationsOptions) => RcreateNotificationsContext
<_E>(_options?: NotificationsPluginOptions | undefined) => ContextTrinity<_E>createNotificationsPlugin
(_options?: NotificationsPluginOptions | undefined) => PluginuseNotifications
<_E>(namespace?: string) => _EOptions
Properties
queue
QueueContext<QueueTicketInput<unknown>, QueueTicket<QueueTicketInput<unknown>>>The toast display queue. Access `queue.values()`, `queue.pause()`, `queue.resume()`.
Methods
move
(id: ID, toIndex: number) => E | undefinedSeek for a ticket based on direction and optional predicate
seek
(direction?: "first" | "last", from?: number, predicate?: (ticket) => boolean) => E | undefinedon
<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => voidListen for registry events
off
<K extends Extensible<RegistryEventName>>(event: K, cb: EventHandler<E, K>) => voidStop listening for registry events
emit
<K extends Extensible<RegistryEventName>>(event: K, data: EventPayload<E, K>) => voidEmit an event with data
batch
<R>(fn: () => R) => RExecute operations in a batch, deferring cache invalidation and event emission until complete