- Add self-hosted push notifications using VAPID (no external services) - Create PushSubscription model in database - Implement server-side push logic with web-push library - Add notification helpers for list events (items, invitations, collaborators) - Create NotificationSettings UI component for profile page - Add usePushNotifications React hook for subscription management - Create API routes for subscription management and VAPID key - Update service worker with push event handlers - Integrate notifications into item actions (add, remove, complete) - Integrate notifications into sharing actions (invite, accept, remove) - Add VAPID key generation script - Add comprehensive documentation and setup guides Notifications are sent when: - Items are added/removed/completed in shared lists - Users are invited to lists - Invitations are accepted - Collaborators are removed from lists Works on iOS 16.4+ (when installed to home screen), Android, and desktop browsers.
265 lines
7.4 KiB
Markdown
265 lines
7.4 KiB
Markdown
# Web Push Notifications - Complete Implementation ✅
|
|
|
|
## What Was Implemented
|
|
|
|
A complete, self-hosted Web Push notification system for your PWA shopping list app.
|
|
|
|
## 📦 Files Created
|
|
|
|
### Core Implementation
|
|
- `lib/push-notifications.ts` - Server-side push notification logic with VAPID
|
|
- `lib/notification-helpers.ts` - Helper functions for specific notification events
|
|
- `hooks/usePushNotifications.ts` - React hook for managing subscriptions
|
|
- `components/NotificationSettings.tsx` - UI component for enabling/disabling notifications
|
|
|
|
### API Routes
|
|
- `app/api/push/vapid-key/route.ts` - Returns public VAPID key
|
|
- `app/api/push/subscribe/route.ts` - Saves push subscriptions
|
|
- `app/api/push/unsubscribe/route.ts` - Removes push subscriptions
|
|
|
|
### Database
|
|
- Updated `prisma/schema.prisma` - Added `PushSubscription` model
|
|
|
|
### Service Worker
|
|
- Updated `public/sw.js` - Added push event handlers
|
|
|
|
### Scripts & Config
|
|
- `scripts/generate-vapid-keys.js` - Generate VAPID keys
|
|
- Updated `package.json` - Added web-push dependency and npm script
|
|
- Updated `.env.example` - Added VAPID key placeholders
|
|
|
|
### Documentation
|
|
- `PUSH_NOTIFICATIONS_QUICK_START.md` - 5-minute setup guide
|
|
- `PUSH_NOTIFICATIONS_SETUP.md` - Complete setup and configuration
|
|
- `PUSH_NOTIFICATIONS_INTEGRATION_EXAMPLE.md` - Code integration examples
|
|
- `PUSH_NOTIFICATIONS_GUIDE.md` - Architecture and testing guide
|
|
- `PUSH_NOTIFICATIONS_COMPLETE.md` - This file
|
|
|
|
## 🎯 How It Works
|
|
|
|
### The Push Notification Server
|
|
|
|
**You don't need an external service!** This implementation uses **VAPID** (Voluntary Application Server Identification), which is a standard protocol that allows your own server to send push notifications directly to browsers.
|
|
|
|
Here's the flow:
|
|
|
|
1. **Generate VAPID Keys** (one-time setup)
|
|
- Run `npm run vapid:generate`
|
|
- These are like JWT secrets - a public/private key pair
|
|
- Public key: shared with browsers
|
|
- Private key: kept secret on your server
|
|
|
|
2. **User Subscribes**
|
|
- User clicks "Enable" in NotificationSettings
|
|
- Browser creates a unique push subscription (includes endpoint URL)
|
|
- Subscription saved to your database
|
|
|
|
3. **Event Occurs**
|
|
- Someone adds an item to a shared list
|
|
- Your server action calls `notifyItemAdded()`
|
|
- Function looks up all subscriptions for list members
|
|
- Sends push notification using `web-push` library
|
|
|
|
4. **Browser Receives**
|
|
- Browser's push service receives the notification
|
|
- Service worker wakes up and displays it
|
|
- User sees notification even if app is closed
|
|
|
|
### The "Server" is Just Your App
|
|
|
|
The push notification "server" is simply:
|
|
- The `web-push` npm package (installed in your app)
|
|
- Your VAPID keys (in your .env file)
|
|
- Your existing Next.js API routes
|
|
|
|
No external service, no additional infrastructure needed!
|
|
|
|
## 🚀 Setup Instructions
|
|
|
|
### Step 1: Install Dependencies
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
### Step 2: Generate VAPID Keys
|
|
```bash
|
|
npm run vapid:generate
|
|
```
|
|
|
|
Copy the output to your `.env` file:
|
|
```env
|
|
VAPID_PUBLIC_KEY=BNxxx...
|
|
VAPID_PRIVATE_KEY=xxx...
|
|
VAPID_SUBJECT=mailto:your-email@example.com
|
|
```
|
|
|
|
### Step 3: Update Database
|
|
```bash
|
|
npx prisma db push
|
|
```
|
|
|
|
### Step 4: Add UI Component
|
|
|
|
In `app/profile/page.tsx`:
|
|
```typescript
|
|
import NotificationSettings from '@/components/NotificationSettings';
|
|
|
|
export default function ProfilePage() {
|
|
return (
|
|
<div>
|
|
{/* Your existing content */}
|
|
<NotificationSettings />
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Step 5: Integrate Notifications
|
|
|
|
In your action files (see `PUSH_NOTIFICATIONS_INTEGRATION_EXAMPLE.md` for details):
|
|
|
|
```typescript
|
|
import { notifyItemAdded } from '@/lib/notification-helpers';
|
|
|
|
// After creating an item:
|
|
await notifyItemAdded(listId, item.title, session.user.id);
|
|
```
|
|
|
|
## 📱 Notification Events
|
|
|
|
| Event | Function | When |
|
|
|-------|----------|------|
|
|
| Item added | `notifyItemAdded()` | Someone adds item to shared list |
|
|
| Item removed | `notifyItemRemoved()` | Someone removes item |
|
|
| Item completed | `notifyItemCompleted()` | Someone marks item complete |
|
|
| List invitation | `notifyListInvitation()` | Someone invites you |
|
|
| Invitation accepted | `notifyInvitationAccepted()` | Someone accepts your invite |
|
|
| Removed from list | `notifyRemovedFromList()` | Owner removes you |
|
|
|
|
## 🌐 Browser Support
|
|
|
|
| Platform | Support | Notes |
|
|
|----------|---------|-------|
|
|
| Chrome Desktop | ✅ Full | Works perfectly |
|
|
| Chrome Android | ✅ Full | Works perfectly |
|
|
| Firefox Desktop | ✅ Full | Works perfectly |
|
|
| Firefox Android | ✅ Full | Works perfectly |
|
|
| Safari macOS | ✅ 16.4+ | Works when installed |
|
|
| Safari iOS | ✅ 16.4+ | **Must be installed to home screen** |
|
|
| Edge | ✅ Full | Chromium-based |
|
|
|
|
### iOS Requirements
|
|
- iOS 16.4 or later
|
|
- Must use "Add to Home Screen" (won't work in Safari browser)
|
|
- Requires HTTPS in production
|
|
|
|
## 🔒 Security
|
|
|
|
- VAPID private key must be kept secret (like JWT secret)
|
|
- Subscriptions are tied to authenticated users
|
|
- Expired subscriptions automatically cleaned up
|
|
- No cross-user notification access
|
|
|
|
## 🧪 Testing
|
|
|
|
### Desktop (Chrome)
|
|
1. Start dev server: `npm run dev`
|
|
2. Open DevTools → Application → Service Workers
|
|
3. Enable notifications in profile
|
|
4. Trigger an action (add item, etc.)
|
|
5. See notification appear
|
|
|
|
### iOS (Real Device)
|
|
1. Deploy with HTTPS
|
|
2. Open in Safari
|
|
3. Share → Add to Home Screen
|
|
4. Open installed app
|
|
5. Enable notifications
|
|
6. Test from another device
|
|
|
|
## 📊 Database Schema
|
|
|
|
New table added:
|
|
```prisma
|
|
model PushSubscription {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
endpoint String @db.Text
|
|
p256dh String @db.Text
|
|
auth String @db.Text
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
user User @relation(...)
|
|
}
|
|
```
|
|
|
|
## 🎨 Customization
|
|
|
|
### Change Notification Content
|
|
Edit `lib/notification-helpers.ts` to customize titles, bodies, icons.
|
|
|
|
### Add Per-List Preferences
|
|
1. Add `notificationsEnabled` to `Collaborator` model
|
|
2. Check this field before sending notifications
|
|
3. Add UI toggle in list settings
|
|
|
|
### Add Notification Sounds
|
|
Update service worker push event:
|
|
```javascript
|
|
const options = {
|
|
...existing,
|
|
silent: false,
|
|
sound: '/notification-sound.mp3',
|
|
};
|
|
```
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### "Push notifications not configured"
|
|
- Verify VAPID keys are in `.env`
|
|
- Restart dev server
|
|
|
|
### Notifications not appearing
|
|
- Check browser permission (must be "granted")
|
|
- Verify service worker is active
|
|
- Check console for errors
|
|
- Ensure HTTPS (or localhost)
|
|
|
|
### iOS not working
|
|
- Check iOS version (16.4+)
|
|
- Must be installed to home screen
|
|
- Check Settings → [App] → Notifications
|
|
|
|
## 📈 Performance
|
|
|
|
- Notifications sent asynchronously (non-blocking)
|
|
- Multiple devices per user supported
|
|
- Automatic cleanup of expired subscriptions
|
|
- TTL: 24 hours
|
|
|
|
## ✅ Production Checklist
|
|
|
|
- [ ] Generate production VAPID keys
|
|
- [ ] Add to production environment variables
|
|
- [ ] Run `npx prisma db push` on production DB
|
|
- [ ] Verify HTTPS is working
|
|
- [ ] Test on actual iOS device
|
|
- [ ] Monitor logs for errors
|
|
|
|
## 🎉 You're Done!
|
|
|
|
Your app now has:
|
|
- ✅ Self-hosted push notifications
|
|
- ✅ No external dependencies
|
|
- ✅ iOS and Android support
|
|
- ✅ Multi-device support
|
|
- ✅ Automatic subscription management
|
|
|
|
Users will receive notifications when:
|
|
- Items are added/removed/completed in shared lists
|
|
- They're invited to lists
|
|
- Their invitations are accepted
|
|
- They're removed from lists
|
|
|
|
All without any external services or additional infrastructure!
|