Web Push Channel
The Web Push channel allows you to send push notifications to web browsers using the Web Push protocol. This channel uses the web-push library with VAPID (Voluntary Application Server Identification) authentication.
Batching
This channel does not support batching. Each notification is sent individually.
Configuration
import { createFacteur } from '@facteurjs/core'
import { webpushChannel } from '@facteurjs/core/channels/webpush'
export const facteur = createFacteur({
discoverer: { searchDirectory: new URL('./notifications/', import.meta.url) },
channels: {
webpush: webpushChannel({
// Required: VAPID configuration
vapidSubject: 'mailto:admin@example.com', // or https://example.com
vapidPublicKey: 'your-vapid-public-key',
vapidPrivateKey: 'your-vapid-private-key',
// Optional: GCM API Key (for legacy Chrome support)
gcmApiKey: 'your-gcm-api-key',
// Optional: Default TTL in seconds (default: 4 weeks)
ttl: 86400,
// Optional: Default urgency level
urgency: 'normal',
// Optional: HTTP proxy configuration
proxy: 'http://proxy:8080',
// Optional: Request timeout in milliseconds
timeout: 30000,
}),
},
})
Configuration Options
vapidSubject(required): Contact information (mailto: or https:// URL) for push service operatorsvapidPublicKey(required): VAPID public key (URL-safe Base64 encoded)vapidPrivateKey(required): VAPID private key (URL-safe Base64 encoded)gcmApiKey(optional): GCM API key for legacy Chrome supportttl(optional): Time-to-live in seconds (how long the push service should retry delivery)urgency(optional): Message urgency level ('very-low','low','normal','high')proxy(optional): HTTP proxy URL for outgoing requeststimeout(optional): Request timeout in milliseconds
Generating VAPID Keys
You can generate VAPID keys using the web-push CLI:
npx web-push generate-vapid-keys
Targets
The Web Push channel requires a push subscription object obtained from the browser:
await facteur
.notification(MyNotification)
.via({
webpush: {
subscription: {
endpoint: 'https://fcm.googleapis.com/fcm/send/...',
keys: {
p256dh: 'user-public-key',
auth: 'user-auth-secret',
},
expirationTime: null,
},
},
})
.send()
Target Properties
subscription(required): A push subscription object from the browser's Push API, or an array of subscription objectsendpoint: The push service URLkeys.p256dh: The user's public keykeys.auth: The authentication secretexpirationTime: Optional expiration timestamp
Multiple devices
Pass an array to notify all of a user's devices in one call:
await facteur
.notification(MyNotification)
.via({ webpush: { subscription: userSubscriptions } })
.send()
Alternatively, return { webpush: { subscription: userSubscriptions } } from notificationTargets() and use .to(user).
All subscriptions are attempted concurrently. Failures are grouped in an AggregateError and mark the channel as failed without preventing delivery to other devices. Retries resend to all devices and may cause duplicates.
Client-Side Setup
To get a push subscription from the browser:
// Register service worker
const registration = await navigator.serviceWorker.register('/sw.js')
// Request push subscription
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
})
// Send subscription to your server
await fetch('/api/push-subscription', {
method: 'POST',
body: JSON.stringify(subscription),
})
Message Features
When creating notifications for Web Push, you can use rich notification features:
import { Notification } from '@facteurjs/core/types'
import { WebpushMessage } from '@facteurjs/core/channels/webpush'
export default class WebpushNotification extends Notification<undefined> {
asWebpushMessage() {
return WebpushMessage.create()
.setTitle('Notification Title')
.setBody('This is the notification body')
.setIcon('/icons/notification-icon.png')
.setImage('/images/large-image.png')
.setBadge('/icons/badge.png')
.setTag('unique-tag')
.setUrl('/page-to-open')
.setData({ customData: 'value' })
.setActions([
{ action: 'view', title: 'View', icon: '/icons/view.png' },
{ action: 'dismiss', title: 'Dismiss' },
])
.setRequireInteraction(true)
.setSilent(false)
.setRenotify(true)
.setVibrate([200, 100, 200])
}
}
Available Methods
setTitle(title): Set the notification titlesetBody(body): Set the notification body textsetIcon(url): Set the notification icon URLsetImage(url): Set a large image URLsetBadge(url): Set the badge icon URLsetTag(tag): Set a tag to group/replace notificationssetData(data): Set custom data payloadsetUrl(url): Set the URL to open when clickedsetActions(actions): Set notification action buttonsaddAction(action): Add a single action buttonsetRequireInteraction(bool): Keep notification visible until user interactssetSilent(bool): Suppress sound/vibrationsetRenotify(bool): Vibrate/sound when replacing a notification with same tagsetTimestamp(timestamp): Set a custom timestampsetVibrate(pattern): Set vibration pattern (array of milliseconds)setDir(dir): Set text direction ('auto','ltr','rtl')setLang(lang): Set notification language