You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7.1 KiB

@../CLAUDE.md

CLAUDE.md — quotesdb

Run all commands from the relevant sub-directory within `quotesdb/` (e.g., `api/`, `ui/`, `infra/`) — not from the repository root or the `quotesdb/` root.

Project Overview

quotesdb is a quotes web application in the vibed mono-repo. It is a single Cargo crate with two binaries and shared library code:

quotesdb/
├── Cargo.toml            # single crate, default-run = "api"
├── src/
│   ├── lib.rs            # shared types/utilities (compiles for host + wasm32)
│   └── bin/
│       ├── api/
│       │   └── main.rs   # API server binary
│       └── ui/
│           └── main.rs   # Yew frontend binary (compiled by Trunk)
├── tests/                # Cargo integration tests (cargo test runs these)
├── index.html            # Trunk HTML entry
├── Trunk.toml            # Trunk config
├── infra/                # OpenTofu infrastructure
└── docs/                 # Planning, architecture, and design docs
    └── plans/
        └── 2026-02-27-quotesdb-design.md

Design reference: docs/plans/2026-02-27-quotesdb-design.md

beans Ticket Tracking

Always run beans commands from the quotesdb/ directory. Beans are scoped to the directory where beans init was run. Running beans from a parent directory will not find these beans.

# Correct — from quotesdb/
beans list --json
beans show --json <id>
beans update --json <id> --status completed

# Wrong — from vibed/
cd quotesdb && beans list --json   # must be in quotesdb/

Bean Hierarchy

quotesdb                          (root epic bean)
├── quotesdb/api                  (sub-epic bean)
│   ├── quotesdb/api/<bean-id>    (task/feature/bug beans)
│   └── ...
├── quotesdb/ui
│   └── ...
├── quotesdb/qa
│   └── ...
└── quotesdb/infra
    └── ...

Rules:

  • Create a bean before starting any non-trivial work.
  • Work beans block their sub-epic bean — wire with beans update <sub-epic-id> --blocked-by <new-bean-id>.
  • Sub-epic beans block the root epic bean.
  • The dependency flows upward: work → sub-epic → root. Each level can only close after all beans below it are done.
  • Only close a bean 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/<domain>/<ticket-id>

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

# Create worktree for a ticket
git worktree add .claude/worktrees/quotesdb-api-<id> -b quotesdb/api/<id>

# ... do the work inside quotesdb/ root ...

# Validate before merging (always from quotesdb/ root)
cargo fmt && cargo check && cargo clippy && cargo test

# Merge into quotesdb branch
git checkout quotesdb
git merge quotesdb/api/<id>

# Remove worktree
git worktree remove .claude/worktrees/quotesdb-api-<id>

Domain Expert Sub-Agents

Dispatch all implementation work to a domain expert sub-agent. Match the domain to the agent:

Domain Path Agent role
API src/bin/api/ Senior Rust backend engineer — expert in API design, Axum, workers-rs, SQLx, and unit testing
UI src/bin/ui/ Senior Rust frontend engineer — expert in Yew, Wasm, Trunk, and web design
Shared src/lib.rs Software architect — must keep code compatible with both host and wasm32 targets
Infra 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 bean body (beans show --json <id>)
  3. The validation commands to run before closing the ticket
  4. The conventional commit scope to use (e.g., feat(quotesdb): ...)

Design Reference

Database Schema

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

API Specification

The API spec lives at api/openapi.yaml (OpenAPI 3.1.0, YAML format).

  • The spec is the source of truth for all endpoint contracts.
  • Validate with Redocly CLI after any changes (from the quotesdb/ directory):
redocly lint api/openapi.yaml

Validation

Run in order from the quotesdb/ root before closing any ticket:

cargo fmt       # 1. formatting
cargo check     # 2. syntax
cargo clippy    # 3. best practices
cargo test      # 4. correctness

For API spec changes:

redocly lint api/openapi.yaml

For infra changes, run from the infra/ directory:

tofu validate
tofu plan