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

Contributors

The avatar of contributor named as XiSenao XiSenao
The avatar of contributor named as Claude Opus 4.6 (1M context) Claude Opus 4.6 (1M context)

Changelog

Discuss

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