| 1 | # CLAUDE.md - Agent Bootstrap for DropHawk |
| 2 | |
| 3 | You are about to build **DropHawk**, an always-on, self-hosted, multi-source ticket-drop monitor. The operator is disabled and relies on this working. Read this file in full, then load the two authoritative documents below. |
| 4 | |
| 5 | ## Authoritative documents (read in order) |
| 6 | |
| 7 | | Order | File | Role | |
| 8 | |---|---|---| |
| 9 | | 1 | `SPEC.md` | Architecture & intent. Section 4 = repo layout. Section 14 = phased roadmap. | |
| 10 | | 2 | `CONTRACTS.md` | **Binding implementation contracts.** Versions, schemas, DDL, colors, algorithms, runbooks. This file wins on disagreement. | |
| 11 | |
| 12 | Do not write any code until both are read. |
| 13 | |
| 14 | ## What DropHawk is |
| 15 | |
| 16 | A homelab Docker service that continuously polls dozens of ticket sources (Ticketmaster, SeatGeek, FIFA, AXS, StubHub, NFL/NBA/NHL/MLB, F1, UEFA, festivals, Twitter/X shock-drop monitor), detects the instant an event's status flips to "on sale" (or a new event appears, or a resale price drops ≥10%), and pushes a notification to the operator's phone via self-hosted ntfy within 15 seconds - with a one-tap link to buy. |
| 17 | |
| 18 | ## What DropHawk is NOT (hard guardrails) |
| 19 | |
| 20 | - ❌ Not a bulk auto-purchaser. (US BOTS Act / UK law) |
| 21 | - ❌ Not a CAPTCHA solver. If a source requires CAPTCHA, mark it `down`. |
| 22 | - ❌ Not a ticket marketplace. |
| 23 | - ❌ Not a scalping bot. Personal-use monitoring + manual purchase only. |
| 24 | |
| 25 | ## Tech stack (locked - see CONTRACTS §A for exact pins) |
| 26 | |
| 27 | - **Backend core**: Rust 1.96 + Tokio + Axum 0.8 + sqlx + async-nats + reqwest |
| 28 | - **Scrapers**: Python 3.11 + httpx + curl_cffi + Playwright + async-nats |
| 29 | - **Frontend**: Next.js 16 + React 19 + Tailwind 4 (CSS-first!) + Radix + Recharts + Framer Motion |
| 30 | - **Data**: PostgreSQL 16 + TimescaleDB + Redis 7 + Meilisearch 1.47 |
| 31 | - **Bus**: NATS 2.14 + JetStream |
| 32 | - **Notifications**: ntfy 2.14 (self-hosted, free iPhone push) |
| 33 | - **Edge**: Caddy 2.11 |
| 34 | - **Observability**: Prometheus + Grafana 13 + Loki |
| 35 | |
| 36 | ## Hard rules (violations are bugs) |
| 37 | |
| 38 | 1. **Implement Phase 1 end-to-end before touching Phase 2.** Thin working slice > wide unfinished. |
| 39 | 2. **No `unwrap()`/`any`/`TODO`/`console.log`/`print` in committed code.** |
| 40 | 3. **Run `make check` before any merge.** Clippy + ruff + mypy + tsc + eslint + tests all green. |
| 41 | 4. **Tailwind is v4 → no `tailwind.config.ts`.** Config lives in `app/globals.css` via `@theme`. Read CONTRACTS §H.1. |
| 42 | 5. **Every notification must pass dedupe + filter pipeline** (CONTRACTS §I.3). False positives erode trust fastest. |
| 43 | 6. **OKLCH palette in CONTRACTS §H.1 is the entire color system.** No ad-hoc hex. |
| 44 | 7. **Hash canonicalization** (CONTRACTS §D) is the regression gate. Golden vectors locked. |
| 45 | 8. **Migrations are forward-only and immutable.** Never edit applied. |
| 46 | 9. **No third-party deps beyond pinned list.** Adding one requires updating CONTRACTS §A. |
| 47 | 10. **`.env` never committed.** Pre-commit `gitleaks` enforces. |
| 48 | 11. **Conventional commits.** `feat:`, `fix:`, `chore:`, `docs:`. |
| 49 | 12. **No direct `fetch` in React components.** All API calls via `lib/api.ts`. |
| 50 | 13. **All forms validated by Zod (client) AND `validator` crate (server).** |
| 51 | 14. **Server Components by default.** `"use client"` only where needed (SSE consumers, interactive state). |
| 52 | 15. **Accessibility: WCAG 2.2 AA.** `axe-core` runs in e2e; CI fails on new violations. |
| 53 | |
| 54 | ## Phase 1 deliverable (your first milestone) |
| 55 | |
| 56 | A vertical slice that proves the architecture: |
| 57 | - Repo scaffold per SPEC §4. |
| 58 | - Rust backend: config, DB pool, NATS, Axum, scheduler, **Ticketmaster adapter only** (CONTRACTS §A.1, §B.3, §C, §D, §E). |
| 59 | - Postgres 16 + TimescaleDB with migrations from CONTRACTS §G.1-§G.10. |
| 60 | - ntfy container + publisher (CONTRACTS §I). |
| 61 | - Next.js 16 + Tailwind 4 (CONTRACTS §H.1) with: dashboard, LiveDropFeed (real SSE), DropCard, StatsRow, watchlist CRUD. |
| 62 | - Caddy + `docker-compose.yml` for this subset. |
| 63 | - **Success criterion**: operator can add "Taylor Swift" to watchlist, get an ntfy push when a Ticketmaster event flips on-sale, see it stream into the dashboard in real time. `make check` green. `docker compose up -d` healthy. |
| 64 | |
| 65 | Do NOT start Phase 2 (SeatGeek, Meilisearch, source grid) until Phase 1 is verified working end-to-end by the operator. |
| 66 | |
| 67 | ## Where to look things up |
| 68 | |
| 69 | | Need | File | Section | |
| 70 | |---|---|---| |
| 71 | | Exact dependency version | CONTRACTS | §A | |
| 72 | | API request/response shape | CONTRACTS | §B | |
| 73 | | Polling algorithm pseudocode | CONTRACTS | §C | |
| 74 | | How content_hash is computed | CONTRACTS | §D | |
| 75 | | Drop detection + classification | CONTRACTS | §E | |
| 76 | | TLS impersonation rules | CONTRACTS | §F | |
| 77 | | SQL schema (every table, index, constraint) | CONTRACTS | §G | |
| 78 | | Color palette / type scale / motion | CONTRACTS | §H | |
| 79 | | ntfy payload templates | CONTRACTS | §I | |
| 80 | | Prometheus metrics + SLOs | CONTRACTS | §J | |
| 81 | | Error taxonomy | CONTRACTS | §K | |
| 82 | | Backup / DR | CONTRACTS | §L | |
| 83 | | Security model | CONTRACTS | §M | |
| 84 | | Testing strategy | CONTRACTS | §N | |
| 85 | | Performance budgets | CONTRACTS | §O | |
| 86 | | Idempotency rules | CONTRACTS | §P | |
| 87 | | Cross-source event linking | CONTRACTS | §Q | |
| 88 | | Buy URL canonicalization | CONTRACTS | §R | |
| 89 | | PWA / mobile | CONTRACTS | §S | |
| 90 | | WCAG 2.2 AA | CONTRACTS | §T | |
| 91 | | i18n | CONTRACTS | §U | |
| 92 | | Image pipeline | CONTRACTS | §V | |
| 93 | | Failure mode runbooks | CONTRACTS | §W | |
| 94 | | CORS | CONTRACTS | §X | |
| 95 | | Every env var | CONTRACTS | §Y | |
| 96 | |
| 97 | ## Make targets to implement |
| 98 | |
| 99 | ```make |
| 100 | make up # docker compose up -d |
| 101 | make down # docker compose down |
| 102 | make logs # docker compose logs -f |
| 103 | make check # clippy + ruff + mypy + tsc + eslint + tests |
| 104 | make migrate # sqlx migrate run (against $DATABASE_URL) |
| 105 | make seed # apply seed migrations |
| 106 | make psql # docker compose exec postgres psql -U drophawk |
| 107 | make redis-cli # docker compose exec redis redis-cli |
| 108 | make nats-sub # docker compose exec nats nats sub '>' |
| 109 | make health # scripts/healthcheck.sh |
| 110 | make backup # scripts/pg-backup.sh |
| 111 | make bench # cargo bench + pnpm test:e2e |
| 112 | ``` |
| 113 | |
| 114 | ## Final note to the executing agent |
| 115 | |
| 116 | The operator wants "the best of the best." This means: production-grade reliability, beautiful dense UI, no shortcuts, no settling. But it also means: **don't over-engineer Phase 1**. The Phase 1 slice must be unambiguously working before breadth is added. Reliability > features. A working Ticketmaster-only slice the operator can trust beats a half-built 25-source monster that crashes nightly. |
| 117 | |
| 118 | Begin now. Read SPEC.md §4, then CONTRACTS.md §A and §G, then scaffold the repo. First commit: empty directory structure with placeholder files matching SPEC §4 + this CLAUDE.md + SPEC.md + CONTRACTS.md + `.env.example` + `Makefile` + `docker-compose.yml`. Then implement Ticketmaster adapter. Then notification. Then UI. Verify end-to-end. Iterate. |