Complete end-to-end implementation of the notification subscription feature for the Tikka raffle platform. Users can subscribe to receive notifications when a raffle ends or when they win.
✅ Frontend UI Components
- Subscribe/unsubscribe buttons on raffle detail pages
- Compact bell icon for raffle cards
- Settings page with notification preferences
- Real-time subscription status updates
✅ Backend API
- RESTful endpoints for subscription management
- JWT authentication integration
- Supabase database storage
- Efficient querying with indexes
✅ Database
- Notifications table with proper constraints
- Indexed for performance
- RLS enabled for security
┌─────────────────────────────────────────────────────────────┐
│ Frontend │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Components │ │
│ │ - NotificationSubscribeButton │ │
│ │ - NotificationBellIcon │ │
│ │ - NotificationPreferences │ │
│ │ - Settings Page │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Hooks & Services │ │
│ │ - useNotifications (React Hook) │ │
│ │ - notificationService (API Client) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ HTTPS/JWT
▼
┌─────────────────────────────────────────────────────────────┐
│ Backend │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ REST API (NestJS) │ │
│ │ - POST /notifications/subscribe │ │
│ │ - DELETE /notifications/subscribe/:raffleId │ │
│ │ - GET /notifications/subscriptions │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Services │ │
│ │ - NotificationsService (Business Logic) │ │
│ │ - NotificationService (Supabase Integration) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ Supabase Client
▼
┌─────────────────────────────────────────────────────────────┐
│ Database │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ notifications table │ │
│ │ - id (UUID) │ │
│ │ - raffle_id (INTEGER) │ │
│ │ - user_address (VARCHAR) │ │
│ │ - channel (VARCHAR) │ │
│ │ - created_at (TIMESTAMP) │ │
│ │ UNIQUE(raffle_id, user_address) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
User visits raffle detail page
↓
Sees "Stay Updated" section with "Notify Me" button
↓
Clicks button (if not signed in, prompted to authenticate)
↓
Frontend calls POST /notifications/subscribe with JWT
↓
Backend validates JWT and creates subscription
↓
Subscription stored in database
↓
Frontend updates button to show "Unsubscribe"
↓
Success message displayed
User navigates to /settings
↓
Clicks "Notifications" tab
↓
Frontend calls GET /notifications/subscriptions
↓
Backend returns all user subscriptions
↓
User sees list of active subscriptions
↓
User clicks unsubscribe on a raffle
↓
Frontend calls DELETE /notifications/subscribe/:raffleId
↓
Backend removes subscription
↓
Frontend updates list
Location: client/
Key Files:
src/services/notificationService.ts- API clientsrc/hooks/useNotifications.ts- React hooksrc/components/NotificationSubscribeButton.tsx- Main buttonsrc/components/NotificationBellIcon.tsx- Compact iconsrc/components/NotificationPreferences.tsx- Settings panelsrc/pages/Settings.tsx- Settings pagesrc/config/api.ts- API endpointssrc/types/types.ts- TypeScript types
Documentation: client/docs/NOTIFICATIONS.md
Location: backend/
Key Files:
src/api/rest/notifications/notifications.controller.ts- HTTP endpointssrc/api/rest/notifications/notifications.service.ts- Business logicsrc/api/rest/notifications/notifications.module.ts- Module configsrc/services/notification.service.ts- Supabase integrationsrc/api/rest/notifications/dto/subscribe.dto.ts- Request validationdatabase/migrations/002_notifications.sql- Database schema
Documentation: backend/NOTIFICATION_IMPLEMENTATION.md
Run the migration in Supabase SQL Editor:
# Navigate to Supabase dashboard
# Go to SQL Editor
# Copy contents of backend/database/migrations/002_notifications.sql
# Execute the SQLcd backend
# Install dependencies (if not already installed)
npm install
# Ensure environment variables are set
# SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, JWT_SECRET
# Start the server
npm run devBackend will be available at http://localhost:3001
cd client
# Install dependencies (if not already installed)
npm install
# Ensure environment variables are set
# VITE_API_BASE_URL=http://localhost:3001
# Start the development server
npm run devFrontend will be available at http://localhost:5173
-
Start both servers (backend and frontend)
-
Sign in with wallet
- Connect Stellar wallet
- Complete SIWS authentication
- Verify JWT token is stored
-
Subscribe to raffle
- Navigate to a raffle detail page
- Click "Notify Me" button
- Verify button changes to "Unsubscribe"
- Check success message appears
-
View subscriptions
- Navigate to
/settings - Click "Notifications" tab
- Verify subscription appears in list
- Navigate to
-
Unsubscribe
- Click unsubscribe button
- Verify subscription is removed from list
-
Test without auth
- Sign out
- Try to subscribe
- Verify authentication prompt appears
See backend/NOTIFICATION_IMPLEMENTATION.md for detailed cURL examples.
Subscribe to raffle notifications.
Authentication: Required (JWT)
Request:
{
"raffleId": 123,
"channel": "email"
}Response (201):
{
"id": "uuid",
"raffle_id": 123,
"user_address": "GXXX...",
"channel": "email",
"created_at": "2024-02-25T10:30:00Z"
}Unsubscribe from raffle notifications.
Authentication: Required (JWT)
Response: 204 No Content
Get all user subscriptions.
Authentication: Required (JWT)
Response (200):
[
{
"id": "uuid",
"raffle_id": 123,
"user_address": "GXXX...",
"channel": "email",
"created_at": "2024-02-25T10:30:00Z"
}
]CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
raffle_id INTEGER NOT NULL,
user_address VARCHAR(56) NOT NULL,
channel VARCHAR(20) NOT NULL DEFAULT 'email',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT unique_raffle_user UNIQUE (raffle_id, user_address)
);
-- Indexes for performance
CREATE INDEX idx_notifications_raffle_id ON notifications(raffle_id);
CREATE INDEX idx_notifications_user_address ON notifications(user_address);
CREATE INDEX idx_notifications_created_at ON notifications(created_at DESC);- ✅ JWT authentication required for all endpoints
- ✅ Users can only manage their own subscriptions
- ✅ Rate limiting via global throttler guard
- ✅ Input validation with DTOs
- ✅ SQL injection protection via Supabase
- ✅ Unique constraint prevents duplicates
- ✅ RLS enabled for future policies
- ✅ Database indexes for fast queries
- ✅ Efficient Supabase connection pooling
- ✅ Optimized React hooks with proper dependencies
- ✅ Minimal re-renders with state management
- ✅ Lazy loading of subscription data
- Email service integration (SendGrid/AWS SES)
- Push notification service (Firebase/OneSignal)
- Event listeners for raffle end/win
- Notification templates
- SMS notifications (Twilio)
- Discord/Telegram webhooks
- Notification preferences (frequency, types)
- Notification history/log
- Batch operations
- Subscription metrics dashboard
- Delivery success tracking
- User engagement analytics
- A/B testing for notifications
Subscription button not working
- Check if user is authenticated
- Verify JWT token in sessionStorage
- Check browser console for errors
- Verify API_BASE_URL is correct
Subscriptions not loading
- Check network tab for API calls
- Verify backend is running
- Check JWT token is valid
- Review backend logs
Cannot create subscription
- Verify database migration ran
- Check Supabase connection
- Review server logs
- Verify JWT secret matches
Duplicate subscription error
- This is expected behavior
- Frontend should handle gracefully
- Returns existing subscription
- Frontend:
client/docs/NOTIFICATIONS.md - Frontend Implementation:
client/NOTIFICATION_IMPLEMENTATION.md - Backend Implementation:
backend/NOTIFICATION_IMPLEMENTATION.md - This Document: Complete feature overview
This implementation resolves GitHub Issue #27:
✅ Users can subscribe to raffle notifications ✅ Backend supports POST /notifications/subscribe ✅ Client offers clear subscription flow ✅ Settings page for notification preferences ✅ JWT authentication integrated ✅ Database table created ✅ API endpoints implemented ✅ UI components created ✅ Documentation complete
-
Deploy to staging
- Run database migration on staging
- Deploy backend with new endpoints
- Deploy frontend with new components
- Test end-to-end flow
-
Implement notification delivery
- Choose email service provider
- Set up event listeners
- Create notification templates
- Test delivery flow
-
Monitor and optimize
- Track subscription metrics
- Monitor API performance
- Gather user feedback
- Iterate on UX
For questions or issues:
- Review documentation in
client/docs/andbackend/ - Check server logs for errors
- Verify database schema in Supabase
- Test API endpoints with cURL
- Review browser console for frontend errors