Transports

Web Push

Encrypt and send browser notifications with VAPID.

Encrypt and send browser notifications with VAPID — the welcome ping, the “report ready” alert, or a silent data sync to a service worker.

The one rule

Create this transport under createPushSender and pass a browser subscription — not an FCM device token.

Quick start

Generate VAPID keys

import { generateVapidKeys } from "sently/transports/webpush";

const { publicKey, privateKey } = await generateVapidKeys();
// Store privateKey in env / secrets manager. Use publicKey in the browser subscribe call.

Configure the sender

import { createPushSender } from "sently/push";
import { WebPushTransport } from "sently/transports/webpush";

const push = createPushSender({
  transport: new WebPushTransport({
    vapidPublicKey: process.env.VAPID_PUBLIC_KEY!,
    vapidPrivateKey: process.env.VAPID_PRIVATE_KEY!,
    subject: "mailto:you@example.com",
  }),
});

Send

await push.send({
  subscription,
  title: "Report ready",
  body: "Your weekly report is ready to view.",
  urgency: "high",
  topic: "report-ready",
});

Configuration

OptionTypeDefault or requirement
vapidPublicKeystringrequired — base64url uncompressed P-256 (65 bytes)
vapidPrivateKeystringrequired — base64url raw private key (32 bytes)
subjectstringrequired — mailto:you@example.com or https://example.com/contact
allowedEndpointHostsstring[]optional — exact hostnames for private push relays

Send options (Web Push)

FieldTypeNotes
subscriptionPushSubscriptionrequired — endpoint, keys.p256dh, keys.auth
title / bodystringrequired together for a visible notification
dataRecord<string, unknown>optional; required for silent / data-only
icon / badge / imagestringNotification API URLs
tagstringreplace an existing notification with the same tag
actions{ action, title, icon? }[]action buttons
requireInteractionbooleankeep open until the user interacts
renotifybooleanre-alert when replacing by tag
ttlnumberseconds (default 2419200 / 28 days)
urgency"very-low" | "low" | "normal" | "high"RFC 8030 Urgency header
topicstringRFC 8030 Topic — 1–32 printable ASCII; collapses pending messages
silentbooleanencrypt only data (no visible fields); requires data
messageIdstringoptional client id

Features

Pick a branch. Channel send goes through push; key generation is imported from sently/transports/webpush.

Visible notification via the channel sender.

await push.send({
  subscription,
  title: "Report ready",
  body: "Your weekly report is ready to view.",
});

Invalid urgency / topic, silent without data, or a partial visible payload (title without body) throw WebPushError (provider: "webpush") with status 400 before fetch.

Troubleshooting

Learn more

Next

On this page