Files
phaseflow/specs/notifications.md
2026-01-10 17:13:18 +00:00

2.7 KiB

Notifications Specification

Job to Be Done

When I wake up each morning, I want to receive an email with my training decision, so that I don't need to open the app to know if I should train.

Email Notifications

Daily Training Email

Sent at user's preferred notificationTime (default: 07:00).

Subject:

PhaseFlow: [STATUS] - Day [cycleDay] ([phase])

Example: PhaseFlow: ✅ TRAIN - Day 12 (FOLLICULAR)

Body:

Good morning!

Today's Decision: [STATUS]
Reason: [reason]

Current Metrics:
- Cycle Day: [cycleDay] ([phase])
- Body Battery: [bbCurrent]
- HRV: [hrvStatus]
- Week Intensity: [weekIntensity]/[phaseLimit] min

Nutrition Today:
- Seeds: [seeds]
- Carbs: [carbRange]
- Keto: [ketoGuidance]

[Optional: Seed switch alert if day 15]
[Optional: Token expiration warning]

---
PhaseFlow - Training with your cycle, not against it

Token Expiration Warnings

14 Days Before: Subject: ⚠️ PhaseFlow: Garmin tokens expire in 14 days

7 Days Before: Subject: 🚨 PhaseFlow: Garmin tokens expire in 7 days - action required

Email Provider

Using Resend via resend npm package.

Configuration:

  • RESEND_API_KEY - API key for Resend
  • EMAIL_FROM - Sender address (e.g., PhaseFlow <noreply@phaseflow.app>)

Email Utilities (src/lib/email.ts)

Functions:

  • sendDailyNotification(user, decision, dailyData) - Send morning email
  • sendTokenExpirationWarning(user, daysUntilExpiry) - Send warning email

Cron Jobs

/api/cron/notifications

Protected by CRON_SECRET header.

Trigger: Daily at notification times

Process:

  1. Find all users with notificationTime matching current hour
  2. For each user:
    • Fetch current decision from decision engine
    • Send email via Resend
    • Update DailyLog.notificationSentAt

Timezone Handling

Users store preferred timezone (e.g., America/New_York).

Cron runs every hour. Check if current hour in user's timezone matches their notificationTime.

Rate Limiting

  • Max 1 notification per user per day
  • Check DailyLog.notificationSentAt before sending
  • Only send if null or different date

Success Criteria

  1. Email arrives within 5 minutes of scheduled time
  2. Email contains all relevant metrics and guidance
  3. Token warnings sent at 14 and 7 day thresholds
  4. No duplicate notifications on same day

Acceptance Tests

  • Daily email contains decision status and reason
  • Daily email includes nutrition guidance
  • Seed switch alert included on day 15
  • Token warning email sent at 14-day threshold
  • Token warning email sent at 7-day threshold
  • Duplicate notifications prevented
  • Timezone conversion correct for notification time
  • CRON_SECRET required for endpoint access