How it works
notify is a thin, hosted layer over the Web Push standard. Here’s what actually happens between the three parties.
The three parties
- The browser owns the push subscription and shows the notification. It will only register a service worker that is same-origin with the page.
- notify (on Cloudflare’s edge) stores the subscription against your userId, holds the VAPID keypair, and signs + delivers each push.
- Your backend never speaks the push protocol. It calls one endpoint.
Subscription flow
When you call notify.subscribe(userId), the script:
- registers your same-origin service worker (which imports our handler logic);
- requests notification permission;
- fetches the public VAPID key from GET /config (so keys can rotate without you re-shipping);
- creates the PushSubscription and posts it to POST /subscribe keyed by your userId.
Why the one-line service worker
A service worker must be served from the same origin as the page that registers it. Since notify.js loads cross-origin, it can’t register our worker directly — so you host a one-liner that imports it. Cross-origin importScripts in a worker is allowed, so this is all it takes:
importScripts("https://api.getnotify.dev/sw.js");Send flow
POST /send looks up the subscription for the userId, encrypts the payload (RFC 8291) and signs the VAPID JWT (RFC 8292) using WebCrypto, then forwards it to the browser’s push service. Your service worker receives the push event and shows the notification.
Built on Effect and deployed with Alchemy. Storage is Cloudflare D1; the push encryption runs on WebCrypto so it works inside a Worker.