106 lines
5.7 KiB
Markdown
106 lines
5.7 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
F1tness Parser is a FastAPI-based web application that parses fitness training data from two note formats:
|
|
- **Obsidian Notes**: Markdown tables with `# DD.MM.YYYY (trainer-session)` headers
|
|
- **Apple Notes**: Bold markdown tables with `**DD.MM.YYYY (trainer-session)**` headers
|
|
|
|
The project is split into two applications in one repository:
|
|
- `backend/` - FastAPI JSON API (parsers, models, services, PostgreSQL)
|
|
- `frontend/` - static site on plain HTML + CSS + JS (ES modules, no build step), served by nginx, which also proxies `/api/` to the backend
|
|
|
|
## Development Commands
|
|
|
|
The project is developed and run **only in Docker**: there is no local Python setup. Everything below runs inside the `fastapi-app` container (backend code lives in `backend/`, inside the container it is `/app`) (`.env` must have `POSTGRES_DATABASE_HOST=postgres`, see `.env.example`).
|
|
|
|
### Docker Development
|
|
```bash
|
|
# Start backend (:8000) + frontend (:8080) + PostgreSQL (applies migrations on start, hot reload for backend/app/)
|
|
# Open http://localhost:8080
|
|
docker compose up --build
|
|
|
|
# Apply migrations manually (Alembic; the app itself does NOT migrate on startup)
|
|
docker compose exec fastapi-app alembic upgrade head
|
|
|
|
# Create a migration after changing tables in app/core/database/tables.py
|
|
# (-u keeps the generated file owned by you instead of root)
|
|
docker compose exec -u "$(id -u):$(id -g)" fastapi-app alembic revision --autogenerate -m "describe change"
|
|
|
|
# Import all Obsidian + Apple notes into the database
|
|
docker compose exec fastapi-app python -m app.cli import [--replace]
|
|
|
|
# Stop (keeps the data) / stop and drop the database volume
|
|
docker compose down
|
|
docker compose down -v
|
|
```
|
|
Rebuild (`--build`) is needed only after changing `requirements*.txt`, `Dockerfile` or `pyproject.toml`.
|
|
|
|
The backend `Dockerfile` has two targets: `dev` (default in compose: pytest, mypy, tests, notes) and `prod` (runtime dependencies and app code only). Production images are built with `docker build --target prod backend`; the prod image has no `data/`, so the dev-only `GET /api/v1/trainings/obsidian/` doesn't work there.
|
|
|
|
### Testing
|
|
Tests that need a database use a separate `<POSTGRES_DATABASE_DB>_test` database (`TEST_DATABASE_URL`, created automatically). Without it they are skipped.
|
|
```bash
|
|
# Run all tests
|
|
docker compose exec fastapi-app pytest
|
|
|
|
# Run specific test file
|
|
docker compose exec fastapi-app pytest tests/test_core/test_obsidian_parser.py
|
|
|
|
# Without a running stack (starts postgres, runs once, removes the container)
|
|
docker compose run --rm fastapi-app pytest
|
|
```
|
|
|
|
### Type Checking
|
|
```bash
|
|
docker compose exec fastapi-app mypy app/
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
|
|
**Parser Architecture**: The system uses a base parser class (`backend/app/core/parsers/base.py`) with format-specific implementations:
|
|
- `ObsidianNotesParser` - handles Obsidian markdown format
|
|
- `AppleNotesParser` - handles Apple notes format
|
|
- Each parser includes exercise name mapping for normalization
|
|
|
|
**Data Models**: Located in `backend/app/core/dto/training.py`:
|
|
- `Training` - represents a workout session
|
|
- `Exercise` - individual exercise with multiple approaches
|
|
- `Approach` - single set with weight and reps
|
|
|
|
**API Structure** (backend, JSON only):
|
|
- `/api/v1/trainings/` (GET list, GET/PUT/DELETE `{id}/`; PUT replaces the whole training), `/api/v1/exercises/`, `/api/v1/exercises/progress/?name=`, `/api/v1/users/` (POST, GET list with `?role=`, GET/PATCH/DELETE `{id}/`; role is `trainer` or `trainee`, passwords are hashed with scrypt, no login yet), `/api/v1/parser/parse/`, `/api/v1/health/`
|
|
|
|
**Frontend** (`frontend/`):
|
|
- `index.html`, `exercises.html`, `parse.html`, `users.html` - pages; `js/common.js` (API + DOM helpers), `js/table.js` (DataTables 3 wrapper), one module per page, `js/modal.js` (Bootstrap modal shell), `js/edit-dialog.js` + `js/edit-form.js` (training edit modal), `js/user-dialog.js` (user create/edit modal)
|
|
- `vendor/` - Bootstrap (CSS + JS bundle), Chart.js and DataTables 3 (jQuery-free): the only third-party code
|
|
- `nginx.conf` - serves static files and proxies `/api/` to `fastapi-app:8000` (same origin, no CORS)
|
|
|
|
### Database
|
|
|
|
Trainings belong to a trainee (`trainings.trainee_id`, required) and optionally have a trainer (`trainings.trainer_id`, NULL = solo); both are users (role `trainee` / `trainer`). A user with trainings can't be deleted. `python -m app.cli import` takes the trainer from the note header and matches it with a trainer user by "First Last".
|
|
|
|
The backend uses PostgreSQL through async SQLAlchemy (asyncpg). tables are described with SQLAlchemy Core (no ORM) in `backend/app/core/database/tables.py`, `TrainingRepository` (`backend/app/core/database/repository.py`) is the data access layer, and a session is injected into endpoints with `Depends(get_session)`. Schema migrations are handled by Alembic (`alembic.ini`, `migrations/`); the URL is taken from `app/config.py`.
|
|
|
|
Configuration is managed through `backend/app/config.py` using Pydantic settings with `.env` file support.
|
|
|
|
### Key Files
|
|
|
|
- `backend/app/main.py` - FastAPI application setup with lifespan management
|
|
- `backend/app/config.py` - Application configuration and database settings
|
|
- `backend/run.py` - Standalone uvicorn runner (unused: Docker starts uvicorn from `compose.yaml`)
|
|
- `backend/migrations/` - Alembic environment and versions
|
|
- `compose.yaml` - Docker Compose setup: backend, frontend, PostgreSQL
|
|
|
|
## Environment Setup
|
|
|
|
Copy `.env.example` to `.env` (repo root) and configure:
|
|
- PostgreSQL connection settings
|
|
- Debug mode
|
|
- PYTHONPATH (for Docker)
|
|
|
|
The application will run database migrations automatically on startup through the FastAPI lifespan event.
|