An open API service indexing awesome lists of open source software.

https://github.com/jrhahn/ai-trainer

AI-powered cycling coach with Strava integration, RAG-based training knowledge, and support for OpenAI & Gemini — built with FastAPI + React.
https://github.com/jrhahn/ai-trainer

ai coaching cycling fastapi gemini llm openai python rag sports sports-analytics

Last synced: 1 day ago
JSON representation

AI-powered cycling coach with Strava integration, RAG-based training knowledge, and support for OpenAI & Gemini — built with FastAPI + React.

Awesome Lists containing this project

README

          

# AI Trainer — Smart Cycling Coach

[![Frontend Coverage](https://codecov.io/gh/jrhahn/ai-trainer/graph/badge.svg)](https://codecov.io/gh/jrhahn/ai-trainer)
[![Backend Coverage](https://codecov.io/gh/jrhahn/ai-trainer/graph/badge.svg?flag=backend)](https://codecov.io/gh/jrhahn/ai-trainer)

A smart cycling training app powered by AI (OpenAI or Google Gemini) with Strava integration.

## Repository structure

```
ai-trainer/
├── frontend/ # Vite + React + TypeScript SPA
└── backend/ # Python FastAPI server (Strava OAuth)
```

## Quick start

### Docker Compose

```bash
cp .env.example .env
# fill in the secrets you want to use
docker compose up -d
```

This starts:

- frontend on
- backend on
- traefik reverse proxy on and
- postgres inside the compose network with a persistent named volume (`postgres_data`)
- authelia for SSO/session-based user management (state persisted in `authelia/`)

The backend can boot with placeholder AI and Strava credentials, but those
features will only work after you set real values in `.env`.
Before first deploy, replace the placeholder Authelia user in
`authelia/users_database.yml` with your real admin account.
Authelia is the file-backed user store for production registration and login,
while the app uses its own JWT for API authorization after sign-in. Local Compose keeps
Authelia notifications in `/data/notification.txt` for password reset and future
identity-verification flows.

### Backend (Strava OAuth)

```bash
cd backend
cp .env.example .env # fill in STRAVA_CLIENT_ID + STRAVA_CLIENT_SECRET
uv sync
uv run uvicorn main:app --reload --port 8000
```

See [`backend/README.md`](backend/README.md) for full setup instructions.

### Frontend

```bash
cd frontend
cp .env.example .env.local # set VITE_BACKEND_URL=http://localhost:8000
npm install
npm run dev
```

The app will be available at .

## How it works

```
Strava API ──► FastAPI backend ──► AI coaching response


pgvector (PostgreSQL)
cycling science knowledge base
(RAG via text-embedding-3-small)
```

The coaching assistant combines two sources of context before calling the LLM:

1. **Retrieval-Augmented Generation (RAG)** — a cycling science knowledge base
(`backend/knowledge/`) is chunked, embedded with `text-embedding-3-small`, and
stored in PostgreSQL via `pgvector`. At query time the most relevant chunks are
retrieved by cosine similarity and injected into the prompt.

2. **Athlete context** — real activity data pulled from the Strava API (power,
heart rate, elevation, cadence streams) is analysed and summarised alongside
the user's training plan and feedback history.

The LLM (OpenAI GPT-4o or Google Gemini, switchable via `AI_PROVIDER` env var)
receives both sources and returns structured coaching advice. The prompt
engineering layer lives in `backend/services/prompts.py`.

See [`docs/update_rag.md`](docs/update_rag.md) for how to refresh the knowledge base.

## Features

- **AI-powered training plans** — generate and adapt cycling plans via OpenAI or Google Gemini
- **Strava integration** — connect your Strava account to pull in real activity data
- **RAG knowledge base** — responses grounded in cycling science literature via pgvector
- **Local-first** — all user data (profile, plan, feedback) persisted in browser `localStorage` via Zustand

## Building for production

```bash
cd frontend
npm run build # outputs to frontend/dist/
```

## Deployment (Hetzner)

This repository includes Ansible-based deployment for a Debian Hetzner VPS:

- Playbook: `deploy/ansible/deploy.yml`
- Workflow: `.github/workflows/deploy.yml`

The deployment workflow is tied to the `production` environment. If that
environment is configured with required reviewers, deployment waits for manual
maintainer approval. If required reviewers are not available (for example on
free plans), deployment runs automatically after pushes to `develop`.

Traefik is configured as the public reverse proxy with Let's Encrypt TLS:

- `trainlikea.pro` and `train-like-a.pro` (and any subdomain) route to the frontend
- backend API routes (`/api`, `/healthz`) are proxied through the same domains
- `auth.trainlikea.pro` and `auth.train-like-a.pro` route to Authelia

DNS records must point to the server:

- `A/AAAA trainlikea.pro`
- `A/AAAA *.trainlikea.pro`
- `A/AAAA train-like-a.pro`
- `A/AAAA *.train-like-a.pro`

Set `ACME_EMAIL` in `.env` (or deployment vars) to receive certificate notices.