2.6 KiB
Case Study: PWA Push Notifications on iOS (Cloudflare Workers)
Implementing push notifications for iOS PWAs on Cloudflare Workers requires addressing several unique runtime and OS-specific constraints.
🛠 Tech Stack
- Framework: Next.js (OpenNext)
- Runtime: Cloudflare Workers (Edge)
- Database: Cloudflare D1
- Library:
web-push
🚀 Key Implementation Details
1. Edge Runtime Compatibility (Crucial)
The standard webPush.sendNotification() relies on Node.js's https module, which is not supported in Cloudflare Workers.
Solution: Use webPush.generateRequestDetails() to create the encrypted payload, and then send it using the Edge-native fetch.
const requestDetails = await webPush.generateRequestDetails(
{ endpoint, keys: { p256dh, auth } },
JSON.stringify(payload)
);
const response = await fetch(requestDetails.endpoint, {
method: 'POST',
headers: requestDetails.headers,
body: requestDetails.body // Note: This is a Buffer/ArrayBuffer
});
2. VAPID Key Generation
VAPID keys must be generated using the native crypto module to avoid dependency issues in restricted environments.
3. iOS PWA Manifest Requirements
For "Add to Home Screen" to trigger the correct push capabilities:
display: standaloneorfullscreenis required.- The user must trigger the permission request via a direct interaction (e.g., clicking an "Enable" button).
4. Background Cron Trigger
Since Next.js API routes on Cloudflare don't support long-running processes, a separate Cron Worker is needed to ping the API every minute.
- Workflow:
Cron Worker (triggers every minute)->Ping /api/cron/reminders->App logic checks D1->App sends push via fetch.
5. Local Timezone Management
iOS background alerts are only useful if they fire at the user's local time.
- The fix: Explicitly capture the user's timezone on the client (
Intl.DateTimeFormat().resolvedOptions().timeZone) and save it to the database. - Verification: Ensure the backend API updates the
timezonecolumn alongside reminder settings to avoid defaulting to UTC.
💡 Lessons Learned
- Minute-Precision: For hourly reminders, sync the minute value (e.g., :18 past the hour) between the UI and the backend checker.
- Visual Feedback: iOS users are often skeptical of web-based push. Providing a "Test & Sync" button that sends an immediate notification builds trust and verifies the connection.
- Authentication: Protect the cron endpoint with a
CRON_SECRETheader to prevent unauthorized trigger pings.