Switch to phone auth via Twilio SMS and add feature flag system
Replace email-based auth (Resend) with phone-based auth (Twilio SMS). Add BBQ_FEATURES env var for toggling features at deploy time — when auth is disabled, no login routes are registered and the app works as before. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## What This Is
|
||||
|
||||
Potluck signup app. No accounts — share a link, people claim slots. Open like a shared Google Sheet.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Build and run
|
||||
go build -o bbq . && ./bbq
|
||||
|
||||
# Docker
|
||||
docker compose up -d --build
|
||||
|
||||
# Regenerate DB layer after editing schema.sql or db/queries.sql
|
||||
$(go env GOPATH)/bin/sqlc generate
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `PORT` — Go server listen port (default `8080`)
|
||||
- `BBQ_DB` — SQLite database path (default `bbq.db`)
|
||||
- `BBQ_BASE_URL` — Absolute URL for OG images (e.g. `https://bbq.torrtle.co`)
|
||||
- `HOST_PORT` — Compose host-side port mapping (default `8090`)
|
||||
|
||||
## Architecture
|
||||
|
||||
**Stack:** Go, chi router, sqlc + SQLite (mattn/go-sqlite3), html/template, HTMX + SSE
|
||||
|
||||
**Design:** Soft Brutalism — cream `#f5f0e8`, black borders/shadows, yellow `#f5e642` accents, Bricolage Grotesque + DM Mono fonts
|
||||
|
||||
### Data Flow
|
||||
|
||||
`schema.sql` defines tables (events, slots, claims, rsvps) → `db/queries.sql` has SQL queries → `sqlc generate` produces `db/` package (models.go, queries.sql.go, db.go). Never edit generated files in `db/` directly.
|
||||
|
||||
### Server (`main.go`)
|
||||
|
||||
`Server` struct holds `*db.Queries`, `*sql.DB`, `baseURL`, and SSE client channels. SSE uses `subscribe/unsubscribe/notify` pattern — any mutation calls `notify(slug)` to push updates to all viewers.
|
||||
|
||||
### Templates
|
||||
|
||||
Go template inheritance doesn't work with a single `ParseFS`, so each page is parsed separately into `pageTmpl` map:
|
||||
- `pageTmpl["home"]` / `pageTmpl["event"]` — full pages, rendered via `.ExecuteTemplate(w, "layout", data)`
|
||||
- `pageTmpl["slots"]` — partial for HTMX responses, rendered via `.ExecuteTemplate(w, "slots-inner", data)`
|
||||
|
||||
Template files: `layout.html` (shell + all CSS/JS), `slots.html` (shared partial), `event.html`, `home.html`. All CSS is inline in `layout.html`.
|
||||
|
||||
### Handlers (`handlers.go`)
|
||||
|
||||
`loadEventPage()` is the shared data loader — assembles `EventPageData` with event, slots+claims, rsvps, and counts. Used by both full page renders and HTMX partial responses.
|
||||
|
||||
### OG Image (`ogimage.go`)
|
||||
|
||||
Dynamic PNG generation at `/e/{slug}/og.png` using Go's `image` package with a custom 5x7 bitmap font. Renders event title, date/time/location in the app's visual style.
|
||||
|
||||
### Routes
|
||||
|
||||
- `GET /` — create event form
|
||||
- `POST /events` — creates event + slots, redirects to admin URL
|
||||
- `GET /e/{slug}` — guest view
|
||||
- `POST /e/{slug}/claim` / `DELETE /e/{slug}/claim/{claimID}` — HTMX claim/unclaim
|
||||
- `POST /e/{slug}/rsvp` / `DELETE /e/{slug}/rsvp/{rsvpID}` — HTMX RSVP
|
||||
- `GET /e/{slug}/sse` — SSE stream for live updates
|
||||
- `GET /e/{slug}/og.png` — dynamic OG image
|
||||
- `GET /e/{slug}/admin/{token}` — admin view (same template, `IsAdmin=true`)
|
||||
- `POST /e/{slug}/admin/{token}/slot` / `DELETE /e/{slug}/admin/{token}/slot/{slotID}` — manage slots
|
||||
|
||||
### Auth Model
|
||||
|
||||
No user auth. Admin access is via secret `admin_token` in the URL. Claims/RSVPs are open to anyone with the event link.
|
||||
Reference in New Issue
Block a user