{"id":50888150,"url":"https://github.com/jrhahn/ai-trainer","last_synced_at":"2026-06-15T19:01:45.999Z","repository":{"id":362565363,"uuid":"1207107256","full_name":"jrhahn/ai-trainer","owner":"jrhahn","description":"AI-powered cycling coach with Strava integration, RAG-based training knowledge, and support for OpenAI \u0026 Gemini — built with FastAPI + React.","archived":false,"fork":false,"pushed_at":"2026-06-14T20:50:26.000Z","size":2797,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-06-14T21:05:41.634Z","etag":null,"topics":["ai","coaching","cycling","fastapi","gemini","llm","openai","python","rag","sports","sports-analytics"],"latest_commit_sha":null,"homepage":"http://trainlikea.pro","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jrhahn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-10T15:26:34.000Z","updated_at":"2026-06-11T17:13:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"321ca923-fb53-442e-930d-2cc0817a4e0c","html_url":"https://github.com/jrhahn/ai-trainer","commit_stats":null,"previous_names":["jrhahn/ai-trainer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jrhahn/ai-trainer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhahn%2Fai-trainer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhahn%2Fai-trainer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhahn%2Fai-trainer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhahn%2Fai-trainer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrhahn","download_url":"https://codeload.github.com/jrhahn/ai-trainer/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrhahn%2Fai-trainer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34376125,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","coaching","cycling","fastapi","gemini","llm","openai","python","rag","sports","sports-analytics"],"created_at":"2026-06-15T19:01:44.896Z","updated_at":"2026-06-15T19:01:45.994Z","avatar_url":"https://github.com/jrhahn.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AI Trainer — Smart Cycling Coach\n\n[![Frontend Coverage](https://codecov.io/gh/jrhahn/ai-trainer/graph/badge.svg)](https://codecov.io/gh/jrhahn/ai-trainer)\n[![Backend Coverage](https://codecov.io/gh/jrhahn/ai-trainer/graph/badge.svg?flag=backend)](https://codecov.io/gh/jrhahn/ai-trainer)\n\nA smart cycling training app powered by AI (OpenAI or Google Gemini) with Strava integration.\n\n## Repository structure\n\n```\nai-trainer/\n├── frontend/   # Vite + React + TypeScript SPA\n└── backend/    # Python FastAPI server (Strava OAuth)\n```\n\n## Quick start\n\n### Docker Compose\n\n```bash\ncp .env.example .env\n# fill in the secrets you want to use\ndocker compose up -d\n```\n\nThis starts:\n\n- frontend on \u003chttp://localhost:5173\u003e\n- backend on \u003chttp://localhost:8000\u003e\n- traefik reverse proxy on \u003chttp://localhost\u003e and \u003chttps://localhost\u003e\n- postgres inside the compose network with a persistent named volume (`postgres_data`)\n- authelia for SSO/session-based user management (state persisted in `authelia/`)\n\nThe backend can boot with placeholder AI and Strava credentials, but those\nfeatures will only work after you set real values in `.env`.\nBefore first deploy, replace the placeholder Authelia user in\n`authelia/users_database.yml` with your real admin account.\nAuthelia is the file-backed user store for production registration and login,\nwhile the app uses its own JWT for API authorization after sign-in. Local Compose keeps\nAuthelia notifications in `/data/notification.txt` for password reset and future\nidentity-verification flows.\n\n### Backend (Strava OAuth)\n\n```bash\ncd backend\ncp .env.example .env   # fill in STRAVA_CLIENT_ID + STRAVA_CLIENT_SECRET\nuv sync\nuv run uvicorn main:app --reload --port 8000\n```\n\nSee [`backend/README.md`](backend/README.md) for full setup instructions.\n\n### Frontend\n\n```bash\ncd frontend\ncp .env.example .env.local   # set VITE_BACKEND_URL=http://localhost:8000\nnpm install\nnpm run dev\n```\n\nThe app will be available at \u003chttp://localhost:5173\u003e.\n\n## How it works\n\n```\nStrava API ──► FastAPI backend ──► AI coaching response\n                    │\n                    ▼\n           pgvector (PostgreSQL)\n           cycling science knowledge base\n           (RAG via text-embedding-3-small)\n```\n\nThe coaching assistant combines two sources of context before calling the LLM:\n\n1. **Retrieval-Augmented Generation (RAG)** — a cycling science knowledge base\n   (`backend/knowledge/`) is chunked, embedded with `text-embedding-3-small`, and\n   stored in PostgreSQL via `pgvector`. At query time the most relevant chunks are\n   retrieved by cosine similarity and injected into the prompt.\n\n2. **Athlete context** — real activity data pulled from the Strava API (power,\n   heart rate, elevation, cadence streams) is analysed and summarised alongside\n   the user's training plan and feedback history.\n\nThe LLM (OpenAI GPT-4o or Google Gemini, switchable via `AI_PROVIDER` env var)\nreceives both sources and returns structured coaching advice. The prompt\nengineering layer lives in `backend/services/prompts.py`.\n\nSee [`docs/update_rag.md`](docs/update_rag.md) for how to refresh the knowledge base.\n\n## Features\n\n- **AI-powered training plans** — generate and adapt cycling plans via OpenAI or Google Gemini\n- **Strava integration** — connect your Strava account to pull in real activity data\n- **RAG knowledge base** — responses grounded in cycling science literature via pgvector\n- **Local-first** — all user data (profile, plan, feedback) persisted in browser `localStorage` via Zustand\n\n## Building for production\n\n```bash\ncd frontend\nnpm run build   # outputs to frontend/dist/\n```\n\n## Deployment (Hetzner)\n\nThis repository includes Ansible-based deployment for a Debian Hetzner VPS:\n\n- Playbook: `deploy/ansible/deploy.yml`\n- Workflow: `.github/workflows/deploy.yml`\n\nThe deployment workflow is tied to the `production` environment. If that\nenvironment is configured with required reviewers, deployment waits for manual\nmaintainer approval. If required reviewers are not available (for example on\nfree plans), deployment runs automatically after pushes to `develop`.\n\nTraefik is configured as the public reverse proxy with Let's Encrypt TLS:\n\n- `trainlikea.pro` and `train-like-a.pro` (and any subdomain) route to the frontend\n- backend API routes (`/api`, `/healthz`) are proxied through the same domains\n- `auth.trainlikea.pro` and `auth.train-like-a.pro` route to Authelia\n\nDNS records must point to the server:\n\n- `A/AAAA trainlikea.pro`\n- `A/AAAA *.trainlikea.pro`\n- `A/AAAA train-like-a.pro`\n- `A/AAAA *.train-like-a.pro`\n\nSet `ACME_EMAIL` in `.env` (or deployment vars) to receive certificate notices.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrhahn%2Fai-trainer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrhahn%2Fai-trainer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrhahn%2Fai-trainer/lists"}