notifications
Every export of @kitr/notifications, @kitr/notifications/react, @kitr/notifications/provider, @kitr/notifications/driver, @kitr/notifications/drivers/web, @kitr/notifications/drivers/electron, @kitr/notifications/drivers/tauri, @kitr/notifications/drivers/capacitor, read from the published type definitions. The guide shows them in use.
@kitr/notifications
capacitorPush
function capacitorPush(): CapacitorPush;
Push notifications through @capacitor/push-notifications. Needs Firebase on Android
(google-services.json) and the Push Notifications capability on iOS; see the package docs.
createCapacitorNotificationsDriver
function createCapacitorNotificationsDriver(_options?: DriverOptions): Driver;
Notifications on @capacitor/local-notifications: the OS schedules and shows them, so scheduled
ones survive the app closing (the web driver's timers do not). On Android a channel becomes a
notification channel, created on first use. Taps from @capacitor/push-notifications reach
onTap too when that plugin is installed; its token and listeners are in capacitorPush().
createElectronNotificationsDriver
function createElectronNotificationsDriver(_options?: DriverOptions): ElectronNotificationsDriver;
The notifications driver for the Electron shell. Notifications are Electron Notifications
shown by the main process over the kitr:notify:* channels of handleKitrIpc(): no permission
prompt on desktop, so permission() and request() answer granted (or unsupported where the
OS has no notification service). Scheduled notifications live in the main process, so they
survive a window reload but not quitting the app. Clicking one focuses the window and calls
onTap with the url and data it was shown with. setBadge(count) sets the app badge.
Throws E_DRIVER_UNAVAILABLE when the preload bridge is missing (no exposeIpc() call).
createMemoryNotificationsDriver
function createMemoryNotificationsDriver(permission?: NotificationPermission): NotificationsDriver & {
shown: (NotificationOptions & {
id: string;
})[];
scheduled: Map<string, ScheduleOptions & {
id: string;
}>;
tap(id: string): void;
};
For tests and the server: records what was shown, tap(id) simulates a tap.
createNotifications
function createNotifications(config?: NotificationsConfig, app?: KitrApp): Notifications;
Build the notifications service. The driver is config.driver, else the one registered on
app, else selectDriver() for the runtime: the web driver in a browser, a memory driver (unsupported)
on the server, and E_DRIVER_UNAVAILABLE in a native shell unless fallbackToWeb is set.
createTauriNotificationsDriver
function createTauriNotificationsDriver(_options?: DriverOptions): Driver;
The notifications driver for the Tauri shell, on @tauri-apps/plugin-notification (imported on
first use, an optional peer: methods reject with E_DRIVER_UNAVAILABLE when it is missing).
Permission is read and asked through the plugin. The desktop plugin shows a notification at once
and cannot schedule one, so schedule() waits in a timer inside the window (lost when the app
quits) and shows it then; on mobile the same timer applies. The plugin reports a tap only on
mobile, so onTap listeners fire there and stay silent on desktop.
createWebNotificationsDriver
function createWebNotificationsDriver(config?: {
icon?: string;
}): NotificationsDriver;
Driver on the browser Notification API, with timers for scheduling. Scheduled ones are lost when the page closes. Falls back to the service worker where the constructor is not allowed.
notificationId
function notificationId(): string;
A unique id such as n-m5x2k1qz-0, used when show() or schedule() gets none.
selectDriver
function selectDriver(runtime: Runtime, options?: DriverOptions): Driver;
The notifications driver for a runtime: the browser Notification API on web (a memory driver
reporting unsupported on the server), and each native shell's own driver. A shell with no
driver yet throws E_DRIVER_UNAVAILABLE rather than falling back to the web one, unless
fallbackToWeb is set.
useNotifications
function useNotifications(app: KitrApp): Notifications;
The app's notifications service, outside React. Same as app.container.use('notifications').
defineConfig
const defineConfig: <const C extends NotificationsConfig>(config: C) => C;
Types config/notifications.ts. Returns the object unchanged.
CapacitorPush
interface CapacitorPush {
/** The permission to receive push notifications. */
permission(): Promise<NotificationPermission>;
/** Ask for it. */
request(): Promise<NotificationPermission>;
/** Register with FCM or APNs and resolve to the device token to send to your server. */
register(): Promise<string>;
/** Called with each push that arrives while the app is open. */
onReceived(listener: (message: PushMessage) => void): () => void;
/** Called when a push is tapped, with its `url` (from `data.url` or `link`) when it has one. */
onAction(listener: (tap: NotificationTap & {
actionId: string;
}) => void): () => void;
}
Remote (FCM and APNs) notifications on @capacitor/push-notifications.
DriverOptions
interface DriverOptions extends SelectDriverOptions {
/** Default icon for web notifications. */
icon?: string;
}
Options of selectDriver().
ElectronNotificationsDriver
interface ElectronNotificationsDriver extends Driver {
/** Set the app badge count (dock on macOS, launcher on Linux); 0 clears it. */
setBadge(count: number): Promise<void>;
}
The Electron driver, with the dock/taskbar badge that only desktop shells have.
NotificationOptions
interface NotificationOptions {
/** Your own id, so the same notification can be replaced or cancelled. Default: generated. */
id?: string;
/** The first line. */
title: string;
/** The text under the title. */
body?: string;
/** Where a tap should take the person, e.g. `/inbox/42`. Handed to `onTap` listeners. */
url?: string;
/** The image beside the text. Default: `config.icon` on the web. */
icon?: string;
/** Platform-specific extras passed through to the driver. */
data?: Record<string, unknown>;
/** Group id (Android channel, web tag). */
channel?: string;
/** Show without sound or vibration. */
silent?: boolean;
}
What to show: a title, optional body and icon, and the url a tap should open.
Notifications
interface Notifications {
/** The active driver. */
readonly driver: NotificationsDriver;
/** Read the permission state without asking. */
permission(): Promise<NotificationPermission>;
/** Ask once; resolves to the new state. Call it from a click, browsers block unprompted asks. */
request(): Promise<NotificationPermission>;
/** Show now. Resolves to the notification id. */
show(options: NotificationOptions): Promise<string>;
/** Show later. Resolves to the id, usable with `cancel()`. */
schedule(options: ScheduleOptions): Promise<string>;
/** Stop a scheduled notification and close it if shown. */
cancel(id: string): Promise<void>;
/** Cancel every scheduled notification and close shown ones. */
cancelAll(): Promise<void>;
/** Ids of scheduled notifications not yet delivered. */
pending(): Promise<string[]>;
/** A notification was tapped (the app may have been opened by it). */
onTap(listener: (tap: NotificationTap) => void): () => void;
}
The notifications service: permission, show, schedule, cancel and taps.
NotificationsConfig
interface NotificationsConfig {
/** Replace the driver the service would pick (tests, custom shells). */
driver?: NotificationsDriver;
/** Default icon for web notifications. */
icon?: string;
/** Ask for permission at boot instead of waiting for the first `request()`. Default false. */
requestOnBoot?: boolean;
/**
* In a native shell (Electron, Tauri, Capacitor) with no notifications driver, use the web
* driver inside the WebView instead of throwing `E_DRIVER_UNAVAILABLE`. Default false.
*/
fallbackToWeb?: boolean;
}
Options for config/notifications.ts and createNotifications().
NotificationsDriver
interface NotificationsDriver {
/** Shown in devtools, such as `web` or `memory`. */
name: string;
/** Read the permission state without asking. */
permission(): Promise<NotificationPermission>;
/** Ask for permission; resolves to the new state. */
request(): Promise<NotificationPermission>;
/** Show now, replacing any notification with the same id. */
show(options: NotificationOptions & {
id: string;
}): Promise<void>;
/** Show at `options.at`, replacing any scheduled notification with the same id. */
schedule(options: ScheduleOptions & {
id: string;
}): Promise<void>;
/** Stop a scheduled notification and close it if shown. */
cancel(id: string): Promise<void>;
/** Cancel everything. Without it the service cancels each pending id. */
cancelAll?(): Promise<void>;
/** Ids scheduled and not yet shown. Without it the service answers `[]`. */
pending?(): Promise<string[]>;
/** Listen for taps; returns a function that removes the listener. */
onTap(listener: (tap: NotificationTap) => void): () => void;
}
What a platform implements to show notifications. The service always passes an id.
NotificationTap
interface NotificationTap {
/** The id `show()` or `schedule()` resolved to. */
id: string;
/** The `url` the notification was shown with. */
url?: string;
/** The `data` the notification was shown with. */
data?: Record<string, unknown>;
}
What a tap listener receives: the notification's id and the url and data it was shown with.
PushMessage
interface PushMessage {
id: string;
title?: string;
body?: string;
data: Record<string, unknown>;
}
A push message, in the fields apps use.
ScheduleOptions
interface ScheduleOptions extends NotificationOptions {
/** When to show it: a `Date` or a timestamp in milliseconds. A past time shows it at once. */
at: Date | number;
}
A notification to show later.
Driver
type Driver = NotificationsDriver;
What a notifications driver is: NotificationsDriver, whichever runtime supplies it.
NotificationPermission
/** Where permission stands: `prompt` until asked, `unsupported` where there is no notification API. */
type NotificationPermission = 'granted' | 'denied' | 'prompt' | 'unsupported';
Where permission stands: prompt until asked, unsupported where there is no notification API.
@kitr/notifications/react
useNotificationPermission
function useNotificationPermission(): {
permission: NotificationPermission | 'unknown';
request: () => Promise<NotificationPermission>;
};
{ permission, request }: the current state and a function to ask (call it from a click).
useNotifications
function useNotifications(): Notifications;
The app's notifications service in a component.
useNotificationTap
function useNotificationTap(handler: (tap: NotificationTap) => void): void;
Run a handler when a notification is tapped, typically (tap) => tap.url && navigate(tap.url).
@kitr/notifications/provider
notificationsProvider
const notificationsProvider: import("@kitr/core").KitrProvider;
Binds notifications to the platform driver (notifications capability) or the web
Notification API. With requestOnBoot it asks for permission as the app starts.
@kitr/notifications/driver
selectDriver
function selectDriver(runtime: Runtime, options?: DriverOptions): Driver;
The notifications driver for a runtime: the browser Notification API on web (a memory driver
reporting unsupported on the server), and each native shell's own driver. A shell with no
driver yet throws E_DRIVER_UNAVAILABLE rather than falling back to the web one, unless
fallbackToWeb is set.
DriverOptions
interface DriverOptions extends SelectDriverOptions {
/** Default icon for web notifications. */
icon?: string;
}
Options of selectDriver().
Driver
type Driver = NotificationsDriver;
What a notifications driver is: NotificationsDriver, whichever runtime supplies it.
@kitr/notifications/drivers/web
createWebNotificationsDriver
function createWebNotificationsDriver(config?: {
icon?: string;
}): NotificationsDriver;
Driver on the browser Notification API, with timers for scheduling. Scheduled ones are lost when the page closes. Falls back to the service worker where the constructor is not allowed.
@kitr/notifications/drivers/electron
createElectronDriver
function createElectronDriver(_options?: DriverOptions): ElectronNotificationsDriver;
The notifications driver for the Electron shell. Notifications are Electron Notifications
shown by the main process over the kitr:notify:* channels of handleKitrIpc(): no permission
prompt on desktop, so permission() and request() answer granted (or unsupported where the
OS has no notification service). Scheduled notifications live in the main process, so they
survive a window reload but not quitting the app. Clicking one focuses the window and calls
onTap with the url and data it was shown with. setBadge(count) sets the app badge.
Throws E_DRIVER_UNAVAILABLE when the preload bridge is missing (no exposeIpc() call).
ElectronNotificationsDriver
interface ElectronNotificationsDriver extends Driver {
/** Set the app badge count (dock on macOS, launcher on Linux); 0 clears it. */
setBadge(count: number): Promise<void>;
}
The Electron driver, with the dock/taskbar badge that only desktop shells have.
@kitr/notifications/drivers/tauri
createTauriDriver
function createTauriDriver(_options?: DriverOptions): Driver;
The notifications driver for the Tauri shell, on @tauri-apps/plugin-notification (imported on
first use, an optional peer: methods reject with E_DRIVER_UNAVAILABLE when it is missing).
Permission is read and asked through the plugin. The desktop plugin shows a notification at once
and cannot schedule one, so schedule() waits in a timer inside the window (lost when the app
quits) and shows it then; on mobile the same timer applies. The plugin reports a tap only on
mobile, so onTap listeners fire there and stay silent on desktop.
numericId
function numericId(id: string): number;
The plugin wants a 32-bit integer id; the service's ids are strings.
@kitr/notifications/drivers/capacitor
capacitorPush
function capacitorPush(): CapacitorPush;
Push notifications through @capacitor/push-notifications. Needs Firebase on Android
(google-services.json) and the Push Notifications capability on iOS; see the package docs.
createCapacitorDriver
function createCapacitorDriver(_options?: DriverOptions): Driver;
Notifications on @capacitor/local-notifications: the OS schedules and shows them, so scheduled
ones survive the app closing (the web driver's timers do not). On Android a channel becomes a
notification channel, created on first use. Taps from @capacitor/push-notifications reach
onTap too when that plugin is installed; its token and listeners are in capacitorPush().
nativeId
function nativeId(id: string): number;
Capacitor ids are 32-bit integers; kitr ids are strings. A stable FNV-1a hash maps one to the other.
toPermission
function toPermission(state: string): NotificationPermission;
Capacitor reports granted, denied, prompt and prompt-with-rationale (Android, after a
first refusal). The last is still a question the app may ask again, so it maps to prompt.
CapacitorPush
interface CapacitorPush {
/** The permission to receive push notifications. */
permission(): Promise<NotificationPermission>;
/** Ask for it. */
request(): Promise<NotificationPermission>;
/** Register with FCM or APNs and resolve to the device token to send to your server. */
register(): Promise<string>;
/** Called with each push that arrives while the app is open. */
onReceived(listener: (message: PushMessage) => void): () => void;
/** Called when a push is tapped, with its `url` (from `data.url` or `link`) when it has one. */
onAction(listener: (tap: NotificationTap & {
actionId: string;
}) => void): () => void;
}
Remote (FCM and APNs) notifications on @capacitor/push-notifications.
PushMessage
interface PushMessage {
id: string;
title?: string;
body?: string;
data: Record<string, unknown>;
}
A push message, in the fields apps use.