From 4c4837037314d1620a41a4b091a8ebca48f29ec8 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Fri, 27 Feb 2026 21:46:45 -0800 Subject: [PATCH] docs(quotesdb): add project CLAUDE.md with workflow and design reference Co-Authored-By: Claude Sonnet 4.6 --- quotesdb/CLAUDE.md | 177 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 quotesdb/CLAUDE.md diff --git a/quotesdb/CLAUDE.md b/quotesdb/CLAUDE.md new file mode 100644 index 0000000..0b3063a --- /dev/null +++ b/quotesdb/CLAUDE.md @@ -0,0 +1,177 @@ +# CLAUDE.md — quotesdb + +> Inherits all conventions from [@../CLAUDE.md](../CLAUDE.md). This file adds project-specific workflow, structure, and agent dispatch rules. + +--- + +## Project Overview + +`quotesdb` is a quotes web application in the vibed mono-repo. It consists of: + +- **`api/`** — Rust/Axum backend on Cloudflare Workers +- **`ui/`** — Yew (Rust/Wasm) frontend on Cloudflare Pages +- **`tests/`** — Integration test crate +- **`infra/`** — OpenTofu infrastructure (Cloudflare D1, Workers, Pages) +- **`docs/`** — Project-level docs and design plans + +Design reference: `docs/plans/2026-02-27-quotesdb-design.md` + +--- + +## Ticket Hierarchy + +Tickets are organised as a dependency tree rooted at the project ticket: + +``` +quotesdb (root project ticket, ec118c) +├── quotesdb/api (sub-project ticket) +│ ├── quotesdb/api/ (task/feature/bug tickets) +│ └── ... +├── quotesdb/ui +│ └── ... +├── quotesdb/qa +│ └── ... +└── quotesdb/infra + └── ... +``` + +Rules: +- Create a ticket **before** starting any non-trivial work. +- Each work ticket must list its sub-project ticket as a dependency (`--deps `). +- Each sub-project ticket must list the root project ticket (`ec118c`) as a dependency. +- **Only close a ticket after its work has been validated** (all `cargo fmt/check/clippy/test` pass, or equivalent for infra). + +--- + +## Branch & Worktree Workflow + +All work happens in **git worktrees** on named branches. + +### Branch naming + +``` +quotesdb// +``` + +Examples: +- `quotesdb/api/a1b2c3` +- `quotesdb/ui/d4e5f6` +- `quotesdb/qa/g7h8i9` +- `quotesdb/infra/j0k1l2` + +### Merge target + +All completed work branches merge into the **`quotesdb`** branch (not `main`). + +### Typical flow + +```bash +# Create worktree for a ticket +git worktree add .claude/worktrees/quotesdb-api- -b quotesdb/api/ + +# ... do the work ... + +# Validate before merging (from the relevant sub-directory) +cargo fmt && cargo check && cargo clippy && cargo test + +# Merge into quotesdb branch +git checkout quotesdb +git merge quotesdb/api/ + +# Remove worktree +git worktree remove .claude/worktrees/quotesdb-api- +``` + +--- + +## Domain Expert Sub-Agents + +Dispatch all implementation work to a domain expert sub-agent. Match the domain to the agent: + +| Domain | Agent role | +|--------|-----------| +| `api/` | Senior Rust backend engineer — expert in API design, Axum, workers-rs, SQLx, and unit testing | +| `ui/` | Senior Rust frontend engineer — expert in Yew, Wasm, Trunk, and web design | +| `tests/` | Senior QA engineer — expert in Rust integration testing and HTTP test harnesses | +| `infra/` | DevOps/infrastructure engineer — expert in OpenTofu, Terraform, and Cloudflare | +| Anything else | Software architect — expert in cloud services, Rust software patterns, and system design | + +Each sub-agent should receive: +1. The relevant section of `docs/plans/2026-02-27-quotesdb-design.md` +2. The specific nbd ticket body +3. The validation commands to run before closing the ticket +4. The conventional commit scope to use (e.g., `feat(quotesdb-api): ...`) + +--- + +## Design Reference + +### Database Schema + +```sql +CREATE TABLE quotes ( + id TEXT PRIMARY KEY, -- NanoID (~21 chars) + text TEXT NOT NULL, + author TEXT NOT NULL, + source TEXT, -- optional: book, speech, etc. + date TEXT, -- optional: ISO date YYYY-MM-DD + auth_code TEXT NOT NULL, -- 4-word passphrase e.g. ocean-table-purple-storm + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE quote_tags ( + quote_id TEXT NOT NULL REFERENCES quotes(id) ON DELETE CASCADE, + tag TEXT NOT NULL, + PRIMARY KEY (quote_id, tag) +); +``` + +### API Endpoints + +| Method | Path | Description | Auth | +|--------|------|-------------|------| +| GET | `/api/` | OpenAPI spec (JSON) | None | +| GET | `/api/quotes` | List quotes, 10/page. Query: `?page=N&author=X&tag=Y` | None | +| GET | `/api/quotes/random` | Random quote | None | +| GET | `/api/quotes/:id` | Get quote by NanoID | None | +| PUT | `/api/quotes` | Create a quote | None (auth_code optional in body) | +| POST | `/api/quotes/:id` | Update a quote | `X-Auth-Code` header | +| DELETE | `/api/quotes/:id` | Delete a quote | `X-Auth-Code` header | + +> **Router order:** `GET /api/quotes/random` must be registered **before** `GET /api/quotes/:id`. + +### Auth + +- No user accounts. Each quote has an `auth_code` (4-word passphrase), stored plaintext. +- Provided via `X-Auth-Code` header for update/delete. On mismatch: `403 Forbidden`. +- Auth code is always returned in the create response. + +### Frontend Routes (Yew) + +| Route | Page | +|-------|------| +| `/` | Home — random quote + "Browse all" link | +| `/browse` | Paginated list with author/tag filter controls | +| `/quotes/:id` | Single quote — view, edit (auth prompt), delete (auth prompt) | +| `/author/:name` | All quotes by an author | +| `/submit` | New quote submission form | + +--- + +## Validation + +Run in order from the relevant sub-directory before closing any ticket: + +```sh +cargo fmt # 1. formatting +cargo check # 2. syntax +cargo clippy # 3. best practices +cargo test # 4. correctness +``` + +For infra tickets: +```sh +tofu validate +tofu plan +```