# 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`.

```typescript
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: standalone` or `fullscreen` is 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 `timezone` column 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_SECRET` header to prevent unauthorized trigger pings.
