Implement tasks 40, 41, 42: web push, notification bus, reminders engine
Task 40 — Web Push (VAPID): - Add web-push package + @types/web-push - pnpm vapid:generate script prints VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, NEXT_PUBLIC_VAPID_PUBLIC_KEY - push_subscriptions schema + migration 0013 - _core/push.ts: sendPush() iterates subscriptions, prunes 404/410 stale entries - SW push/notificationclick event handlers added to generated sw.js template - PushOptIn client component on /settings (opt-in, disable, send test) Task 42 — Notification bus + ntfy adapter: - notifications table + notif_push/notif_inapp/notif_ntfy user columns (migration 0013) - _core/notify.ts: notify() fans out to push, in-app DB, and optional ntfy POST - NotificationBell server component in AppNav: unread badge, dropdown inbox, mark-read - NotifyChannelToggles client component in /settings Task 41 — Reminders engine: - fired_at + created_by added to reminders; default channel changed to 'auto' - _core/reminders.ts: scheduleReminder (upsert), cancelReminder, listReminders, tickReminders - tickReminders uses pg_try_advisory_xact_lock for horizontal-scale safety - src/instrumentation.ts starts reminder worker (30s tick) on Node.js boot - Notes actions use scheduleReminder/cancelReminder instead of raw SQL - Calendar createEvent: optional remindMinutesBefore, deleteEvent: cancelReminder - Calendar-shell: "Remind me 30 min before" checkbox on new event form Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
ec20f1bc87
commit
b6abe052c9
@@ -30,6 +30,12 @@ Living progress tracker. Update at the end of each task. Codex and Claude Code b
|
||||
- **50 — PWA shell**. `public/manifest.webmanifest` (name, short_name, icons, theme_color, display: standalone, start_url `/`). Placeholder PNG icons at 180, 192, 384, 512 (regular + maskable) generated by `scripts/generate-icons.mjs` (`pnpm gen:icons`); `public/icon.svg` committed as source. Hand-rolled service worker at `public/sw.js`: precaches `offline.html` on install, cache-first for `/_next/static/`, network-first for navigation with offline fallback, network-only for API routes. `src/components/pwa-register.tsx` registers the SW client-side. `src/components/install-prompt.tsx` shows a dismissible banner: `beforeinstallprompt` on Android/Chrome, a one-time "Add to Home Screen" hint on iOS (detected via UA + `navigator.maxTouchPoints`, suppressed in standalone mode). Root layout exports `viewport` (themeColor), updated `metadata` (manifest, appleWebApp, apple-touch-icon), and mounts both new components. `pnpm typecheck`, `pnpm lint`, `pnpm build` all clean.
|
||||
- **51 — Offline shell + service worker caching**. `next.config.ts` generates `public/sw.js` as a side effect on every `next build` / `next dev` invocation, embedding a build timestamp as `CACHE_VERSION` (stable `"dev"` string in development to avoid hot-reload cache churn; epoch milliseconds in production). SW strategies: stale-while-revalidate for `/_next/static/` chunks and navigation HTML (cached page served instantly, network update fires in background); network-first with 2-second abort timeout for API GETs falling back to cache; network-only for mutations (POST/PATCH/DELETE/PUT) — if offline, all controlled clients receive `{ type: "OFFLINE_MUTATION" }` via `postMessage` and a synthetic 503 is returned. Activate handler evicts all `famapp-*` caches whose suffix doesn't match the current version, then claims clients. `pwa-register.tsx` extended with three inline toasts: amber "offline" banner (persistent, driven by `navigator.onLine` + `online`/`offline` events), red "changes can't be saved" toast (auto-dismisses in 4 s, driven by SW postMessage), and indigo "new version available — refresh" bottom toast (driven by `controllerchange` with `hadController` guard). `pnpm typecheck`, `pnpm build` pass.
|
||||
|
||||
- **40 — Web Push (VAPID)**. Installed `web-push` + `@types/web-push`. Added `pnpm vapid:generate` script (`scripts/vapid-generate.mjs`) that prints all three env vars to stdout. Added `push_subscriptions` table to `_core/schema.ts` + migration `0013_push_notify_reminders.sql`. Created `_core/push.ts` with `sendPush(userId, payload)` — iterates subscriptions, removes 404/410 stale entries. Added `push` and `notificationclick` event handlers to the generated `public/sw.js` template. Created `<PushOptIn />` client component on `/settings` (opt-in button → `subscribeToPush` server action, disable button → `unsubscribeFromPush`, test button → `sendTestNotification`). Documented `NEXT_PUBLIC_VAPID_PUBLIC_KEY` in `.env.example`. `pnpm typecheck`, `pnpm lint`, `pnpm build` pass.
|
||||
|
||||
- **42 — Notification bus + ntfy adapter**. Added `notifications` table and `notif_push`/`notif_inapp`/`notif_ntfy` columns on `users` (migration `0013_push_notify_reminders.sql`). Created `_core/notify.ts` with `notify(userId, { title, body, url, channels? })` — fans out to push (if VAPID configured), in-app DB insert, and ntfy POST (if `NTFY_URL`+`NTFY_TOPIC` set). Added `<NotificationBell />` async server component in `AppNav`: queries last 20 notifications, shows unread badge, dropdown inbox with mark-read and mark-all-read. Added `<NotifyChannelToggles />` client component with per-channel checkboxes in `/settings`. `pnpm typecheck`, `pnpm lint`, `pnpm build` pass.
|
||||
|
||||
- **41 — Reminders engine**. Added `fired_at` and `created_by` columns to `reminders` table (migration `0013_push_notify_reminders.sql`); default channel changed to `'auto'`. Created `_core/reminders.ts` with `scheduleReminder` (upsert by entity), `cancelReminder`, `listReminders`, and `tickReminders` (30 s tick, `pg_try_advisory_xact_lock` guard). `startReminderWorker()` started via `src/instrumentation.ts` on the Node.js runtime. Notes actions updated to use `scheduleReminder`/`cancelReminder` instead of raw SQL. Calendar `createEvent` accepts optional `remindMinutesBefore` and schedules a reminder; `deleteEvent` calls `cancelReminder`. Calendar-shell event dialog shows "Remind me 30 min before" checkbox (new events only, checked by default). Reminder worker confirmed starting on server boot (logged in dev server output). `pnpm typecheck`, `pnpm lint`, `pnpm build` pass.
|
||||
|
||||
## Next up
|
||||
|
||||
- Next task in `docs/tasks/`.
|
||||
|
||||
Reference in New Issue
Block a user