- 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
3.0 KiB
3.0 KiB
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
# 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
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
docker build -t fitness-web:latest .
2. NixOS module
Add machines/cj/fitness-web.nix to your nix_config:
{ 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:
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:
"fitness.jhink.org" = simpleProxy 8688;
4. Firewall
Add to allowedTCPPorts in firewall.nix:
8688 # fitness-web
5. Deploy
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 — Original training repo with markdown logs and Juggernaut history. This web app replaces it.