Refactor notification system

This commit is contained in:
gpt-engineer-app[bot]
2025-10-01 12:29:31 +00:00
parent e2f0df22cc
commit 27b0a3ffff
2 changed files with 542 additions and 0 deletions

304
docs/NOVU_MIGRATION.md Normal file
View File

@@ -0,0 +1,304 @@
# Migrating from Legacy to Novu Notifications
This guide covers migrating from the old notification system to the new Novu-powered system.
## Migration Overview
The new notification system:
- Uses Novu for multi-channel delivery
- Supports granular preferences per workflow
- Includes frequency controls
- Provides delivery tracking
- Backwards compatible with existing preferences
## Data Migration
### Step 1: Migrate Existing User Preferences
The system automatically migrates old preferences from `user_preferences.email_notifications` and `user_preferences.push_notifications` to the new `user_notification_preferences` table.
Run this migration script to batch migrate existing users:
```sql
-- Migrate existing users to new notification preferences
INSERT INTO user_notification_preferences (
user_id,
channel_preferences,
workflow_preferences,
frequency_settings
)
SELECT
user_id,
jsonb_build_object(
'in_app', true,
'email', COALESCE((email_notifications->>'system_announcements')::boolean, true),
'push', COALESCE((push_notifications->>'browser_enabled')::boolean, false),
'sms', false
),
jsonb_build_object(
'review-reply', COALESCE((email_notifications->>'review_replies')::boolean, true),
'new-follower', COALESCE((email_notifications->>'new_followers')::boolean, true),
'system-announcement', COALESCE((email_notifications->>'system_announcements')::boolean, true),
'weekly-digest', COALESCE((email_notifications->>'weekly_digest')::boolean, false),
'monthly-digest', COALESCE((email_notifications->>'monthly_digest')::boolean, true)
),
jsonb_build_object(
'digest', 'daily',
'max_per_hour', 10
)
FROM user_preferences
WHERE NOT EXISTS (
SELECT 1 FROM user_notification_preferences
WHERE user_notification_preferences.user_id = user_preferences.user_id
);
```
### Step 2: Create Novu Subscribers for Existing Users
Create a batch script to register all existing users as Novu subscribers:
```typescript
import { supabase } from '@/integrations/supabase/client';
import { notificationService } from '@/lib/notificationService';
async function migrateUsersToNovu() {
const { data: profiles, error } = await supabase
.from('profiles')
.select('user_id, username, display_name')
.is('banned', false);
if (error) {
console.error('Error fetching profiles:', error);
return;
}
for (const profile of profiles) {
// Get user's auth data for email
const { data: { user } } = await supabase.auth.admin.getUserById(profile.user_id);
if (user?.email) {
await notificationService.createSubscriber({
subscriberId: profile.user_id,
email: user.email,
firstName: profile.display_name?.split(' ')[0],
lastName: profile.display_name?.split(' ').slice(1).join(' '),
data: {
username: profile.username,
},
});
console.log(`Migrated user: ${profile.username}`);
// Rate limit to avoid overwhelming Novu API
await new Promise(resolve => setTimeout(resolve, 100));
}
}
console.log('Migration complete!');
}
```
## Code Migration
### Updating Notification Triggers
**Old Way:**
```typescript
// Direct database insert (legacy)
await supabase
.from('notifications')
.insert({
user_id: userId,
type: 'review_reply',
content: 'Someone replied to your review',
});
```
**New Way:**
```typescript
// Using Novu via notificationService
import { notificationService } from '@/lib/notificationService';
await notificationService.trigger({
workflowId: 'review-reply',
subscriberId: userId,
payload: {
reviewTitle: 'Great ride!',
replyAuthor: 'Jane Doe',
replyContent: 'Thanks for the review!',
reviewUrl: `/reviews/${reviewId}`,
},
});
```
### Updating Preference Management
**Old Way:**
```typescript
await supabase
.from('user_preferences')
.update({
email_notifications: {
review_replies: false,
},
})
.eq('user_id', userId);
```
**New Way:**
```typescript
import { notificationService } from '@/lib/notificationService';
await notificationService.updatePreferences(userId, {
channelPreferences: {
in_app: true,
email: true,
push: false,
sms: false,
},
workflowPreferences: {
'review-reply': false,
},
frequencySettings: {
digest: 'daily',
max_per_hour: 10,
},
});
```
## Rollback Plan
If you need to rollback to the old system:
1. **Keep Old Tables**: Don't drop `user_preferences.email_notifications` or `push_notifications` columns
2. **Disable Novu**: Clear `VITE_NOVU_APPLICATION_IDENTIFIER` environment variable
3. **Revert Code**: The notification service gracefully handles missing Novu config
## Testing the Migration
### Test Checklist
- [ ] All existing users have entries in `user_notification_preferences`
- [ ] User preferences match their previous settings
- [ ] Test users receive notifications on all enabled channels
- [ ] Webhook is receiving delivery events
- [ ] Notification logs are being created
- [ ] User preference changes sync to Novu
- [ ] Unsubscribe links work correctly
- [ ] Email templates render correctly
- [ ] Push notifications work in supported browsers
- [ ] In-app notifications display correctly
### Test Script
```typescript
// Test notification delivery
import { notificationService } from '@/lib/notificationService';
async function testNotifications(testUserId: string) {
console.log('Testing notification delivery...');
// Test each workflow
const workflows = [
{
id: 'review-reply',
payload: {
reviewTitle: 'Test Review',
replyAuthor: 'Test User',
replyContent: 'Test reply content',
reviewUrl: '/test',
},
},
{
id: 'new-follower',
payload: {
followerName: 'Test Follower',
followerProfile: '/profile/test',
},
},
];
for (const workflow of workflows) {
const result = await notificationService.trigger({
workflowId: workflow.id,
subscriberId: testUserId,
payload: workflow.payload,
});
console.log(`${workflow.id}: ${result.success ? '✓' : '✗'}`);
if (!result.success) {
console.error(`Error: ${result.error}`);
}
}
}
```
## Performance Considerations
### Batch Operations
When migrating large numbers of users:
1. **Rate Limiting**: Add delays between API calls
2. **Batch Size**: Process in chunks of 100-500 users
3. **Error Handling**: Log failures and retry
4. **Progress Tracking**: Store migration state
### Optimization Tips
1. **Cache Templates**: Load notification templates once at startup
2. **Async Processing**: Use edge functions for heavy operations
3. **Database Indexes**: Already created on `user_notification_preferences`
4. **Connection Pooling**: Supabase handles this automatically
## Monitoring Post-Migration
Track these metrics after migration:
```sql
-- Delivery success rate
SELECT
DATE(created_at) as date,
COUNT(*) FILTER (WHERE status = 'delivered') * 100.0 / COUNT(*) as success_rate
FROM notification_logs
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY DATE(created_at)
ORDER BY date DESC;
-- Channel usage
SELECT
channel,
COUNT(*) as total_sent,
COUNT(*) FILTER (WHERE status = 'delivered') as delivered,
COUNT(*) FILTER (WHERE read_at IS NOT NULL) as read
FROM notification_logs
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY channel;
-- User engagement
SELECT
COUNT(DISTINCT user_id) as active_users,
AVG(EXTRACT(EPOCH FROM (read_at - delivered_at))) as avg_time_to_read_seconds
FROM notification_logs
WHERE read_at IS NOT NULL
AND created_at > NOW() - INTERVAL '7 days';
```
## Support During Migration
1. **Backup Data**: Export old notification preferences before migration
2. **Phased Rollout**: Enable for a subset of users first
3. **Feature Flag**: Use admin settings to control Novu enablement
4. **User Communication**: Notify users of new notification features
5. **Monitor Logs**: Watch edge function logs during migration
## Timeline
Recommended migration timeline:
- **Week 1**: Test with internal users
- **Week 2**: Rollout to 10% of users
- **Week 3**: Rollout to 50% of users
- **Week 4**: Complete rollout
- **Week 5**: Remove legacy code (optional)

238
docs/NOVU_SETUP.md Normal file
View File

@@ -0,0 +1,238 @@
# Novu Cloud Integration Setup Guide
This guide will help you set up and configure Novu Cloud for the ThrillWiki notification system.
## Overview
The notification system uses Novu Cloud for managing multi-channel notifications including:
- In-app notifications
- Email notifications
- Push notifications
- SMS notifications (planned)
## Prerequisites
1. A Novu Cloud account (sign up at https://novu.co)
2. Access to the Supabase project
3. Environment variable configuration access
## Step 1: Create a Novu Cloud Account
1. Go to https://novu.co and sign up
2. Create a new application in the Novu dashboard
3. Note down your **Application Identifier** from the Settings page
## Step 2: Configure Environment Variables
Add the following environment variables to your `.env` file:
```bash
# Novu Configuration
VITE_NOVU_APPLICATION_IDENTIFIER="your-app-identifier"
VITE_NOVU_SOCKET_URL="wss://ws.novu.co"
VITE_NOVU_API_URL="https://api.novu.co"
```
## Step 3: Add Novu API Key to Supabase Secrets
The Novu API key needs to be stored as a Supabase secret (already done via the setup):
1. Go to your Novu dashboard
2. Navigate to Settings > API Keys
3. Copy your API Key
4. The secret `NOVU_API_KEY` should already be configured in Supabase
## Step 4: Create Novu Workflows
Create the following workflows in your Novu dashboard to match the templates in the database:
### 1. Review Reply (`review-reply`)
**Trigger Identifier:** `review-reply`
**Channels:** Email, In-App
**Payload Variables:**
- `reviewTitle` - Title of the review
- `replyAuthor` - Name of the person who replied
- `replyContent` - Content of the reply
- `reviewUrl` - Link to the review
### 2. New Follower (`new-follower`)
**Trigger Identifier:** `new-follower`
**Channels:** Email, In-App, Push
**Payload Variables:**
- `followerName` - Name of the new follower
- `followerProfile` - Link to the follower's profile
### 3. System Announcement (`system-announcement`)
**Trigger Identifier:** `system-announcement`
**Channels:** Email, In-App, Push
**Payload Variables:**
- `title` - Announcement title
- `content` - Announcement content
- `priority` - Priority level (info, warning, critical)
### 4. Weekly Digest (`weekly-digest`)
**Trigger Identifier:** `weekly-digest`
**Channels:** Email
**Payload Variables:**
- `userName` - User's name
- `weekStart` - Start date of the week
- `weekEnd` - End date of the week
- `stats` - Activity statistics object
- `highlights` - Array of highlighted content
### 5. Monthly Digest (`monthly-digest`)
**Trigger Identifier:** `monthly-digest`
**Channels:** Email
**Payload Variables:**
- `userName` - User's name
- `month` - Month name
- `stats` - Monthly statistics object
- `topContent` - Array of popular content
### 6. Moderation Alert (`moderation-alert`)
**Trigger Identifier:** `moderation-alert`
**Channels:** Email, In-App
**Payload Variables:**
- `itemType` - Type of content (review, photo, etc.)
- `itemId` - ID of the item
- `submitterName` - Name of the submitter
- `moderationUrl` - Link to moderation queue
### 7. Content Approved (`content-approved`)
**Trigger Identifier:** `content-approved`
**Channels:** Email, In-App
**Payload Variables:**
- `contentType` - Type of content
- `contentTitle` - Title/name of content
- `contentUrl` - Link to the approved content
### 8. Content Rejected (`content-rejected`)
**Trigger Identifier:** `content-rejected`
**Channels:** Email, In-App
**Payload Variables:**
- `contentType` - Type of content
- `contentTitle` - Title/name of content
- `rejectionReason` - Reason for rejection
## Step 5: Configure Webhook (Optional)
To track notification delivery status:
1. Go to Novu Dashboard > Settings > Webhooks
2. Add a new webhook endpoint: `https://ydvtmnrszybqnbcqbdcy.supabase.co/functions/v1/novu-webhook`
3. Select events: `notification.sent`, `notification.delivered`, `notification.read`, `notification.failed`
## Step 6: Test the Integration
Run these tests to ensure everything works:
### Test Subscriber Creation
```typescript
import { notificationService } from '@/lib/notificationService';
await notificationService.createSubscriber({
subscriberId: 'user-id',
email: 'user@example.com',
firstName: 'John',
lastName: 'Doe',
});
```
### Test Notification Trigger
```typescript
import { notificationService } from '@/lib/notificationService';
await notificationService.trigger({
workflowId: 'review-reply',
subscriberId: 'user-id',
payload: {
reviewTitle: 'Great ride!',
replyAuthor: 'Jane Doe',
replyContent: 'Thanks for the review!',
reviewUrl: 'https://example.com/review/123',
},
});
```
## Architecture
### Database Tables
1. **notification_templates** - Stores workflow configuration
2. **notification_logs** - Tracks sent notifications
3. **notification_channels** - Manages available channels
4. **user_notification_preferences** - User preferences and Novu subscriber mapping
### Edge Functions
1. **create-novu-subscriber** - Creates/updates Novu subscribers
2. **update-novu-preferences** - Syncs preferences with Novu
3. **trigger-notification** - Triggers notification workflows
4. **novu-webhook** - Handles Novu webhook events
### Frontend Components
1. **NotificationsTab** - User preferences management
2. **NotificationCenter** - In-app notification display
3. **notificationService** - Core notification logic
## Switching to Self-Hosted Novu
To switch to a self-hosted Novu instance:
1. Update environment variables:
```bash
VITE_NOVU_SOCKET_URL="wss://your-novu-instance.com"
VITE_NOVU_API_URL="https://your-novu-instance.com/api"
```
2. Update the Novu API key in Supabase secrets to match your self-hosted instance
3. No code changes required! The system is designed to work with both Cloud and self-hosted versions
## Troubleshooting
### Notifications Not Sending
1. Check that `VITE_NOVU_APPLICATION_IDENTIFIER` is set
2. Verify `NOVU_API_KEY` is configured in Supabase secrets
3. Check edge function logs: https://supabase.com/dashboard/project/ydvtmnrszybqnbcqbdcy/functions
4. Verify workflow IDs match between database and Novu dashboard
### User Not Receiving Notifications
1. Check user's notification preferences in the database
2. Verify subscriber was created in Novu
3. Check notification logs table for delivery status
4. Verify user's email/push permission settings
### Webhook Not Working
1. Verify webhook URL is correct in Novu dashboard
2. Check that `novu-webhook` edge function has `verify_jwt = false`
3. Review edge function logs for errors
## Monitoring
Track notification performance:
1. View delivery rates in `notification_logs` table
2. Monitor edge function logs for errors
3. Check Novu dashboard analytics
4. Query notification statistics:
```sql
SELECT
status,
COUNT(*) as count,
AVG(EXTRACT(EPOCH FROM (delivered_at - created_at))) as avg_delivery_time_seconds
FROM notification_logs
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY status;
```
## Support
- Novu Documentation: https://docs.novu.co
- Novu Discord: https://discord.gg/novu
- ThrillWiki Support: [Add support contact]