Appearance
IE.8: In-App Notification Delivery
Summary
In-app notifications are rendered from notification templates, stored as notification records, and pushed to connected clients over SSE. Users see them through the notification dropdown and Inbox notification tab, where they can mark notifications read, mark all read, or archive them.
Role
- Primary: Client, Counselor, Admin
- Secondary: System
Entry Point
- Notification producer services: booking, meeting, assessment, messaging, and other system events
- Realtime stream:
/api/v1/realtime/stream - Frontend UI: notification dropdown,
/inbox?tab=notifications - APIs:
GET /notifications,GET /notifications/unread-count,POST /notifications/:id/read,POST /notifications/:id/archive,POST /notifications/read-all
Preconditions
- Recipient has a user account.
- Notification template exists for templated notifications, or caller provides simple content.
- SSE service is initialized for realtime delivery.
Steps
- A backend service requests a templated or simple in-app notification.
- For templated notifications, backend resolves template key and language, with English fallback.
- Backend renders the notification body.
- Backend creates a
notificationsrow withnotification_type=in_app, category, recipient, sender, content, and delivered status. - Backend publishes an SSE
notificationevent to the recipient's user notification channel. - Frontend realtime provider receives the notification event and adds it to the notification store.
- If browser notification permission is granted, frontend can show a browser notification.
- Notification dropdown and Inbox notification tab fetch unread/list state from the API.
- User selects a notification; the Inbox auto-marks it read after a short delay.
- User can mark a notification read, mark all read, or archive/delete a notification.
Diagram
Edge Cases
- Template missing: Templated notification send returns/logs an error depending on the caller; domain actions usually continue.
- SSE failure: Notification remains persisted even if realtime publish fails.
- Reconnect gap: Frontend realtime provider fetches missed notifications after reconnect.
- Ownership: Notification read/archive/get APIs verify recipient ownership.
- HTML content: Inbox sanitizes notification HTML before rendering.
- Message notifications: Message notification templates exist for
message_received; realtime message events and notification events are handled separately by the frontend provider.
Current Implementation Notes
- Backend:
backend/internal/services/in_app_notification_service.go,backend/internal/services/notification_service.go,backend/internal/services/sse_service.go - Frontend:
frontend/src/features/conversations/components/realtime-provider.tsx,frontend/src/shared/store/notification-store.ts,frontend/src/app/pages/inbox.tsx,frontend/src/shared/components/notifications/notification-dropdown.tsx - Templates:
backend/scripts/seed_notification_templates.sql,backend/scripts/seeds/007_seed_message_notification_templates.sql
Screenshot Status
- Not captured.