Skip to content

feat: browser push notifications with granular settings#106

Open
crgeee wants to merge 13 commits into
mainfrom
feat/browser-notifications
Open

feat: browser push notifications with granular settings#106
crgeee wants to merge 13 commits into
mainfrom
feat/browser-notifications

Conversation

@crgeee

@crgeee crgeee commented Mar 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add Web Push API notifications using VAPID keys and the web-push npm package
  • Multi-channel delivery: web-push + Pushover in parallel via Promise.allSettled()
  • 6 granular notification preferences (daily briefing, weekly insight, reviews due, streak milestones, AI evaluation complete, task alerts), all user-configurable in Settings > Notifications
  • Per-task custom alerts with date/time picker in the task edit modal
  • Service worker handles push events and notification clicks (focuses existing tab or opens new window)
  • Push subscription management: subscribe/unsubscribe with SSRF-safe endpoint validation (allowlisted push service domains)
  • Security: max 10 subscriptions per user, max 20 alerts per task, alerts capped at 1 year, zod validation on all inputs, expired subscriptions auto-cleaned on 404/410
  • Cron: task alert check every minute (batched per-user), review-due push at 8 AM daily

New files

  • db/020-browser-notifications.sql — migration (push_subscriptions, task_alerts tables, user pref columns)
  • server/push/send.ts — web-push delivery module with VAPID init and endpoint validation
  • server/routes/notifications.ts — subscribe/unsubscribe/test endpoints
  • web/public/sw.js — service worker
  • web/src/lib/push.ts — frontend push subscription manager

Test plan

  • Add VAPID env vars to .env (generate with npx web-push generate-vapid-keys)
  • Run migration: npm run migrate
  • Enable push in Settings > Notifications — browser should prompt for permission
  • Send test notification — should arrive as native browser notification
  • Disable push — should unsubscribe cleanly
  • Add a task alert with date/time picker, verify it fires at the scheduled time
  • Toggle individual notification types on/off and verify preferences persist
  • Verify notifications work when tab is closed (true background push)
  • Check "Notifications blocked" state shows when browser permission is denied

🤖 Generated with Claude Code

crgeee and others added 13 commits March 8, 2026 11:39
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- checkTaskAlerts cron now respects notify_task_alerts user preference
- coach.ts skips send() when userId is not provided
- Alert API responses now return camelCase (rowToAlert transform)
- handleDeleteAlert in TaskEditModal has error handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant