Files
aicyclingcoach-go/designdoc.md
2025-09-12 07:32:32 -07:00

7.2 KiB

# AI-Assisted Cycling Coach — Design Document ## 1. Architecture Overview Goal: Web-based cycling coach that plans workouts, analyzes Garmin rides, and integrates AI while enforcing strict user-defined rules. ### Components | Component | Tech | Purpose | | ---------------- | -------------------------- | ------------------------------------------------------------------ | | Frontend | React/Next.js | UI for routes, plans, analysis, file uploads | | Backend | Python (FastAPI, async) | API layer, AI integration, Garmin sync, DB access | | Database | PostgreSQL | Stores routes, sections, plans, rules, workouts, prompts, analyses | | File Storage | Mounted folder /data/gpx | Store GPX files for sections/routes | | AI Integration | OpenRouter via backend | Plan generation, workout analysis, suggestions | | Containerization | Docker + docker-compose | Encapsulate frontend, backend, database with persistent storage | Workflow Overview 1. Upload/import GPX → backend saves to mounted folder + metadata in DB 2. Define plaintext rules → Store directly in DB 3. Generate plan → AI creates JSON plan → DB versioned 4. Ride recorded on Garmin → backend syncs activity metrics → stores in DB 5. AI analyzes workout → feedback & suggestions stored → user approves → new plan version created

2. Backend Design (Python, Async)

Framework: FastAPI (async-first, non-blocking I/O) Tasks:

  • Route/Section Management: Upload GPX, store metadata, read GPX files for visualization
  • Rule Management: CRUD rules with plaintext storage
  • Plan Management: Generate plans (AI), store versions
  • Workout Analysis: Fetch Garmin activity, run AI analysis, store reports
  • AI Integration: Async calls to OpenRouter
  • Database Interaction: Async Postgres client (e.g., asyncpg or SQLAlchemy Async)

Endpoints (examples)

Method Endpoint Description
POST /routes/upload Upload GPX file for route/section
GET /routes List routes and sections
POST /rules Create new rule set (plaintext)
POST /plans/generate Generate new plan using rules & goals
GET /plans/{plan_id} Fetch plan JSON & version info
POST /workouts/analyze Trigger AI analysis for a synced Garmin activity
POST /workouts/approve Approve AI suggestions → create new plan version

Async Patterns:

  • File I/O → async reading/writing GPX
  • AI API calls → async HTTP requests
  • Garmin sync → async polling/scheduled jobs

3. Database Design (Postgres)

Tables:

-- Routes & Sections
CREATE TABLE routes (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT now()
);

CREATE TABLE sections (
    id SERIAL PRIMARY KEY,
    route_id INT REFERENCES routes(id),
    gpx_file_path TEXT NOT NULL,
    distance_m NUMERIC,
    grade_avg NUMERIC,
    min_gear TEXT,
    est_time_minutes NUMERIC,
    created_at TIMESTAMP DEFAULT now()
);

-- Rules (plaintext storage)
CREATE TABLE rules (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    description TEXT,
    user_defined BOOLEAN DEFAULT true,
    rule_text TEXT NOT NULL, -- Plaintext rules
    version INT DEFAULT 1,
    parent_rule_id INT REFERENCES rules(id),
    created_at TIMESTAMP DEFAULT now(),
    updated_at TIMESTAMP DEFAULT now()
);

-- Plans (versioned)
CREATE TABLE plans (
    id SERIAL PRIMARY KEY,
    jsonb_plan JSONB NOT NULL,
    version INT NOT NULL,
    created_at TIMESTAMP DEFAULT now()
);

-- Workouts
CREATE TABLE workouts (
    id SERIAL PRIMARY KEY,
    plan_id INT REFERENCES plans(id),
    garmin_activity_id TEXT NOT NULL,
    metrics JSONB,
    created_at TIMESTAMP DEFAULT now()
);

-- Analyses
CREATE TABLE analyses (
    id SERIAL PRIMARY KEY,
    workout_id INT REFERENCES workouts(id),
    jsonb_feedback JSONB,
    created_at TIMESTAMP DEFAULT now()
);

-- AI Prompts
CREATE TABLE prompts (
    id SERIAL PRIMARY KEY,
    action_type TEXT, -- plan, analysis, suggestion
    model TEXT,
    prompt_text TEXT,
    version INT DEFAULT 1,
    created_at TIMESTAMP DEFAULT now()
);

4. Containerization (Docker Compose)

version: '3.9'
services:
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    volumes:
      - gpx-data:/app/data/gpx
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/cycling
    depends_on:
      - db

  frontend:
    build: ./frontend
    ports:
      - "3000:3000"

  db:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_DB: cycling
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  gpx-data:
    driver: local
  postgres-data:
    driver: local

Notes:

  • /app/data/gpx inside backend container is persisted on host via gpx-data volume.
  • Postgres data persisted via postgres-data.
  • Backend talks to DB via async client.

5. Frontend UI Layouts & Flows

5.1 Layout

  • Navbar: Routes | Rules | Plans | Workouts | Analysis | Export/Import
  • Sidebar: Filters (date, type, difficulty)
  • Main Area: Dynamic content depending on selection

5.2 Key Screens

  1. Routes

    • Upload/import GPX
    • View route map + section metadata
  2. Rules

    • Plaintext rule editor
    • Simple create/edit form
    • Rule version history
  3. Plan

    • Select goal + rule set → generate plan
    • View plan timeline & weekly workouts
  4. Workout Analysis

    • List synced Garmin activities
    • Select activity → AI generates report
    • Visualizations: HR, cadence, power vs planned
    • Approve suggestions → new plan version
  5. Export/Import

    • Export JSON/ZIP of routes, rules, plans
    • Import JSON/GPX

5.3 User Flow Example

  1. Upload GPX → backend saves file + DB metadata
  2. Define rule set → Store plaintext → DB versioned
  3. Generate plan → AI → store plan version in DB
  4. Sync Garmin activity → backend fetches metrics → store workout
  5. AI analyzes → report displayed → user approves → new plan version
  6. Export plan or route as needed

6. AI Integration

  • Each action type (plan generation, analysis, suggestion) has:

    • Stored prompt template in DB
    • Configurable model per action
  • Async calls to OpenRouter

  • Store raw AI output + processed structured result in DB

  • Use plaintext rules directly in prompts without parsing


Next Steps

  1. Implement Python FastAPI backend with async patterns.
  2. Build Postgres DB schema and migration scripts.
  3. Setup Docker Compose with mounted GPX folder.
  4. Design frontend UI based on the flows above.
  5. Integrate AI endpoints and Garmin sync.