-
-
Notifications
You must be signed in to change notification settings - Fork 131
Declarative Web Push support #2300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
TODOs: - sane app badge count
…med payload recognition on classic push notifications
47ac4f9
to
6db2717
Compare
This comment was marked as resolved.
This comment was marked as resolved.
|
||
// adapt declarative payload for legacy Push API | ||
options = notification || {} | ||
title = notification.title |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Service Worker Notification API Violation
The service worker incorrectly passes the entire notification
object as options
to self.registration.showNotification
. This violates the Web Notifications API specification because the options
object should not contain the title
property (which is passed separately as the first argument) nor other declarative push properties (e.g., navigate
, app_badge
) unsupported by the legacy API. Furthermore, the destructuring of the push event payload can cause a TypeError
if the payload is null or undefined, leading to a service worker crash.
Locations (1)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the ultra-rare case of having a notification that's not sent by us, the try catch handles this
Lines 78 to 94 in a4a0fdb
try { | |
payload = event.data?.json() | |
if (!payload) { | |
throw new Error('no payload in push event') | |
} | |
} catch (err) { | |
// we show a default nofication on any error because we *must* show a notification | |
// else the browser will show one for us or worse, remove our push subscription | |
return event.waitUntil( | |
self.registration.showNotification( | |
// TODO: funny message as easter egg? | |
// example: "dude i'm bugging, that's wild" from https://www.youtube.com/watch?v=QsQLIaKK2s0&t=176s but in wild west theme? | |
'something went wrong', | |
{ icon: '/icons/icon_x96.png' } | |
) | |
) | |
} |
Correct me if I'm wrong: deploying this will remove badging from Apple devices? |
Yeah, I admit it's not a great experience. Then I remembered the new
Maybe we can use it to easily set the badge like we usually do. 🤔 I'll take a look. |
This defeats the purpose of declarative web push, passing the torch yet again to the legacy Push API to handle the notification, disabling all the benefits Drafting until a declarative badge system is implemented in this PR |
Description
Closes #2298
Adds support for Declarative Web Push notifications, enabling them right now on browsers that support it (e.g. Safari >= 18.4) and automatically on other browsers in the near future.
Highlight of this PR is the capability to navigate to URLs natively by the browser on Apple devices.
Screenshots
Demonstration of correct URL navigation by a Declarative Web Push notification
Screen.Recording.2025-07-20.at.12.00.13.mp4
Demo Badge count manipulation and URL navigation
cropped_declarative_potential.mp4
Additional Context
To handle badging declaratively we need to find new ways to count notifications, sending JSON payloads with the
app_badge
property.For the moment only devices with Legacy Push API will have badging support.
What is Declarative Web Push, and why we want to support it
This new specification packs features like service worker-less notifications and better privacy, but in our case the most interesting part is that it's Apple native (for now), potentially enabling things that were broken before on Apple devices:Ultimately, less code, only a declarative JSON payload.
These benefits of course will be extended to all browsers, automatically, once they catch up.
In the meantime, they're backwards compatible:
Some other context
When we send a JSON payload to a push notification server (e.g. Apple's APNs), this payload is sent to the browser, then to our service worker, triggering events like
onPush
,notificationclick
, enabling us to execute custom code on push notifications.This was and still is how it works, but Declarative Web Push eliminates the last step of sending it to the service worker: the browser, instead, manages the notifications, shows it and brings native support to stuff like custom actions and navigation urls.
The service worker is still the only way to execute custom JS on notifications, Declarative Web Push supports the
mutable
field, enabling extra processing of the notification by the service worker.We don't have this need for mutable notifications for now, this PR enables Declarative Web Push automatically by just adjusting the JSON payload and making sure it's backwards compatible to the Push API that we use for the rest of our users.
On a side note, it seems that Declarative Web Push doesn't support relative paths, nor local URLs, so developer experience is hindered. A WebKit bug has been opened.
TODOs
Checklist
Are your changes backward compatible? Please answer below:
For example, a change is not backward compatible if you removed a GraphQL field or dropped a database column.
Yes, the service worker has been aligned to the new JSON payload.
On a scale of 1-10 how well and how have you QA'd this change and any features it might affect? Please answer below:
8
.macOS:
iOS:
Linux:
For frontend changes: Tested on mobile, light and dark mode? Please answer below:
n/a
Did you introduce any new environment variables? If so, call them out explicitly here:
n/a
Footnotes
Meet Declarative Web Push ↩