# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands A `Taskfile.yml` is provided — run `task` to list all tasks. Key ones: ```bash task build # build frontend + Go binary task go:run # build frontend then start server on :8080 task web:dev # frontend hot-reload dev server on :3000 task go:test # run all Go tests task go:test:verbose task go:lint # go vet task web:test # frontend tests task docker:up # docker-compose up --build task clean # remove build artifacts ``` For a single Go package test: `go test ./internal/volunteer/...` ## Architecture ### Go Backend Domain-based packaging under `internal/` — each domain owns its models, store (DB queries), and HTTP handler in a single package: | Package | Responsibility | |---------|---------------| | `internal/volunteer` | Volunteer CRUD; also owns `/auth/login` and `/auth/register` handlers | | `internal/schedule` | Shift scheduling | | `internal/timeoff` | Time-off requests and admin review | | `internal/checkin` | Check-in / check-out and history | | `internal/notification` | Per-volunteer notifications | | `internal/auth` | JWT issuance (`auth.Service`) and `HashPassword` | | `internal/db` | SQLite open + one-shot schema migration (`db.Migrate`) | | `internal/respond` | `respond.JSON` / `respond.Error` helpers | | `internal/server` | Wires all handlers into a chi router; serves static files at `/` | | `internal/server/middleware` | `Authenticate` (JWT) and `RequireAdmin` middleware; `ClaimsFromContext` | `cmd/server/main.go` opens the DB, runs migrations, calls `server.New`, and starts `http.ListenAndServe`. All API routes are prefixed `/api/v1`. The Go binary serves the compiled React app from `STATIC_DIR` (default `./web/dist`) for all non-API routes. ### React Frontend Standard CRA layout in `web/src/`: - `api.ts` — typed fetch wrapper; reads JWT from `localStorage`, prefixes `BASE = '/api/v1'` - `auth.tsx` — `AuthProvider` context; decodes the JWT payload to expose `role` and `volunteerID` - `pages/` — one file per route (`Dashboard`, `Schedules`, `TimeOff`, `Volunteers`, `Login`) - `App.tsx` — `BrowserRouter` with a `ProtectedLayout` that redirects to `/login` when no token is present; admin-only nav links gated on `role === 'admin'` ### Data Storage SQLite via `modernc.org/sqlite` (pure Go, no CGO). Schema is defined inline in `internal/db/schema.go` and applied via `CREATE TABLE IF NOT EXISTS` on every startup. No migration framework — additive changes are safe; destructive changes require manual handling. ### Auth HS256 JWT signed with `JWT_SECRET`. Token payload: `{ volunteer_id, role, exp }`. Role is either `volunteer` or `admin`. The `RequireAdmin` middleware enforces admin-only routes server-side. ## Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `DATABASE_DSN` | `walkies.db` | SQLite file path | | `JWT_SECRET` | `change-me-in-production` | HMAC signing key | | `STATIC_DIR` | `./web/dist` | Path to compiled React app | | `PORT` | `8080` | HTTP listen port |