- Merge opencode-serve into the web container via entrypoint script - Add /api/agent/* JSON endpoints for workouts, sets, checkins - Rewrite fitness-trainer.md to use API instead of markdown files - Pass recent workouts and check-ins as chat context to the coach - Show current training phase on dashboard - Clarify check-ins as morning check-ins (calories/steps = yesterday) - Add NixOS deployment section to README - Make all check-in fields explicitly optional in UI
126 lines
3.0 KiB
Markdown
126 lines
3.0 KiB
Markdown
# Fitness Web
|
|
|
|
Multi-user fitness tracking web app with AI coaching.
|
|
|
|
Track workouts, log daily check-ins, explore exercise history, and chat with an AI coach powered by opencode.
|
|
|
|
## Features
|
|
|
|
- **Workouts** — Plan and log workouts with set-level detail (reps, weight, RPE)
|
|
- **Exercises** — Catalog with body-part filtering and history
|
|
- **Check-ins** — Daily weight, calories, steps, sleep tracking
|
|
- **AI Coach** — Chat interface backed by opencode (Big Pickle model, free)
|
|
- **Multi-user** — Login-based, each user has independent data
|
|
- **Calendar view** — See your training history at a glance
|
|
- **NixOS-ready** — Docker-based deploy with provided NixOS module
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# Install dependencies
|
|
uv sync
|
|
|
|
# Initialize and seed the database
|
|
uv run python scripts/schema.py
|
|
uv run python scripts/seed.py
|
|
|
|
# Start the dev server
|
|
uv run uvicorn app.main:app --reload
|
|
```
|
|
|
|
Open http://localhost:8000, register a user, and you're ready.
|
|
|
|
## Docker
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
## NixOS Deployment
|
|
|
|
A single container runs both the web app and the AI coach (opencode-serve) together, sharing the SQLite database on the same filesystem.
|
|
|
|
### 1. Build image
|
|
|
|
```bash
|
|
docker build -t fitness-web:latest .
|
|
```
|
|
|
|
### 2. NixOS module
|
|
|
|
Add `machines/cj/fitness-web.nix` to your nix_config:
|
|
|
|
```nix
|
|
{ serverIP, serverIP6 }: {
|
|
fitness-web = {
|
|
image = "fitness-web:latest";
|
|
ports = [ "8688:8000" ];
|
|
environment = {
|
|
TZ = "America/New_York";
|
|
SESSION_SECRET = "change-me-in-production";
|
|
};
|
|
volumes = [
|
|
"/serverdata/fitness-web/data:/app/data"
|
|
"/serverdata/fitness-web/opencode:/root/.config/opencode"
|
|
];
|
|
};
|
|
}
|
|
```
|
|
|
|
Wire it into `configuration.nix`:
|
|
|
|
```nix
|
|
virtualisation.oci-containers.containers = let
|
|
ips = { ... };
|
|
in {
|
|
# ... existing containers ...
|
|
fitness-web = (import ./fitness-web.nix ips).fitness-web;
|
|
};
|
|
```
|
|
|
|
### 3. Nginx reverse proxy
|
|
|
|
In `nginx.nix`, add a vhost:
|
|
|
|
```nix
|
|
"fitness.jhink.org" = simpleProxy 8688;
|
|
```
|
|
|
|
### 4. Firewall
|
|
|
|
Add to `allowedTCPPorts` in `firewall.nix`:
|
|
|
|
```nix
|
|
8688 # fitness-web
|
|
```
|
|
|
|
### 5. Deploy
|
|
|
|
```bash
|
|
nixos-rebuild switch --flake .#cj
|
|
```
|
|
|
|
Then access at https://fitness.jhink.org (or your chosen domain).
|
|
|
|
## Architecture
|
|
|
|
```
|
|
app/
|
|
├── main.py — FastAPI app factory with lifespan
|
|
├── config.py — Settings from environment
|
|
├── auth.py — Auth helpers (hash, verify, session)
|
|
├── models/ — SQLAlchemy ORM models
|
|
├── routers/ — Route handlers per feature
|
|
├── services/ — External service integrations (opencode)
|
|
├── templates/ — Jinja2 templates (Pico.css)
|
|
└── static/ — CSS overrides
|
|
scripts/
|
|
├── schema.py — DB table creation
|
|
└── seed.py — Seed exercises and phases
|
|
data/ — SQLite database (gitignored)
|
|
```
|
|
|
|
## Related
|
|
|
|
- [fitness-agent](https://github.com/yourname/fitness-agent) — Original training repo with markdown logs and Juggernaut history. This web app replaces it.
|