Notifications & Announcements
One-line: Reaches students, parents, and staff through in-app alerts, real-time streams, mobile push, and email — driven by reusable templates and school-wide announcements.
What it does
- Templated notifications — business events (fee overdue, attendance marked, leave approved) render a reusable template with per-recipient context.
- In-app notifications — every alert is stored and shown in a bell-icon inbox with an unread count, mark-as-read, and deep links.
- Real-time SSE stream — the inbox updates live over a
text/event-streamconnection, with an optional sound chime on arrival. - Push to mobile — delivered to registered devices via Firebase Cloud Messaging (FCM) and Expo push for the Expo app.
- Email — sent through the shared mailer using HTML templates.
- School announcements — admins author broadcasts that land in the same inbox as everything else.
Who uses it
- Admins / staff — send manual notifications, author and recall announcements, manage templates.
- Parents / students / teachers — receive alerts in-app, on mobile, and by email.
Key concepts
- Notification template — a named, event-triggered layout (
subject,body_template) rendered with Jinja context; can targetin_app,push,email, or a combination. - In-app notification — a stored record (
title,message,type,action_url,is_read). - SSE stream — long-lived
GET /api/notifications/streampushing new items as they arrive. - Device registration / token — a mobile device registers its FCM/Expo token so push can reach it.
- Push (Firebase / Expo) — device delivery via FCM HTTP v1 and the Expo push API.
- Announcement — a sibling module (
draft → scheduled → published → recalled) that fans out to the same inbox. - Mailer / email — shared email sender with reusable HTML templates.
How it works
Business event (e.g. fee marked overdue)
-> dispatch template for the event, render with per-user context
-> for each recipient:
- create in-app Notification (also pushed over SSE)
- send push to registered devices (FCM / Expo)
- send email if the template has an email channelAnnouncements are authored by admins; on publish, a fan-out task creates one parent notification plus recipient rows, so readers see them alongside normal alerts.
Rules & edge cases
- Gated by the plan key
notifications; permissions use thenotification.*/announcement.*prefixes. - Everything is tenant-scoped — templates may be tenant-specific or platform-level (
tenant_idnull). - The SSE route calls
db.session.remove()before streaming so a live connection never parks a DB pool slot; a keepalive (SSE_KEEPALIVE_SEC, default 15s) doubles as dead-client detection. On a single-worker deployment, long-lived SSE connections can consume worker threads, so thread count must be sized for expected concurrent streams. - Announcement attachments are S3-backed; unpublished draft attachments are swept after 24h.
- Push requires Firebase service-account credentials; email in production runs through the deployment’s SMTP relay (AWS SES), which starts in sandbox mode until a sending limit is granted — see infrastructure.
Where it lives
server/modules/notifications/— templates, dispatch, SSE, pushserver/modules/devices/— device token registrationserver/modules/announcements/— announcement authoring and fan-outserver/modules/mailer/— email templates and sending- admin-web — bell inbox, dropdown, chime, template management
- mobile client — device registration and push receipt
- Plan key:
notifications