Files
phaseflow/specs/calendar.md
Petru Paler 6a8d55c0b9 Document spec gaps: auth, phase scaling, observability, testing
Address 21 previously undefined behaviors across specs:

- Authentication: Replace email/password with OIDC (Pocket-ID)
- Cycle tracking: Add fixed-luteal phase scaling formula with examples
- Calendar: Document period logging behavior (preserve predictions)
- Garmin: Clarify connection is required (no phase-only mode)
- Dashboard: Add UI states, dark mode, onboarding, accessibility
- Notifications: Document timezone batching approach
- New specs: observability.md (health, metrics, logging)
- New specs: testing.md (unit + integration strategy)
- Main spec: Add backup/recovery, known limitations, API updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 07:49:56 +00:00

3.7 KiB

Calendar Specification

Job to Be Done

When I want to plan ahead, I want to view my cycle phases on a calendar, so that I can schedule training and rest days appropriately.

ICS Feed

Endpoint: GET /api/calendar/[userId]/[token].ics

Returns ICS calendar feed for subscription in external apps.

URL Format:

https://phaseflow.app/api/calendar/user123/abc123token.ics

Security:

  • token is a random 32-character secret per user
  • Token stored in user.calendarToken
  • No authentication required (token IS authentication)

ICS Events

Generate events for the next 90 days:

Phase Events (all-day):

BEGIN:VEVENT
SUMMARY:🩸 Menstrual (Days 1-3)
DTSTART;VALUE=DATE:20240110
DTEND;VALUE=DATE:20240113
DESCRIPTION:Gentle rebounding only. Weekly limit: 30 min.
END:VEVENT

Color Coding (via categories):

  • MENSTRUAL: Red
  • FOLLICULAR: Green
  • OVULATION: Pink
  • EARLY_LUTEAL: Yellow
  • LATE_LUTEAL: Orange

Token Regeneration

POST /api/calendar/regenerate-token

Generates new calendarToken, invalidating previous subscriptions.

Response:

{
  "token": "newRandomToken123...",
  "url": "https://phaseflow.app/api/calendar/user123/newRandomToken123.ics"
}

Period Logging Behavior

When a user logs a new period start date, the ICS feed updates as follows:

  1. Current cycle: Phase events are corrected retroactively to reflect actual dates
  2. Original predictions preserved: Previous predictions for the current cycle are kept as separate events with "(Predicted)" suffix, allowing users to compare predicted vs. actual
  3. Older cycles: Events from previous cycles remain unchanged
  4. Future cycles: Regenerated based on new period date and cycle length

Example after logging period on Day 28 of a predicted 31-day cycle:

BEGIN:VEVENT
SUMMARY:🩸 Menstrual (Days 1-3)
DTSTART;VALUE=DATE:20240128
DESCRIPTION:Actual period start
END:VEVENT
BEGIN:VEVENT
SUMMARY:🩸 Menstrual (Predicted)
DTSTART;VALUE=DATE:20240131
DESCRIPTION:Original prediction - period arrived 3 days early
END:VEVENT

This creates a built-in accuracy feedback loop for understanding cycle patterns.

In-App Calendar

Month View (/calendar)

Full-page calendar showing current month with phase visualization.

Components:

  • month-view.tsx - Main calendar grid
  • day-cell.tsx - Individual day cell

Day Cell Contents:

  • Date number
  • Phase color background
  • Period indicator (if day 1-3)
  • Today highlight
  • Training decision icon (for today only)

Navigation

  • Previous/Next month buttons
  • "Today" button to jump to current date
  • Month/Year header

Phase Legend

Below calendar:

🩸 Menstrual | 🌱 Follicular | 🌸 Ovulation | 🌙 Early Luteal | 🌑 Late Luteal

ICS Utilities (src/lib/ics.ts)

Functions:

  • generateCalendarFeed(user, startDate, endDate) - Create ICS string
  • generatePhaseEvents(lastPeriodDate, cycleLength, range) - Create phase events

Dependencies:

  • ics npm package for ICS generation

Success Criteria

  1. ICS feed subscribable in Google Calendar, Apple Calendar, Outlook
  2. Phase colors render correctly in calendar apps
  3. In-app calendar responsive on mobile
  4. Token regeneration immediately invalidates old URLs

Acceptance Tests

  • ICS endpoint returns valid ICS format
  • ICS contains events for next 90 days
  • Invalid token returns 401
  • Regenerate token creates new unique token
  • Period log updates current cycle events retroactively
  • Period log preserves original predictions as "(Predicted)" events
  • Month view renders all days in month
  • Day cells show correct phase colors
  • Today is visually highlighted
  • Navigation between months works
  • Phase legend displays correctly