ProjectR Docs
Backend (Convex)

Notifications

The enqueue pipeline, policy engine, and push delivery.

The pipeline overview and diagrams live in Notification Pipeline; this page is the backend-oriented reference.

Key functions

FunctionFileNotes
enqueueNotification (internal) / enqueueNotificationHelperconvex/notification/mutations.tsThe only entry point for producers
evaluatePolicyconvex/notification/policies.tsPure; runs inside the enqueueing transaction
sendPushNotification (internal action)convex/notification/actions.tsExpo send per active token, 3 retries, idempotent on terminal status
processPendingToWorkpoolconvex/notification/mutations.ts5-min cron; re-enqueues unclaimed rows past scheduledAt
markAsRead / markAllAsRead / deleteNotificationconvex/notification/mutations.tsUnread counter decrements under countsTowardUnread

Producer obligations

  • Render the final title/body yourself — templates exist but are not auto-rendered by the pipeline.
  • Pass a producerModule (webhook, gamificationLoyalty, dashboard, …) — it lands on the row for auditing.
  • Bulk sends cap at 100 users per mutation; larger audiences go through sendBroadcastNotification.

Data model

notifications (with policyResult, producerModule, traceId, channelStatus, enqueuedAt), notificationPreferences (channel toggles, disabled types, quiet hours, timezone), pushTokens (mirrored into the Expo push component), notificationTemplates. Aggregate: unread:<userId> sharded counter.

Mobile exposure

toMobileFormat() in convex/notification/queries.ts is the field firewall — mobile sees only what it explicitly maps. New backend fields are invisible to the app until added there.

On this page