@andreasnicolaou/web-notifier

June 25, 2026 ยท View on GitHub

Logo

@andreasnicolaou/web-notifier

A lightweight, dependency-friendly wrapper around the browser Notification API. It gives you a clean, reactive (RxJS) and Promise-based API for requesting permission, showing notifications, auto-dismissing them, delaying them, and reacting to click/close/show events.

GitHub License npm version npm downloads Types Minified size

๐Ÿ‘‰ Try the live demo โ€” request permission and fire real notifications right from your browser.

Note: This library wraps the Notification API (the small banner/toast notifications a page can show while it is open). It does not implement the Push API or service-worker push, so it does not deliver messages while the site is closed. If you only need to notify the user while your app is running, this is for you.

Features

  • ๐Ÿ”” Show browser notifications with the full set of native options.
  • โฑ๏ธ Auto-dismiss notifications after a configurable timeout.
  • โณ Delay a notification before it is shown.
  • ๐Ÿ–ฑ๏ธ Handle click, close, show, error and permission-denied events via callbacks.
  • ๐Ÿ›ก๏ธ Graceful permission handling โ€” never prompts twice, never throws on unsupported browsers.
  • ๐Ÿงฉ Use it your way: RxJS Observables (show) or Promises (showAsync).
  • ๐Ÿชถ Tiny, tree-shakeable ESM/CJS builds plus a ready-to-use UMD bundle for CDNs.
  • ๐Ÿ“˜ Written in TypeScript with complete type definitions.

Installation

npm install @andreasnicolaou/web-notifier

rxjs (v7+) is a dependency. If your app already uses RxJS, it is deduped automatically.

Usage

Promise API (simplest)

import { WebPushNotifier } from '@andreasnicolaou/web-notifier';

const notifier = new WebPushNotifier({ autoDismiss: 5000 });

const notification = await notifier.showAsync('Hello there!', {
  body: 'This is a test notification using @andreasnicolaou/web-notifier.',
});

if (notification) {
  console.log('Notification shown!');
}

RxJS API

import { WebPushNotifier } from '@andreasnicolaou/web-notifier';

const notifier = new WebPushNotifier({ autoDismiss: 5000 });

notifier
  .show('Hello there!', { body: 'Reactive notification.' }, { onclick: () => console.log('clicked') })
  .subscribe((notification) => {
    if (notification) {
      console.log('Notification shown!');
    }
  });

You can also fire-and-forget โ€” calling show() displays the notification immediately, even without subscribing:

notifier.show('Quick ping!');

Checking support and permission

if (WebPushNotifier.isSupported()) {
  const notifier = new WebPushNotifier();
  notifier.requestPermission().subscribe((permission) => {
    console.log('Permission is now:', permission); // 'granted' | 'denied' | 'default'
  });
}

CDN Usage

You can use the library directly in the browser via CDN. The UMD build exposes the global variable webNotifier.

<script src="https://unpkg.com/@andreasnicolaou/web-notifier"></script>
<script>
  const Notifier = window.webNotifier.WebPushNotifier;
  const notifier = new Notifier({ autoDismiss: 2000 });
  notifier.show('Hello from CDN!', { body: 'This is a test notification.' });
</script>

Other CDN entry points:

  • unpkg (minified): https://unpkg.com/@andreasnicolaou/web-notifier/dist/index.umd.min.js
  • jsDelivr (unminified): https://cdn.jsdelivr.net/npm/@andreasnicolaou/web-notifier/dist/index.umd.js
  • jsDelivr (minified): https://cdn.jsdelivr.net/npm/@andreasnicolaou/web-notifier/dist/index.umd.min.js

API

new WebPushNotifier(globalOptions?, globalCallbacks?)

Creates a notifier. globalOptions and globalCallbacks are merged into (and overridden by) the per-call options/callbacks passed to show / showAsync.

show(title, options?, callbacks?): Observable<Notification | null>

Shows a notification. Returns a shared Observable that emits the Notification instance (or null if permission was not granted). The notification is created exactly once, no matter how many times you subscribe.

showAsync(title, options?, callbacks?): Promise<Notification | null>

Promise-based variant of show. Resolves with the Notification instance, or null when permission is not granted. Rejects if notifications are unsupported.

requestPermission(): Observable<NotificationPermission>

Requests permission, returning the existing value without re-prompting if it has already been granted or denied.

dismissAll(): void

Closes all notifications created by this instance that are still open.

isSupported(): boolean / WebPushNotifier.isSupported(): boolean

Returns whether the current environment supports the Notification API (available as both an instance and a static method).

permission: NotificationPermission | 'unsupported' (getter)

The current permission, or 'unsupported' when the API is unavailable.

activeCount: number (getter)

The number of notifications from this instance that are currently open.

Options (WebPushNotifierOptions)

Extends the native NotificationOptions with:

OptionTypeDescription
autoDismissnumberMilliseconds after which the notification is automatically closed.
delaynumberMilliseconds to wait before the notification is shown.

Callbacks (WebPushNotifierCallbacks)

CallbackSignatureWhen it fires
onclick(notification: Notification) => voidThe user clicks the notification.
onclose(notification: Notification) => voidThe notification is closed.
onshow(notification: Notification) => voidThe notification is shown.
onerror(error: unknown) => voidThe notification fails to display.
onPermissionDenied() => voidPermission is (or has already been) denied.

Notes & limitations

These come from the underlying Notification API, not from this library:

  • The OS controls display. Your operating system decides how many notifications are visible at once and may queue or coalesce them โ€” that is expected, not a bug.
  • activeCount / dismissAll are best-effort. They track notifications this instance created and was told were closed. Some browsers (notably Chrome on Windows) fire the close event unreliably, so a notification the user closes from the OS may remain counted until you call dismissAll(). For deterministic cleanup, use the autoDismiss option โ€” the library closes those itself and updates its tracking regardless of the close event.
  • Permission must be requested from a user gesture (e.g. a click handler) in modern browsers.

Learn more about the Notification API

License

MIT ยฉ Andreas Nicolaou