Appearance
Web Push Setup
This guide covers the complete flow for sending push notifications to web browsers: how the VAPID protocol works, registering a service worker, subscribing users, and sending the subscription to Krafter.
How Web Push Works
Web Push uses the VAPID (Voluntary Application Server Identification) protocol to authenticate your server with browser push services. The flow is:
- Your server holds a VAPID keypair (Krafter auto-generates this when you create a push app).
- Your frontend uses the VAPID public key to subscribe the browser via
PushManager.subscribe(). - The browser returns a
PushSubscriptionobject containing an endpoint URL and encryption keys. - You send this subscription data to Krafter as a subscriber registration.
- When you create a notification, Krafter signs it with your VAPID private key and delivers it to the browser's push service.
- The browser's service worker receives the push event and displays the notification.
No third-party push service account is needed for Web Push -- the VAPID protocol works directly with browser vendors (Chrome, Firefox, Edge, Safari).
Prerequisites
- A Krafter push app (see Quickstart)
- Your app's
vapid_public_keyfrom the app creation response - An HTTPS-enabled website (required for service workers)
Step 1: Register a Service Worker
Create a sw.js file at the root of your site to handle incoming push events:
js
// sw.js
self.addEventListener("push", (event) => {
const data = event.data ? event.data.json() : {};
const title = data.title || "New Notification";
const options = {
body: data.body || "",
icon: data.icon,
data: { url: data.url },
};
event.waitUntil(self.registration.showNotification(title, options));
});
self.addEventListener("notificationclick", (event) => {
event.notification.close();
const url = event.notification.data?.url;
if (url) {
event.waitUntil(clients.openWindow(url));
}
});Register the service worker from your main JavaScript:
js
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/sw.js");
}Step 2: Request Permission and Subscribe
Request notification permission from the user and subscribe to push using your VAPID public key:
js
const VAPID_PUBLIC_KEY = "BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LNgKQ...";
async function subscribeToPush() {
const permission = await Notification.requestPermission();
if (permission !== "granted") {
console.log("Push notification permission denied");
return null;
}
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
});
return subscription;
}The applicationServerKey must be a Uint8Array. Use this helper to convert the base64-encoded VAPID key:
js
function urlBase64ToUint8Array(base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/-/g, "+")
.replace(/_/g, "/");
const rawData = atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; i++) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}Step 3: Send Subscription to Krafter
Once the browser returns a PushSubscription, send it to the Krafter API to register the subscriber:
js
const APP_ID = "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f";
const API_KEY = "kr_live_abc123def456"; // Use a backend proxy in production
async function registerSubscriber(subscription) {
const response = await fetch(
`https://app.krafter.dev/api/v1/push/apps/${APP_ID}/subscribers`,
{
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
platform: "web",
token: JSON.stringify(subscription),
user_id: getCurrentUserId(), // optional, your app's user identifier
tags: ["web-user"],
}),
}
);
return response.json();
}WARNING
Never expose your API key in client-side code in production. Route the registration request through your backend server, which adds the Authorization header before forwarding to Krafter.
Step 4: Put It All Together
Here is the complete flow from permission request to subscriber registration:
js
async function initPushNotifications() {
// Check browser support
if (!("serviceWorker" in navigator) || !("PushManager" in window)) {
console.log("Push notifications are not supported");
return;
}
// Register service worker
const registration = await navigator.serviceWorker.register("/sw.js");
await navigator.serviceWorker.ready;
// Check existing subscription
let subscription = await registration.pushManager.getSubscription();
if (!subscription) {
// Request permission and subscribe
const permission = await Notification.requestPermission();
if (permission !== "granted") {
return;
}
subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
});
// Register with Krafter
await registerSubscriber(subscription);
}
}
// Call on page load or after user action
initPushNotifications();TIP
Best practice is to trigger the permission prompt after a user action (e.g., clicking "Enable notifications") rather than on page load. Browsers may block automatic permission requests, and users are more likely to accept when they understand the value.
Handling Permission Changes
Users can revoke notification permission at any time through browser settings. Check the permission state before attempting to subscribe:
js
function checkPermissionState() {
if (Notification.permission === "denied") {
// Permission was blocked -- show instructions to re-enable in browser settings
return "blocked";
}
if (Notification.permission === "granted") {
return "granted";
}
return "prompt"; // Not yet asked
}Browser Support
Web Push with VAPID is supported in all modern browsers:
| Browser | Support |
|---|---|
| Chrome | 50+ |
| Firefox | 44+ |
| Edge | 17+ |
| Safari | 16.1+ |
| Opera | 42+ |
Safari requires the user to have added the site to their Dock or Home Screen on older macOS versions. Safari 16.1+ supports standard Web Push on macOS; Safari 16.4+ supports it on iOS and iPadOS.
Next Steps
- Targeting -- Send notifications to specific subscribers by tags, user IDs, or platform
- Quickstart -- API walkthrough for the full push notification lifecycle
- API Reference -- Full endpoint documentation for apps, subscribers, and notifications