Overview
OpenCouncil’s notification system automatically sends targeted updates to citizens about council meeting subjects relevant to their location and topic preferences. Notifications are delivered via multiple channels—email, WhatsApp, and SMS—at two key moments: before meetings (agenda preview) and after meetings (summary).System architecture
The notification system consists of several interconnected data models:Notification
Core record linking a user to a specific meeting and type (before/after)Relations: user, city, meeting, deliveries, subjects
NotificationSubject
Links notifications to relevant meeting subjects with a reason (proximity, topic, or general interest)Unique constraint: One entry per (notification, subject) pair
NotificationDelivery
Represents an upcoming or completed delivery via email or messageFields: title, body, email, phone, status (pending/sent/failed), messageSentVia (whatsapp/sms)
Notification creation triggers
Notifications are created automatically when specific tasks complete, or manually by administrators.- Before meeting
- After meeting
- Manual creation
Created when
processAgenda task completes successfullyContent: Preview of meeting subjects based on processed agendaBehavior: Controlled by administrative body’s notificationBehavior settingSubject-to-user matching
The notification system uses sophisticated matching logic to determine which users should be notified about which subjects.Subject importance levels
Each subject has two importance dimensions:Topic importance
- doNotNotify: No topic-based notifications
- normal: Notify users interested in the topic
- high: Notify all users (general interest)
Proximity importance
- none: No location-based notifications
- near: Notify users within 250m
- wide: Notify users within 1000m
Matching rules
A user receives a notification for subject S if any of these conditions are met:Near proximity
S.proximityImportance is near AND user has a location within 250m of subject locationIf no subjects match any user through these rules, no notifications are created at all.
Statistics
The creation process produces two key metrics:- Notifications created: Number of users notified (one notification per user)
- NotificationSubjects created: Total subjects across all users
Notification deliveries
NotificationDeliveries represent the actual sending of notifications through specific channels.Delivery lifecycle
Creation
All deliveries are initially created with
pending status:- Email delivery: Always created for every notification
- Message delivery: Created additionally if user has a phone number
Email delivery
Email content
Email content
Title format:
OpenCouncil {municipalityName}: {adminBody} - {date}Body content: Formatted HTML email containing:- Titles, topics, and descriptions of all notification subjects
- Navigation buttons (top and bottom) linking to the notification view page
Sending process
Sending process
- Sent using Resend service
- Uses title and body created during delivery creation
- Status updated to
senton success
Message delivery (WhatsApp/SMS)
Message delivery flow
Service: All message delivery handled through Bird APIWhatsApp-first approach:
- Attempts WhatsApp delivery using pre-approved templates
- Falls back to SMS via Bird if WhatsApp fails
messageSentVia field tracks actual delivery method (whatsapp/sms)WhatsApp template system
WhatsApp requires pre-approved templates for users who haven’t messaged in 24 hours (always assumed).- Before meeting template
- After meeting template
Used for
beforeMeeting notificationsParameters:date: Meeting datecityName: City name (e.g., “Athens”)subjectsSummary: Comma-separated subject titlesadminBody: Administrative body namenotificationId: For redirect button to/notifications/{id}
Both templates take exactly the same parameters for consistency.
SMS fallback
If WhatsApp delivery fails, the system uses SMS with the body content created during delivery creation.Administrative body notification flow
Each administrative body has anotificationBehavior setting that controls the notification lifecycle:
- NOTIFICATIONS_DISABLED
- NOTIFICATIONS_AUTO
- NOTIFICATIONS_APPROVAL
Behavior: Skip notification creation entirelyUse case: Bodies that don’t want any automated notifications
Core implementation
The notification system is implemented across several key modules:Matching engine
src/lib/notifications/matching.ts
Notification creation
src/lib/db/notifications.ts
- Checks administrative body notification behavior
- Gets all users with preferences for the city
- Applies importance rules and matches subjects to users
- Creates Notification records with NotificationSubjects
- Creates NotificationDeliveries (email + message if phone exists)
- Optionally sends immediately if
NOTIFICATIONS_AUTO
Proximity calculations
src/lib/db/notifications.ts
ST_DWithin to calculate geographic distances, with special handling for inverted coordinates outside Greece bounds.
Delivery system
src/lib/notifications/deliver.ts
- Sends emails via Resend
- Sends messages via Bird (WhatsApp → SMS fallback)
- Updates delivery status and
messageSentVia - Implements 500ms delays to avoid rate limiting
Content generation
Notification content is generated at creation time:Automatic triggers
Notifications are automatically triggered from task handlers:- Process agenda handler
- Summarize handler
src/lib/tasks/processAgenda.ts
Admin notification management
Administrators manage notifications through/admin/notifications with:
Administrative body settings
Configure
notificationBehavior per body with impact summariesNotification filters
Filter by status, city, administrative body, date range
Grouped notification list
Hierarchical view: City → Admin Body → Meeting → Type (before/after)
Bulk actions
Release all, release selected, view failed deliveries, convert to auto
User preference management
Users manage their notification preferences through a simple profile integration:Per-city actions
- Edit button: Redirects to existing
/{cityId}/notificationsUI - Unsubscribe button: Deletes
NotificationPreferencerecord
Security and authorization
- Only super admins can access
/admin/notifications - City admins can create notifications for their city’s meetings
- Delivery content is sanitized before sending
- Unsubscribe links include secure tokens
Performance considerations
Rate limiting
Rate limiting
500ms delays between delivery attempts prevent rate limit issues with email and messaging services.
Chunked processing
Chunked processing
Bulk operations process notifications in chunks to prevent timeouts on large datasets.
Database indexing
Database indexing
Strategic indexes on
status, createdAt, and composite keys optimize common query patterns.PostGIS queries
PostGIS queries
Proximity calculations use PostGIS geography type for accurate distance measurements on Earth’s surface.
File reference
Key implementation files
src/lib/db/notifications.ts- Core notification creation and managementsrc/lib/notifications/matching.ts- Subject-to-user matching logicsrc/lib/notifications/deliver.ts- Multi-channel delivery systemsrc/lib/notifications/content.ts- Email and SMS content generationsrc/lib/notifications/bird.ts- Bird API integration (WhatsApp/SMS)prisma/schema.prisma- Notification data models (lines 920-1013)