Back to Developer Logs

Build Log — January 26, 2026

Build Log — January 26, 2026

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 converter
  • app/api/intervals/ — OAuth, export, status endpoints
  • components/IntervalsConnection.tsx — Connection UI component
  • DB migration for intervals_integrations table

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.ts to next.config.js headers (Next.js 16 change)

Environment & Configuration

  • Updated .env.example with 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 .fit test files to tests/fixtures/fit/
  • Moved screenshots to docs/
  • Moved analysis files to docs/analysis/
  • Removed duplicate env.example

Referral Landing Pages

  • Created /x route for Twitter referrals
  • Created /strava route for Strava referrals
  • Both render main landing page while tracking referral source via analytics

Health Metrics Enhancements

Body Battery Improvements

  • Added charged and drained fields 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 onSendToZwift prop in DayWorkoutModalProps
  • Fixed missing allMetrics prop in DailyMetricsModalProps
  • Fixed undefined userId in handleSendToZwift function
  • Fixed HRV property name in MonthGrid memo (heartRateVariabilityhrv)
  • 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

  1. Intervals.icu testing — Verify workout sync to Zwift works correctly
  2. Production deployment — Deploy with new security headers
  3. 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 to next.config.js headers
  • 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.