
# [App Name] · Go + HTMX

A Go web app. Server-rendered HTML, HTMX for partial updates, SQLite for state. Single binary, single deploy.

## Source of truth
GitHub. CI builds a single static binary (CGO_ENABLED=0 GOOS=linux). The deployed binary is canonical. SQLite file is included in the volume; nightly backup to S3.

## Tech stack
Go 1.23+ + `chi` for routing + `templ` for typed templates + HTMX for interactivity + Alpine.js (only where HTMX falls short). SQLite via `mattn/go-sqlite3` (or `modernc.org/sqlite` for pure Go). Tailwind v4 via the standalone CLI (no Node). Litestream for SQLite replication.

## Deploy
- Build: `go build -o bin/app ./cmd/server`
- Run: `./bin/app` (port 8080)
- Production: systemd service + Caddy in front for TLS. OR Fly.io with a single VM and persistent volume.
- Backups: Litestream replicates SQLite to S3 continuously.

## File map
- `cmd/server/main.go` server entrypoint, HTTP setup
- `internal/handlers/` chi handlers, one per resource
- `internal/views/` `*.templ` templates (compiled to Go via `templ generate`)
- `internal/db/` sqlc queries (typed Go from SQL) OR raw `database/sql`
- `internal/middleware/` auth, logging, request ID
- `migrations/` numbered SQL migrations applied via `goose`
- `static/` JS (htmx, alpine), CSS (compiled Tailwind), images
- `Caddyfile` reverse proxy config (production)

## .env keys
- `DB_PATH` default `./data/app.db`
- `PORT` default 8080
- `SESSION_SECRET` random 32-byte hex
- `S3_BUCKET`, `S3_ACCESS_KEY`, `S3_SECRET` (Litestream)
- `ENV` `dev` | `prod`

## Hard rules
- Templates are `.templ` files compiled with `templ generate`. Never edit generated `.templ.go` files.
- SQLite is single-writer. Don't run multiple processes against the same DB file. Litestream is for backup, not for distribution.
- HTMX swaps are SCOPED. Every endpoint returns a fragment that exactly matches the swap target. Don't return full pages and then style-hide chunks.
- Migrations via `goose up`. Migration files are immutable once shipped to prod.
- Session cookie is httpOnly, secure, sameSite=lax. Random 32-byte token, NOT a JWT.
- Single binary deploy. No `node_modules`. No `vendor/` committed unless you have a hard reason.

## Recent significant changes
- 2026-05-11: Scaffolded. Locked: templ over html/template (type safety), HTMX over full SPA (boring is good), Litestream over manual backups (works while you sleep).

## Next session: start here
1. `templ generate` to compile templates. Set up a `make` target so this runs on every save.
2. `goose -dir migrations create init sql` and write your first schema.
3. Implement first resource: handler + template + SQL query. Click through it.
4. Set up Litestream pointing at S3. Confirm a backup appears within 10 minutes.
5. Deploy to a single Fly VM with a persistent volume. Confirm restart doesn't lose data.
