Prompt
I’m building a web app and need browser push notifications via API
Latest observation
Oct 14, 2026
OpenAI APIWeb search: off
To add browser push notifications via an API to your web app, you’ll typically use the Web Push API plus a backend service that sends notifications to subscribed browsers.
High-level flow
- Frontend asks for notification permission
- Frontend registers a service worker
- Frontend subscribes the user to push
- Frontend sends the subscription to your backend
- Backend stores the subscription
- When needed, backend sends a push message to the browser
- Service worker receives it and displays a notification
Requirements
- HTTPS site (required for push)
- Service worker
- Browser support for Push API and Notifications API
- Backend capable of sending Web Push messages
Frontend setup
1) Request permission
const permission = await Notification.requestPermission();
if (permission !== "granted") {
throw new Error("Notification permission not granted");
}
2) Register a service worker
const registration = await navigator.serviceWorker.register("/sw.js");
3) Subscribe the user
You need your VAPID public key from the server, converted to Uint8Array.
function urlBase64ToUint8Array(base64String) {
const padding = "=".repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
const rawData = atob(base64);
return Uint8Array.from([...rawData].map(char => char.charCodeAt(0)));
}
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
});
4) Send subscription to your API
await fetch("/api/push/subscribe", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(subscription)
});
Service worker (/sw.js)
This file listens for push events and shows notifications.
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 || "/icon.png",
data: data.url || "/"
};
event.waitUntil(self.registration.showNotification(title, options));
});
self.addEventListener("notificationclick", event => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data || "/")
);
});
Backend example
If you use Node.js, the common library is web-push.
Install
npm install web-push
Generate VAPID keys
npx web-push generate-vapid-keys
Configure and send push
import webpush from "web-push";
webpush.setVapidDetails(
"mailto:admin@example.com",
process.env.VAPID_PUBLIC_KEY,
process.env.VAPID_PRIVATE_KEY
);
await webpush.sendNotification(
subscription,
JSON.stringify({
title: "Hello!",
body: "You have a new message",
url: "/messages"
})
);
Example API endpoints
Subscribe
POST /api/push/subscribe
- Save the subscription object to your database
- Associate it with the logged-in user
Send notification
POST /api/push/send
- Retrieve subscriptions for a user or audience
- Use
web-pushto send to each subscription - Remove expired subscriptions (
410 Goneresponses)
Important notes
- Push notifications are not the same as in-app alerts: push works even when the site isn’t open.
- You must display a notification for every push message when using
userVisibleOnly: true. - Safari support can differ, especially on older versions; test the browsers you care about.
- Handle subscription expiration and cleanup.
Recommended architecture
-
Frontend
- register SW
- request permission
- subscribe
- send subscription to backend
-
Backend
- store subscriptions
- authenticate users
- send pushes using VAPID
-
Service worker
- receive push
- show notification
- handle click actions
If you want, I can provide:
- a complete working example in Node/Express + vanilla JS, or
- the same setup in Next.js / React / Firebase / Django / Laravel.