3.3 KiB
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:
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 |
MySQL 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 fromlocalStorage, prefixesBASE = '/api/v1'auth.tsx—AuthProvidercontext; decodes the JWT payload to exposeroleandvolunteerIDpages/— one file per route (Dashboard,Schedules,TimeOff,Volunteers,Login)App.tsx—BrowserRouterwith aProtectedLayoutthat redirects to/loginwhen no token is present; admin-only nav links gated onrole === 'admin'
Data Storage
MySQL 8.0 via github.com/go-sql-driver/mysql. 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 |
|---|---|---|
DB_HOST |
localhost |
MySQL host |
DB_PORT |
3306 |
MySQL port |
DB_USER |
root |
MySQL username |
DB_PASSWORD |
`` | MySQL password |
DB_NAME |
walkies |
MySQL database name |
JWT_SECRET |
change-me-in-production |
HMAC signing key |
STATIC_DIR |
./web/dist |
Path to compiled React app |
PORT |
8080 |
HTTP listen port |