Files
tutortool/CLAUDE.md

3.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

# Development
make dev              # start backend + frontend in parallel
make dev-backend      # cargo run (port 3000)
make dev-frontend     # pnpm dev (port 5173, /api proxied to :3000)

# Build
make build            # pnpm 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
pnpm check            # TypeScript + Svelte type check
pnpm check:watch      # watch mode
pnpm 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<SqlitePool> 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/admin/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: closedopenlocked. 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.