Context / Focus for Today
Big integration day — added Intervals.icu as a pathway to sync workouts to Zwift, plus major production hardening and project cleanup.
Things I Got Done Today
Intervals.icu Integration (Major Feature)
Zwift Workout Sync Pipeline
- Added Intervals.icu as a bridge to Zwift: Flow State → Intervals.icu → Zwift (auto-sync)
- OAuth flow ready (pending app registration with Intervals.icu)
- API key fallback for immediate use without waiting for OAuth approval
- Per-workout "Export to Zwift" button in workout builder
- Bulk export via SyncMenu with date range selection
- ZWO format converter for structured workouts
New Files
lib/intervals/— API client with dual auth support (OAuth + API key)lib/export/zwoWorkoutExporter.ts— ZWO format converterapp/api/intervals/— OAuth, export, status endpointscomponents/IntervalsConnection.tsx— Connection UI component- DB migration for
intervals_integrationstable
Production Readiness
Security Hardening
- Added Content-Security-Policy header to
next.config.js - Created security middleware for request validation
- Blocks path traversal and suspicious request patterns
- Sensitive API routes now have no-cache headers
- Migrated from deprecated
middleware.tstonext.config.jsheaders (Next.js 16 change)
Environment & Configuration
- Updated
.env.examplewith comprehensive documentation (30+ variables) - Fixed Stripe tests to match updated return type signatures
- Added production launch checklist to docs
UI/UX Refinements
Branding Consistency
- Added Strava orange logo to Sync, Disconnect, and Connect buttons
- Replaced Garmin wordmark images with consistent delta/arrow SVG icon
- Matches the synced activity cards in WorkoutCard
Activity Modal Improvements
- Moved device/gear info to top of ActivityStatsModal (was buried at bottom)
- Replaced custom export icon with Garmin Connect icon
- Same treatment for Strava sync metrics — device/gear now at top
Project Cleanup
Root Directory
- Removed junk files (
nul, temp files, corrupted PowerShell script) - Moved 7
.fittest files totests/fixtures/fit/ - Moved screenshots to
docs/ - Moved analysis files to
docs/analysis/ - Removed duplicate
env.example
Referral Landing Pages
- Created
/xroute for Twitter referrals - Created
/stravaroute for Strava referrals - Both render main landing page while tracking referral source via analytics
Health Metrics Enhancements
Body Battery Improvements
- Added
chargedanddrainedfields to bodyBattery type - Updated Garmin health data processing to capture charge/drain values
- Updated health API route and UI components for new fields
Garmin Reconnect
- Added "Repair Connection" option to settings page
- Allows users to re-authenticate Garmin without full disconnect
Build & Type Fixes
- Fixed missing
onSendToZwiftprop inDayWorkoutModalProps - Fixed missing
allMetricsprop inDailyMetricsModalProps - Fixed undefined
userIdinhandleSendToZwiftfunction - Fixed HRV property name in MonthGrid memo (
heartRateVariability→hrv) - Fixed stress property name in MonthGrid memo
- Fixed property names in DailyMetricsBadge memo
- Updated health metrics types across components
Commits Today
- 26 commits covering features, fixes, refactors, and docs
- Major: Intervals.icu integration (
8608bf5) - Feature: Garmin reconnect (
f7c4e6f) - Health: Body battery charged/drained (
cdcc01d,385e439,fcf4f12) - Security: Production hardening (
4645062,635fa74) - UI: Strava/Garmin branding (
5d0658a,8f134c0,251d19c)
In Progress
- Intervals.icu OAuth app registration (waiting on approval)
- Testing Zwift sync end-to-end with API key auth
Targets for Tomorrow
- Intervals.icu testing — Verify workout sync to Zwift works correctly
- Production deployment — Deploy with new security headers
- OAuth approval — Follow up on Intervals.icu app registration
Notes / Observations
- Intervals.icu provides a nice bridge to Zwift since Zwift doesn't have a public API
- The dual-auth approach (OAuth + API key fallback) means users can start immediately
- Next.js 16 deprecated
middleware.ts— had to migrate tonext.config.jsheaders - Good cleanup day — project root was getting cluttered with test files
Momentum Score: 8 / 10
Solid integration day. Intervals.icu opens up Zwift sync which users have been asking for. Security hardening puts us in good shape for production. The cleanup was overdue but the codebase feels tidier now.