Skip to content

Weekly Training Review AI Assistant

Overview

Build-time script that generates weekly training analysis by calling Claude API, producing per-week JSON files consumed by a new Dashboard modal component. Integrates with existing strava:sync workflow.

Decisions

DecisionChoiceRationale
TriggerBuild-time script (pnpm weekly-review)Consistent with strava:sync workflow, git-trackable output
StoragePer-week JSON files (W01.json, W02.json)Independent, easy to regenerate individual weeks
Analysis4 dimensions: completion, quality, fatigue, adviceComprehensive yet focused on actionable insights
UINew card in ProgressTracker + modalFollows existing Dashboard pattern
LanguageBilingual (zh + en) per fileMatches project's i18n structure

Data Structure

WeeklyReview Interface

typescript
export interface WeeklyReview {
  weekNumber: number;
  weekRange: string; // "2026-01-19 - 2026-01-25"
  language: 'zh' | 'en';
  generatedAt: string; // ISO timestamp

  planCompletion: {
    weeklyDistanceTarget: number;
    weeklyDistanceActual: number;
    completionRate: number; // 0-1
    missedSessions: string[];
    summary: string; // AI-generated
  };

  qualityAssessment: {
    avgPace: string;
    paceConsistency: 'excellent' | 'good' | 'variable' | 'poor';
    heartRateCompliance: number; // 0-1
    effortDistribution: {
      easy: number;
      moderate: number;
      hard: number;
      allOut: number;
    };
    summary: string;
  };

  fatigueRisk: {
    level: 'low' | 'moderate' | 'high';
    indicators: string[];
    recommendation: string;
  };

  nextWeekAdvice: {
    focus: string;
    adjustments: string[];
    tips: string;
  };
}

JSON File Format (data/weekly-reviews/W01.json)

json
{
  "zh": { "weekNumber": 1, "language": "zh", ... },
  "en": { "weekNumber": 1, "language": "en", ... }
}

Architecture

Script Structure

scripts/weekly-review/
├── generate.ts        # Main: aggregate data + call Claude API
├── client.ts          # Claude API client wrapper
├── config.ts          # API key / model config (from env)
└── prompt.ts          # Prompt templates (zh + en)

Workflow

  1. Data Aggregation (generate.ts)

    • Read workouts.json + training-config.ts
    • Calculate current training week (based on trainingStartDate)
    • Filter workouts for target week (Monday-Sunday)
    • Extract plan data (weeklyPlan + lsdDistanceByWeek)
    • Compute metrics: distance, pace, HR zones, effort distribution
  2. Prompt Construction (prompt.ts)

    • Role: Professional running coach analyzing marathon training
    • Input: Structured JSON (plan vs actual)
    • Requirements: 4-dimension analysis with specific metrics
    • Output: Strict JSON schema (WeeklyReview interface)
    • Tone: Professional yet friendly, moderate emoji use (match training-config tips style)
  3. API Call (client.ts)

    • Model: claude-3-5-sonnet-20241022
    • Temperature: 0.3 (consistent analysis)
    • Max tokens: 4096
    • Parse response JSON, validate structure
  4. Output

    • Write to data/weekly-reviews/W{weekNumber}.json
    • Bilingual: both zh and en in single file

CLI Commands

bash
pnpm weekly-review              # Generate current week
pnpm weekly-review --week 3     # Generate week 3
pnpm weekly-review --all        # Regenerate all completed weeks
pnpm weekly-review --lang zh    # Chinese only (default: both)

Integration with Strava Sync

Modify scripts/strava/sync.ts:

  • After successful sync, check if current week is complete (has Sunday data)
  • If complete, auto-run weekly-review for current week
  • Log: "✓ Week 8 review generated"

Prompt Design

Key Elements

  1. Role Definition

    You are a professional running coach analyzing marathon training data.
    Provide specific, actionable insights based on the data provided.
  2. Input Format

    • Plan: sessions array with type, distance, targetHR
    • Actual: workouts array with pace, HR zones, effort
    • Context: week number, training phase (base/peak/taper)
  3. Analysis Requirements

    • Plan Completion: Compare target vs actual distance, identify missed sessions
    • Quality Assessment: Pace consistency (CV%), HR compliance (% in target zones), effort balance
    • Fatigue Risk: Detect patterns (consecutive high-intensity, insufficient rest)
    • Next Week Advice: Specific adjustments based on current performance
  4. Output Schema

    • Provide complete TypeScript interface as JSON schema
    • Include example output (few-shot)
    • Require strict JSON response (no markdown)
  5. Terminology (Chinese)

    • LSD (Long Slow Distance) → 长距离慢跑
    • Interval → 间歇跑
    • Tempo → 节奏跑
    • Recovery → 恢复跑
    • Heart Rate Zone → 心率区间

Example Prompt Structure

typescript
export function buildWeeklyReviewPrompt(
  data: WeeklyData,
  lang: 'zh' | 'en',
): string {
  return `
You are a professional marathon coach. Analyze this week's training data.

## Week ${data.weekNumber} (${data.weekRange})
Training Phase: ${data.phase}

## Planned Training
${JSON.stringify(data.plan, null, 2)}

## Actual Workouts
${JSON.stringify(data.actual, null, 2)}

## Analysis Requirements
1. Plan Completion: Calculate completion rate, list missed sessions
2. Quality Assessment: Evaluate pace consistency, HR compliance, effort distribution
3. Fatigue Risk: Identify warning signs (consecutive high-intensity, skipped rest)
4. Next Week Advice: Provide 2-3 specific adjustments

## Output Format
Return ONLY valid JSON matching this schema:
${JSON.stringify(WeeklyReviewSchema, null, 2)}

Language: ${lang === 'zh' ? 'Chinese' : 'English'}
Tone: Professional, friendly, use moderate emojis (🏃 💪 ⚠️ ✅)
`;
}

UI Components

New Components

  • composites/WeeklyReviewModal.tsx + .css
  • CSS prefix: wr-
  • z-index: 1000 (level-1 modal)
┌─────────────────────────────────────┐
│  📊 Week 8 Review        [← →] [×] │  ← Title + week nav + close
├─────────────────────────────────────┤
│  ■ Plan Completion                  │
│  ████████░░ 82%  (40.2 / 49km)      │  ← Progress bar + numbers
│  "Completed most sessions..."       │  ← AI summary
├─────────────────────────────────────┤
│  ■ Training Quality                 │
│  Pace Consistency: ★★★★☆            │
│  HR Compliance: 78%                 │
│  "Interval HR control was good..."  │
├─────────────────────────────────────┤
│  ■ Fatigue Risk  🟢 Low             │  ← Green/Yellow/Red
│  "Rest days well scheduled..."      │
├─────────────────────────────────────┤
│  ■ Next Week Advice                 │
│  • Increase LSD to 19km             │
│  • Maintain 6 interval sets         │
│  "Continue building aerobic base..."│
└─────────────────────────────────────┘

Component Props

typescript
interface WeeklyReviewModalProps {
  weekNumber: number; // Initial week to display
  onClose: () => void;
  allWorkoutRecords: WorkoutRecord[];
  trainingPlan: TrainingPlan;
}

Integration with ProgressTracker

Option A: Replace "Completed Sessions" card with "Weekly Review" card

  • Icon: 📊
  • Label: "Week 8 Review"
  • Value: Completion rate (e.g., "82%")
  • Click → open WeeklyReviewModal

Option B: Add 5th card below existing 4

  • Keep existing 4 cards unchanged
  • New row with single "Weekly Review" card

Recommendation: Option A (replace), keeps layout compact

Week Navigation

  • Modal header: ← Week 7 | Week 8 Review | Week 9 →
  • Arrows disabled if week data doesn't exist
  • Dynamically load W{n}.json on navigation
  • Show loading spinner during fetch

Data Loading

typescript
// In training-config.ts
export async function loadWeeklyReview(
  weekNumber: number,
  lang: 'zh' | 'en',
): Promise<WeeklyReview | null> {
  try {
    const data = await import(
      `../data/weekly-reviews/W${weekNumber.toString().padStart(2, '0')}.json`
    );
    return data[lang];
  } catch {
    return null;
  }
}

File Structure

scripts/weekly-review/
├── generate.ts
├── client.ts
├── config.ts
└── prompt.ts

daily/long-term-goals/
├── data/
│   └── weekly-reviews/
│       ├── W01.json
│       ├── W02.json
│       └── ...
└── components/
    ├── core/types.ts          # + WeeklyReview interface
    ├── composites/
    │   ├── WeeklyReviewModal.tsx  # New
    │   ├── WeeklyReviewModal.css  # New
    │   └── ProgressTracker.tsx    # Modified: add review card
    └── training-config.ts     # + loadWeeklyReview function

zh/daily/long-term-goals/
└── components/
    └── composites/
        ├── WeeklyReviewModal.tsx  # Chinese version
        └── WeeklyReviewModal.css  # Shared CSS

Implementation Phases

Phase 1: Script Foundation

  1. Create scripts/weekly-review/ structure
  2. Implement data aggregation logic
  3. Build prompt templates (zh + en)
  4. Set up Claude API client
  5. Test with Week 1 data

Phase 2: CLI Integration

  1. Add weekly-review npm script
  2. Implement CLI arguments (--week, --all, --lang)
  3. Integrate with strava:sync auto-trigger
  4. Generate reviews for all completed weeks

Phase 3: UI Components

  1. Define WeeklyReview TypeScript interface
  2. Build WeeklyReviewModal component
  3. Implement week navigation
  4. Add review card to ProgressTracker
  5. Style with Strava-inspired design

Phase 4: Bilingual Support

  1. Duplicate components to zh/ directory
  2. Test language switching
  3. Ensure prompt quality in both languages

Configuration

Environment Variables

bash
# .env.local
ANTHROPIC_API_KEY=sk-ant-...
WEEKLY_REVIEW_MODEL=claude-3-5-sonnet-20241022  # Optional, default
WEEKLY_REVIEW_TEMPERATURE=0.3                    # Optional, default

package.json Scripts

json
{
  "scripts": {
    "weekly-review": "tsx scripts/weekly-review/generate.ts",
    "weekly-review:all": "tsx scripts/weekly-review/generate.ts --all",
    "strava:sync": "tsx scripts/strava/sync.ts && pnpm weekly-review"
  }
}

Error Handling

  1. Missing API Key: Exit with clear error message
  2. API Failure: Retry once, then log error and continue
  3. Invalid JSON Response: Log raw response, skip week
  4. Missing Week Data: Return null, show "No review available" in UI
  5. File Write Error: Log error, don't crash script

Testing Strategy

  1. Unit Tests (optional, if time permits)

    • Prompt construction
    • Data aggregation logic
    • JSON validation
  2. Manual Testing

    • Generate Week 1 review, verify all 4 dimensions
    • Test with incomplete week (missing sessions)
    • Test with perfect week (all sessions completed)
    • Verify bilingual output quality
    • Test UI navigation between weeks
  3. Edge Cases

    • Week with zero workouts
    • Week with only rest days
    • Week with multiple workouts per day
    • Future weeks (should fail gracefully)

Success Criteria

  • [ ] Script generates valid JSON for completed weeks
  • [ ] Bilingual output (zh + en) in single file
  • [ ] 4 analysis dimensions present and meaningful
  • [ ] UI modal displays review with week navigation
  • [ ] Integration with strava:sync works automatically
  • [ ] No build errors, TypeScript types correct
  • [ ] Mobile responsive (modal adapts to small screens)

Future Enhancements

  1. Trend Analysis: Compare current week vs previous 4 weeks
  2. Goal Tracking: Progress toward sub-9:30 marathon goal
  3. Injury Risk: Detect sudden mileage spikes (>10% increase)
  4. Export: Download review as PDF or markdown
  5. Notifications: Alert if fatigue risk is high

Released under the CC BY-SA 4.0 License. (70b7115)