Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesNotificationsNotifications (Email + Scheduled)

Notifications (Email + Scheduled)

Status: Shipped — Resend-backed transactional email + nestjs/schedule cron jobs. Last reviewed: 2026-05-28

What

Scheduled outbound email notifications via Resend:

  • Class reminders — daily 08:00 UTC cron picks tomorrow’s sessions and emails confirmed bookings.
  • Subscription expiration warnings — daily 09:00 UTC cron warns members whose subscription expires in 6–7 days.
  • Payment reminders — payment-related transactional emails.
  • Cancellation notifications — booking / class cancellation emails (separate service).

Distinct from:

Why

Email is the lowest-common-denominator nudge channel for not-yet-installed mobile members and a parallel backup to push for installed members. Class reminders are required for booking retention.

Personas

PersonaSurfaceCapabilities
System (cron)n/aAuto-sends reminders
MemberInboxReceives the email

No user-facing notification center exists today — notifications are write-once email events, not stored in a table for in-app retrieval.

Capabilities

  • Resend client — global RESEND_CLIENT token; from = RESEND_FROM_ADDRESS env or 'FitKit <noreply@fitkit.fit>'.
  • Send wrapperEmailService.send({to, subject, html}) swallows Resend errors and logs them.
  • Test sink — in NODE_ENV=test, EmailService retains sent emails in-memory for spec assertions.
  • Cron jobsNotificationSchedulerService registers @Cron('0 8 * * *') (class reminders), @Cron('0 9 * * *') (expiration warnings), more in cancellation-notifications.service.
  • HTML templatesapps/api/src/notifications/templates/ hand-written HTML helpers per email kind.
  • Retry wrapperrunWithRetry in common/cron-retry.ts for transient failures.
  • Cron gatecronsEnabled() toggle env-driven; off in dev by default.

Capabilities (gaps)

  • No in-app notification feed / notification center.
  • No per-user email opt-out for transactional categories (only push prefs exist).
  • No SMS / WhatsApp channel.
  • No batching / digest support.
  • No localization in the email templates (HTML is currently English-first; verify per template).

Source code

  • API: apps/api/src/notifications/
    • email.service.ts — Resend wrapper
    • notification-scheduler.service.ts — cron jobs
    • cancellation-notifications.service.ts — booking cancellation emails
    • templates/class-reminder, expiration-warning, payment-reminder, cancellation
  • DB: no notifications table; persistence lives in the source domain (bookings, subscriptions)