Skip to content

Declarative Push Notification Examples #75

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

Merged
merged 1 commit into from
Mar 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,22 @@ You'll also want to serve a `serviceWorker.mjs` file at the root of your server
self.addEventListener('push', function(event) {
const data = event.data?.json() ?? {};
event.waitUntil((async () => {
const notification = data?.notification ?? {}
/// Try parsing the data, otherwise use fallback content. DO NOT skip sending the notification, as you must display one for every push message that is received or your subscription will be dropped.
let title = data?.title ?? "Your App Name";
const body = data?.body ?? "New Content Available!";
const title = notification.title ?? "Your App Name";
const body = notification.body ?? "New Content Available!";

await self.registration.showNotification(title, {
body,
icon: "/notification-icon.png", /// Only some browsers support this.
data
body,
requireInteraction: notification.require_interaction ?? false,
...notification,
});
})());
});
```

In the example above, we are using the new **Declarative Push Notification** format for our message payload so the browser can automatically skip requiring the service worker, but you can send send any data payload and interpret it in your service worker should you choose. Note that doing so will require more resources on your user's devices when Declarative Push Notifications are otherwise supported.

> [!NOTE]
> `.mjs` here allows your code to import other js modules as needed. If you are not using Vapor, please make sure your server uses the correct mime type for this file extension.

Expand Down Expand Up @@ -349,7 +352,12 @@ import WebPush

do {
try await manager.send(
json: ["title": "Test Notification", "body": "Hello, World!"],
/// We use a declarative push notification to allow newer browsers to deliver the notification to users on our behalf.
notification: PushMessage.Notification(
destination: URL(string: "https://example.com/notificationDetails")!,
title: "Test Notification",
body: "Hello, World!"
),
to: subscriber
/// If sent from a request, pass the request's logger here to maintain its metadata.
// logger: request.logger
Expand All @@ -367,6 +375,8 @@ do {

Your service worker will receive this message, decode it, and present it to the user.

You can also send JSON (`send(json: ...)`), data (`send(data: ...)`), or text (`send(string: ...)`) and have your service worker interpret the payload as it sees fit.

> [!NOTE]
> Although the spec supports it, most browsers do not support silent notifications, and will drop a subscription if they are used.

Expand Down
6 changes: 6 additions & 0 deletions Sources/WebPush/Push Message/Notification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ extension PushMessage {


/// Initialize a new Declarative Push Notification.
///
/// - Important: The entire notification must fit within ``WebPushManager/maximumMessageSize`` once encoded, or sending the notification will fail. Keep this in mind when specifying data to be sent along with the notification.
///
/// - Parameters:
/// - kind: The kind of notification to send. Defaults to ``PushMessage/NotificationKind/declarative``.
/// - destination: The destination URL that should be opened when the user interacts with the notification.
Expand Down Expand Up @@ -164,6 +167,9 @@ extension PushMessage {

extension PushMessage.Notification where Contents == Never {
/// Initialize a new Declarative Push Notification.
///
/// - Important: The entire notification must fit within ``WebPushManager/maximumMessageSize`` once encoded, or sending the notification will fail. Keep this in mind when specifying data to be sent along with the notification.
///
/// - Parameters:
/// - kind: The kind of notification to send. Defaults to ``PushMessage/NotificationKind/declarative``.
/// - destination: The destination URL that should be opened when the user interacts with the notification.
Expand Down
2 changes: 2 additions & 0 deletions Sources/WebPush/Push Message/PushMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
//

/// Common Push Message types.
///
/// Currently, only ``PushMessage/Notification`` is defined.
public enum PushMessage: Sendable {}