# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash # Development make dev # start backend + frontend in parallel make dev-backend # cargo run (port 3000) make dev-frontend # npm run dev (port 5173, /api proxied to :3000) # Build make build # npm run build, then cargo build --release make compose-up # docker compose build + start # Backend cargo test # run all tests (uses sqlx::test macro — no DB setup needed) cargo check # fast type check without linking # Frontend npm run check # TypeScript + Svelte type check npm run check:watch # watch mode npm run build # Vite build to dist/ ``` ## Architecture TutorTool is a **Rust + SvelteKit attendance tracker** for tutoring sessions. ### Backend (`backend/`) - **Framework**: Axum (async) on Tokio, port 3000 - **Database**: SQLite via SQLx — all queries use the runtime `sqlx::query()` / `sqlx::query_as::<_, T>()` (not compile-time macros); no `DATABASE_URL` needed for `cargo build`/`cargo check` - **Auth**: JWT (7-day expiry, `jsonwebtoken` crate) + bcrypt passwords; `TutorClaims` extractor in `auth.rs` - **Static serving**: `tower_http::ServeDir` serves compiled frontend from `frontend/build/` with SPA fallback to `index.html` - **Migrations**: auto-run via `sqlx::migrate!` at startup from `backend/migrations/` - **`PRAGMA foreign_keys = ON`** is enforced on every connection in `db.rs` Route handlers live in `backend/src/routes/` and are merged into the main router in `main.rs`. Each handler receives `State` and extracts `TutorClaims` from the JWT on protected routes. ### Frontend (`frontend/`) - **Framework**: SvelteKit 5 (Svelte runes, `$state`/`$derived`) with TypeScript - **Adapter**: `adapter-static` → single-page app, `fallback: 'index.html'` - **API client**: `src/lib/api.ts` — all fetch calls go through here; JWT injected from `src/lib/auth.ts` (localStorage-backed store) - **Types**: `src/lib/types.ts` mirrors the Rust models exactly — keep them in sync when changing the API Routes: - `routes/login/` — public login - `routes/admin/` — all tutor-facing pages (guarded by `+layout.svelte` auth check) - `routes/s/[code]/` — public student check-in page ### Data Model (SQLite, 9 tables) ``` tutors ──< tutor_courses >── courses ──< students └──< sessions ──< slots ──< attendances └──< notes rooms (layout_json) ←── slots.room_id ``` Key slot status transitions: `closed` → `open` → `locked`. The `code` field on slots is the public check-in token students use at `/s/[code]`. ### Container / K8s - `Dockerfile`: 3-stage build (Node 20 frontend → Rust 1.95 backend → Debian slim runtime) - `k8s/`: Deployment, Service, PVC for SQLite, CronJob for nightly vacuum + backup rotation - Live at `tutor.puchstein.dev` (tenant-5, ITSH Cloud) ## Conventions - SQLx compile-time queries require `DATABASE_URL` set to a valid SQLite file during `cargo build`/`cargo check`. Use `export DATABASE_URL=sqlite:./dev.db` if running outside `make dev`. - Rust toolchain is pinned to 1.95.0 via `rust-toolchain.toml`. - Frontend indentation: 2 spaces (Svelte/TS files). Backend: standard `rustfmt` defaults.