Notifications
Notifications owns in-app notifications, event preferences, email templates, delivery queue, send logs, and Resend webhook updates.
On this page
Where to look
| Area | Paths |
|---|---|
| Routes | src/app/(dashboard)/communications, /communications/outbound, /communications/outbound/settings, /communications/outbound/templates |
| Webhook | src/app/api/notifications/webhooks/resend |
| Event registry | src/features/notifications/server/notification-events.ts |
| In-app | src/features/notifications/server/in-app, src/features/notifications/ui/bell.tsx, list.tsx |
| Delivery | src/features/notifications/server/delivery |
| Outbox | src/features/notifications/server/outbox, src/features/notifications/ui/outbox |
| Templates | src/features/notifications/server/templates, src/features/notifications/ui/templates |
| Settings | src/features/notifications/server/settings, src/features/notifications/ui/settings |
Code-backed notifications map
Canonical event registry
Notification keys are defined once so templates, preferences, delivery, and webhook flows use the same vocabulary.
src/features/notifications/server/notification-events.ts
Queue and dedupe
Product code queues work into notification_outbox, canonicalizes event keys, and treats unique dedupe conflicts as already queued.
src/features/notifications/server/delivery/queue/notify-queue.ts
Worker and retry behavior
The worker atomically claims rows, dispatches through the delivery registry, marks success or failure, and moves exhausted rows to dead letter.
src/features/notifications/server/outbox/services/worker.tssrc/features/notifications/server/delivery/registry.ts
Templates and provider updates
Template runtime code renders event-specific messages, while Resend webhooks update delivery status after provider callbacks arrive.
src/features/notifications/server/templates/services/runtime.tssrc/features/notifications/server/templates/services/render.tssrc/app/api/notifications/webhooks/resend/route.ts
Notification delivery flow
- 1
Choose a canonical event key
Callers use a canonical event key for preferences and delivery logs. Application-owned events may also have editable templates; team.invite remains Supabase Auth-owned.
src/features/notifications/server/notification-events.ts
- 2
Queue the work
The queue helper writes notification_outbox rows with recipient, payload, resource id, dedupe key, status, and next attempt time.
src/features/notifications/server/delivery/queue/notify-queue.ts
- 3
Claim atomically
The worker uses claim_notification_batch to avoid two workers sending the same queued message.
src/features/notifications/server/outbox/services/worker.tssupabase/migrations/20260426000000_init.sql
- 4
Dispatch, retry, or dead-letter
Delivery runs through the registry, records provider status, retries transient failures with backoff, and dead-letters exhausted rows.
src/features/notifications/server/outbox/services/worker.tssrc/features/notifications/server/delivery/registry.ts
Notification event registry
Source: src/features/notifications/server/notification-events.ts
Add events here first, then explicitly decide whether delivery is Supabase Auth-owned or application-owned before adding an editable template.
export const NOTIFICATION_EVENT_KEY_VALUES = [
"lead.new",
"lead.contact.message",
"team.invite",
"auth.signup.welcome",
"system.alert",
"operations.stripe.dispute.created",
"billing.invoice.payment_succeeded",
"billing.invoice.payment_failed",
"billing.subscription.expiring_soon",
] as const;Recipe: add an email event
Add a notification event that can be queued, templated, retried, and audited without sending from unrelated product code.
Inspect
- src/features/notifications/server/notification-events.ts
- src/features/notifications/server/delivery/registry.ts
- src/features/notifications/server/templates/services/runtime.ts
- src/features/notifications/server/outbox/services/worker.ts
Edit
- src/features/notifications/server/notification-events.ts
- src/features/notifications/server/delivery/registry.ts
- src/features/notifications/server/templates/shared/defaults.ts
- src/features/notifications/server/templates/shared/constants.ts
Steps
- Add the event key to the registry.
- Add or update the default template and allowed variables.
- Add delivery handling through the registry.
- Queue the event from the product module using a dedupe key when duplicate source events are possible.
Verify
- pnpm run test:features
- pnpm run quality
- Trigger the event in test mode and confirm notification_outbox status changes.
Common mistakes
- Do not send provider email directly from billing, auth, team, or contact code.
- Do not invent event keys outside the registry.
- Do not hide retry errors from the outbox UI.
AI prompt: notification event
Add a notification event for <event>. Inspect the canonical event registry, delivery registry, template runtime, outbox worker, and the source module that queues the event. Keep provider sending inside the notification delivery boundary and preserve retry/dead-letter behavior.Inspect first
- src/features/notifications/server/notification-events.ts
- src/features/notifications/server/delivery/registry.ts
- src/features/notifications/server/outbox/services/worker.ts
Verify
- pnpm run test:features
- pnpm run quality
Delivery rules
- Queue provider delivery instead of sending from unrelated product code.
- Keep retry state and failure reason visible in the outbox.
- Use event keys from the registry so templates and preferences stay consistent.
- Handle Resend webhook updates without trusting raw payloads as application state.