Skip to main content

Notifications

Architecture

Toast functions

All located in src/lib/show-notifications.tsx:

FunctionUse case
showSuccessToast(title, message)Successful mutation
showFailedToast(title, message)Failed operation
showInfoToast(title, message)Informational
showWarningToast(title, message)Warning

handleServerSuccess signature

handleServerSuccess(
request?, // mutation input variables
response?, // mutation response data
translationKey?, // becomes notification title (use t() key)
invalidateQueryKeys?,
message? // becomes notification message (app title / context)
)

Notification triggers

EventTitleMessage
Application createdt('success.created')variables.input.title
Application updatedt('success.updated')data.title from response
Comment addedt('success.commented')"Domain · AppTitle · Visibility"
Document reviewedt('success.reviewed')App title (optional)
Applicant CRUDt('success.*')application?.title from context

Message format

The message field uses · as separator for structured context:

"Domain · Application Title · Visibility"

Examples:

  • "Application · My Tax App · Internal"
  • "Document · My Tax App · External"
  • "My Tax App" — plain app title for create/update events

parseContext() in notification-panel.tsx splits on ·{ label, title, visibility }.

Key files

FilePurpose
src/stores/notification-store.tsZustand store: unread count, flush queue, settings
src/lib/show-notifications.tsxToast helper functions
src/features/notifications/notification-flusher.tsxFlushes queue to backend; polls unread count every 30s
src/features/notifications/notification-bell.tsxBell icon with unread badge
src/features/notifications/notification-panel.tsxSheet panel: list, mark-read, settings
src/features/notifications/hooks/use-notifications.tsAll GraphQL hooks
src/components/layout/authenticated-layout.tsxMounts NotificationFlusher and NotificationBell

Adding a new notification source

  1. Call showSuccessToast(title, appTitle) on mutation success — that's sufficient for most cases
  2. For hooks using handleServerSuccess, pass app title as 5th argument
  3. For hooks inside ApplicationProvider, use useApplicationContext() to get application?.title
  4. The flusher persists everything automatically — no extra wiring needed

See also