Package delivery schedule and Web Push notifications#10
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds configurable weekly package delivery timing (weekday + local time + timezone), foreground notifications when packages are generated while the app is open, and optional Web Push notifications via the existing Cloudflare Worker (including subscribe/unsubscribe endpoints and a 15-minute cron job to send “package ready” reminders).
Changes:
- Adds delivery scheduling fields to app settings and uses them to decide when weekly packages are generated and when to show foreground notifications.
- Adds PWA push-capable service worker (injectManifest) plus a debug-only minimal push SW to avoid dev precache issues.
- Extends the Worker with push subscription storage in KV, test routes, Firebase ID token verification (optional), and a cron sender that checks Firestore for synced users.
Reviewed changes
Copilot reviewed 35 out of 38 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| worker/wrangler.jsonc | Adds nodejs compat, cron trigger, and PUSH_KV binding for push subscriptions/dedupe. |
| worker/src/index.ts | Routes new push endpoints and adds a scheduled cron handler. |
| worker/src/env.ts | Defines Worker environment bindings for push, VAPID keys, and optional Firebase SA JSON. |
| worker/src/cors.ts | Extracts shared CORS helpers used by weekly summary + push endpoints. |
| worker/src/weeklySummary.ts | Moves weekly AI summary handler into its own module (existing behavior + rate limit). |
| worker/src/pushTypes.ts | Defines types for push subscription payloads and stored subscriber records. |
| worker/src/pushSend.ts | Adds Workers-compatible Web Push sender via web-push-neo + VAPID configuration. |
| worker/src/pushHandlers.ts | Implements subscribe/unsubscribe/status/test routes and authorization logic. |
| worker/src/pushDelivery.ts | Adds delivery window checks and last-completed-week range helpers for cron. |
| worker/src/pushCron.ts | Implements 15-minute cron to send due notifications and Firestore checks for synced users. |
| worker/src/firebaseAuth.ts | Adds Firebase ID token verification via Google JWKS (jose). |
| worker/src/firestoreAdmin.ts | Adds minimal Firestore Admin queries using service account JWT flow. |
| worker/README.md | Documents KV setup, VAPID/Firebase secrets, and push routes/cron behavior. |
| worker/.dev.vars.example | Adds local dev env placeholders for VAPID keys and optional service account JSON. |
| worker/package.json | Adds date-fns, jose, and web-push-neo dependencies for push + Firestore auth. |
| worker/package-lock.json | Locks the new Worker dependencies. |
| vite.config.ts | Switches PWA strategy to injectManifest, adds dev SW options, and adjusts precache patterns. |
| src/pwa/sw.ts | Adds Workbox-based service worker with push + notification click handlers. |
| public/dev-push-sw.js | Adds minimal push-only SW for debug mode to avoid Workbox dev precache issues. |
| src/pwa/registerDebugPushSw.ts | Registers/unregisters the debug push SW in debug builds when configured. |
| src/pwa/pushSubscribe.ts | Implements push subscription creation, sync to Worker, and debug/test helpers. |
| src/pwa/notifications.ts | Adds settings-aware permission prompting and foreground notification helpers. |
| src/main.tsx | Uses debug push SW in debug mode (when configured) and normal PWA registration otherwise. |
| src/vite-env.d.ts | Adds VITE_VAPID_PUBLIC_KEY and VITE_PUSH_API_BASE env typings. |
| src/shared/settings/appSettings.ts | Adds notification + delivery scheduling settings and sanitization/defaults. |
| src/features/settings/SettingsPage.tsx | Adds UI controls for notifications and delivery schedule + permission state messaging. |
| src/features/packages/packageDelivery.ts | Adds logic to compute when a week becomes deliverable based on schedule. |
| src/features/packages/packageGenerator.ts | Generates weekly packages only when deliverable; returns newly created rows. |
| src/features/packages/runPackageDelivery.ts | Runs delivery generation and shows foreground notification when packages appear. |
| src/features/debug/debugNotifications.ts | Adds a debug snapshot/actions layer for push + SW + permission testing. |
| src/features/debug/DebugPanel.tsx | Adds a notifications debug section (SW status, subscribe, test push, delayed push). |
| src/App.tsx | Runs package delivery periodically while visible and prompts permission after submits when relevant. |
| docs/FIREBASE.md | Documents optional push + Firestore service account setup and behavior. |
| AGENTS.md | Updates repo/operator notes for debug push SW, delivery schedule, and push setup/testing. |
| .github/workflows/gh-pages.yml | Plumbs VITE_VAPID_PUBLIC_KEY and VITE_PUSH_API_BASE into the Pages build. |
| .env.local.example | Adds local env examples for Web Push configuration. |
| .env.example | Adds Web Push env placeholders for production builds. |
Files not reviewed (1)
- worker/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function lastCompletedWeekRange(now: Date, timeZone: string) { | ||
| const todayKey = dateKeyInTimeZone(now, timeZone) | ||
| const today = parseISO(todayKey) | ||
| const lastCompleteWeekEnd = endOfWeek(subWeeks(today, 1), { weekStartsOn: 1 }) | ||
| const lastCompleteWeekStart = startOfWeek(lastCompleteWeekEnd, { weekStartsOn: 1 }) | ||
| return { | ||
| weekKey: format(lastCompleteWeekStart, "yyyy-'W'II"), | ||
| startKey: format(lastCompleteWeekStart, 'yyyy-MM-dd'), | ||
| endKey: format(lastCompleteWeekEnd, 'yyyy-MM-dd'), | ||
| } |
| export async function handlePushStatus(request: Request, env: PushEnv) { | ||
| const origin = request.headers.get('Origin') | ||
| if (request.method === 'OPTIONS') return corsResponse(null, 204, env, origin) | ||
| if (request.method !== 'GET') { | ||
| return corsJson({ error: 'Method not allowed' }, 405, env, origin) | ||
| } | ||
| return corsJson({ vapidConfigured: vapidConfigured(env) }, 200, env, origin) | ||
| } |
| const res = await fetch('https://oauth2.googleapis.com/token', { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, | ||
| body: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${assertion}`, |
| if (body.endpoint) { | ||
| const epKey = `ep:${await hashEndpoint(body.endpoint)}` | ||
| const mapped = await env.PUSH_KV.get(epKey) | ||
| if (mapped) await env.PUSH_KV.delete(mapped) | ||
| await env.PUSH_KV.delete(epKey) | ||
| } | ||
| await env.PUSH_KV.delete(key) |
| function subscriberKey(uid: string | undefined, clientId: string | undefined) { | ||
| if (uid) return `sub:${uid}` | ||
| if (clientId) return `sub:cid:${clientId}` | ||
| return null | ||
| } |
Agent-Logs-Url: https://github.com/SillyLittleTech/mentell/sessions/b7570a76-d1ec-4cb0-a6fe-72b0180f0720 Co-authored-by: kiyarose <75678535+kiyarose@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Summary
web-push-neo(Workers-compatible), and PWAinjectManifestservice worker with push handlers.dev-push-sw.js, and weekly-token auth when Firebase service account is not configured locally.Operator setup (after merge)
Worker:
VAPID_PUBLIC_KEY,VAPID_PRIVATE_KEY, optionalFIREBASE_SERVICE_ACCOUNT_JSONviawrangler secret put; deploy withnpm run worker:deploy. Local dev usesworker/.dev.vars.GitHub Pages Variables:
VITE_VAPID_PUBLIC_KEY,VITE_PUSH_API_BASE(worker origin, no trailing slash). Push is skipped in the client build if these are unset.Test plan
npm run build:checkcd worker && npm run typesPOST /push/subscribe200), delayed push with tab closedMade with Cursor