Push service

Browser notifications travel through a push service that the browser picks: Chrome uses Google's, Firefox uses Mozilla's, Safari uses Apple's. The ungoogled-chromium engine TronBrowser runs on has none, so on a stock build every site's pushManager.subscribe() fails with Registration failed - push service error.

TronBrowser brings its own. The built-in extension supplies pushManager to every page and registers with https://tronbrowser.dev/api/1/push by default. Change it under Settings → Push notifications: another compatible service, or off.

For site owners: nothing to change

Your site subscribes the usual way and gets an endpoint on our service. Your server sends exactly what it sends to FCM or Mozilla: an aes128gcm body (RFC 8291) with a VAPID header (RFC 8292), via web-push, @profullstack/notifications or anything else that speaks the standard. We answer 201, and 404 / 410 when a subscription is gone, so your cleanup keeps working.

One difference: the notification is shown by TronBrowser from the payload's title, body, icon and url (also notification.* and click_action). Your service worker's push handler does not run, so a silent push that only syncs data shows as a plain notification.

Privacy

The protocol, for a self-hosted service

RequestWhoWhat
GET /settings page{"service":"tronbrowser-push","version":1}, which is how the browser checks a custom URL
POST /{token}site serversRFC 8030 push. TTL required, body ≤ 4096 bytes, Topic replaces a pending message
POST /subscriptionsbrowser{origin, applicationServerKey} → {token, endpoint}
DELETE /subscriptions/{token}browserunsubscribe; later pushes get 410
GET /messages, POST /ackbrowserpending messages, then {ids} to acknowledge
GET /connectbrowserWebSocket. Send {"type":"hello","secret"}; receive {"type":"messages"}; reply {"type":"ack","ids"}

Browser calls carry Authorization: Bearer <device secret>. The source is in services/api/src/push.