diff --git a/CLAUDE.md b/CLAUDE.md index 6082a57..85ecc93 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ ## Project Overview -Workout Tracker — a self-hosted, mobile-first SvelteKit app for logging workouts with progressive overload tracking. Single-user, no auth. See `llm-docs/v1/REQUIREMENTS.md` for full product requirements and `llm-docs/v1/TECHNICAL_DESIGN.md` for architecture details. +Workout Tracker -- a self-hosted, mobile-first SvelteKit app for logging workouts with progressive overload tracking. Single-user, no auth. See `docs/` for architecture, database schema, offline design, and deployment. See `llm-docs/` for original product requirements and technical design. ## Tech Stack @@ -50,41 +50,36 @@ Two test projects configured in `vite.config.ts`: Any documentation written by agents must be clear, simple, and short. No unnecessary verbosity. -## Architecture +## Key File Locations -- **DB schema**: `src/lib/server/db/schema.ts` — Drizzle schema definition -- **DB connection**: `src/lib/server/db/index.ts` — creates connection with auto-detected path -- **Drizzle config**: `drizzle.config.ts` — migration config, schema path, SQLite dialect -- **Shared utils**: `src/lib/utils.ts` — `cn()` helper for Tailwind class merging + shadcn type helpers -- **Routes**: `src/routes/` — SvelteKit file-based routing -- **Components**: `src/lib/components/` — organized by domain (layout, workout, program, history, exercises, shared, ui) -- **Server logic**: `src/lib/server/` — DB queries in `db/queries/`, utilities in `utils/` +- **DB schema**: `src/lib/server/db/schema.ts` +- **DB connection**: `src/lib/server/db/index.ts` +- **DB queries**: `src/lib/server/db/queries/` +- **Drizzle config**: `drizzle.config.ts` +- **Shared utils**: `src/lib/utils.ts` +- **Routes**: `src/routes/` +- **Components**: `src/lib/components/` (layout, workout, program, shared, ui) +- **Server logic**: `src/lib/server/` +- **Offline module**: `src/lib/offline/` ## Documentation Lookup Rules **CRITICAL: Never rely on training data for syntax or APIs. Always look up latest docs.** -- **Svelte/SvelteKit**: Use the Svelte MCP server (`list-sections` then `get-documentation`). Always run `svelte-autofixer` on any Svelte code before finalizing. -- **shadcn-svelte**: Use https://www.shadcn-svelte.com — index at https://www.shadcn-svelte.com/llms.txt +- **Svelte/SvelteKit**: Use the Svelte MCP server (`list-sections` then `get-documentation`). Always run `svelte-autofixer` on any Svelte code before finalising. +- **shadcn-svelte**: Use https://www.shadcn-svelte.com -- index at https://www.shadcn-svelte.com/llms.txt - **All other technologies**: Use the Context7 MCP Server for up-to-date documentation. ## Svelte MCP Tools -1. **list-sections** — Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths. When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections. -2. **get-documentation** — Retrieves full documentation content for specific sections. Accepts single or multiple sections. After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task. -3. **svelte-autofixer** — Analyzes Svelte code and returns issues and suggestions. You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned. +1. **list-sections** -- Use this FIRST to discover all available documentation sections. +2. **get-documentation** -- Retrieves full documentation content for specific sections. After calling list-sections, analyse the returned sections and fetch ALL relevant ones. +3. **svelte-autofixer** -- Analyses Svelte code and returns issues and suggestions. MUST be used on any Svelte code before finalising. Keep calling until no issues remain. ## Context7 MCP Tools -1. **resolve-library-id** — Resolves a general library name into a Context7-compatible library ID. - -- `query` (required): The user's question or task (used to rank results by relevance) -- `libraryName` (required): The name of the library to search for - -2. **query-docs** — Retrieves documentation for a library using a Context7-compatible library ID. - -- `libraryId` (required): Exact Context7-compatible library ID (e.g., shadcn-svelte.com/docs, tailwindcss.com/docs) -- `query` (required): The question or task to get relevant documentation for +1. **resolve-library-id** -- Resolves a library name into a Context7-compatible library ID. +2. **query-docs** -- Retrieves documentation for a library using a Context7-compatible library ID. ## Branching & PR Workflow @@ -121,7 +116,7 @@ The `playwright-cli` skill is available for any Playwright browser automation ac At the end of each phase, a verifier subagent MUST be kicked off to check: -1. Everything is built as per the plan — no outstanding items +1. Everything is built as per the plan -- no outstanding items 2. No regressions or bugs introduced -3. All rules in this file were followed — no shortcuts taken +3. All rules in this file were followed -- no shortcuts taken 4. Code quality: DRY/YAGNI, clear, self-documenting diff --git a/README.md b/README.md index 21ad113..18b5744 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ # Workout Tracker -A self-hosted, mobile-first workout logging app with progressive overload tracking. Built with SvelteKit, SQLite, and Docker. +A self-hosted, mobile-first workout logging app built with SvelteKit and SQLite. Create workout programmes, log sets with weight and reps, and track progressive overload over time. Single-user, zero-config, works offline as a PWA. ## Requirements -- Node.js 22+ +- Node.js 22+ (for local development) +- Docker (for deployment) -## Development +## Local Development ```sh npm install @@ -15,43 +16,21 @@ npm run dev The database is automatically created at `./data/workout-tracker.db`. -## Deployment with Docker - -### Using Docker Compose (recommended) +## Docker Deployment ```sh docker compose up -d ``` -This starts the container on port 6789 and persists the database via a volume mount to `/data`. - -### Using Docker directly - -```sh -docker build -t workout-tracker . -docker run -d \ - -p 3000:3000 \ - -v workout-data:/data \ - workout-tracker -``` - -### Using the pre-built image from GHCR +Or use the pre-built image: ```sh -docker run -d \ - -p 3000:3000 \ - -v workout-data:/data \ - ghcr.io/kavith-k/workout-tracker:latest +docker run -d -p 3000:3000 -v workout-data:/data ghcr.io/kavith-k/workout-tracker:latest ``` -### Data persistence - -The database is stored at `/data/workout-tracker.db` inside the container. Mount a volume to `/data` to persist data across container restarts. - -### Configuration - -No environment variables are required. The app is zero-config. - -### HTTPS +## Documentation -Service workers and offline features require HTTPS in most browsers. This works automatically on `localhost`, but remote access over plain HTTP will disable offline support. Use a reverse proxy (e.g., Caddy, Traefik, nginx) to terminate TLS if accessing the app over the network. +- [Architecture](docs/architecture.md) -- tech stack, directory structure, data flow +- [Database](docs/database.md) -- schema, relationships, migration workflow +- [Offline](docs/offline.md) -- PWA, IndexedDB queue, sync engine +- [Deployment](docs/deployment.md) -- Docker, reverse proxy, HTTPS, data persistence diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..27ac726 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,122 @@ +# Architecture + +## Tech Stack + +| Layer | Technology | +| --------- | ------------------------------------- | +| Framework | SvelteKit 2 (Svelte 5), Node adapter | +| Styling | TailwindCSS v4 + shadcn-svelte | +| Database | SQLite via better-sqlite3 + Drizzle ORM | +| Offline | PWA with Service Worker (Workbox) | +| Testing | Vitest (unit/component) + Playwright (E2E) | + +## Directory Structure + +``` +src/ + lib/ + server/ + db/ + index.ts # DB connection (auto-detected path) + schema.ts # Drizzle schema definition + queries/ # Reusable query functions + programs.ts # Programme CRUD + exercises.ts # Exercise CRUD + workouts.ts # Workout session lifecycle + history.ts # History browsing and deletion + export.ts # JSON/CSV export assembly + utils/ # Server-side utilities + components/ + ui/ # shadcn-svelte components + layout/ # App shell, navigation, resume banner + home/ # ConsistencyGrid (GitHub-style activity heatmap) + program/ # Programme form (drag-to-reorder via svelte-dnd-action) + workout/ # Workout wizard, ExerciseStep (set logging, copy-down, volume) + shared/ # Offline indicator, empty state, confirm dialog + offline/ + queue.ts # IndexedDB queue management + sync.ts # Sync engine (periodic + on-reconnect) + stores.svelte.ts # Reactive online/sync status + utils.ts # cn() helper, shadcn type helpers + routes/ # SvelteKit file-based routing (see below) + app.html + app.css # Tailwind imports, global styles +static/ # PWA icons, favicon +drizzle/ # Generated migrations +e2e/ # Playwright E2E tests +scripts/ + seed-test-data.mjs # Wipe DB and populate with 2 years of sample data +``` + +## Routes + +| Route | Purpose | +| ------------------------------ | --------------------------------------------- | +| `/` | Home screen with active programme days and consistency grid | +| `/workout/start` | Form action to create session and redirect | +| `/workout/[sessionId]` | Active workout logging interface | +| `/workout/[sessionId]/summary` | Post-workout summary with PRs and stats | +| `/history` | Past workouts by date with infinite scroll | +| `/history/[sessionId]` | Single workout session details | +| `/api/history` | GET endpoint for paginated history (infinite scroll) | +| `/programs` | List and manage programmes | +| `/programs/new` | Create new programme | +| `/programs/[programId]` | Edit existing programme | +| `/exercises` | Exercise library with stats | +| `/settings` | Data export (JSON/CSV) | +| `/api/sync` | POST endpoint for offline queue synchronisation | + +## Data Flow + +### Starting a Workout + +1. User taps a workout day on the home screen +2. `POST /workout/start` creates a `workout_session` (status: `in_progress`), pre-creates `exercise_logs` and empty `set_logs` +3. Redirects to `/workout/[sessionId]` +4. Load function fetches session details, exercise logs with sets, and progressive overload data + +### Logging Sets + +Each set row is a `