@../CLAUDE.md # CLAUDE.md — pages `pages` is a micro static-site host: upload an `.html` or `.zip`, get it served at `pages.elijah.run//`. One Cloudflare Worker (Rust → wasm via workers-rs + axum), an R2 bucket for content, a D1 database for users/sessions/page metadata, GitHub OAuth for login. **Design reference (read first):** `docs/plans/2026-07-12-pages-design.md` Run all commands from `pages/` (or `pages/infra/` for OpenTofu). Beans are scoped to this directory — run `beans` commands from `pages/`. ## Deviations from repo defaults (deliberate, see design doc §3) - **No SQLx** — SQLx cannot run on Cloudflare Workers; D1 access uses the `worker` crate bindings directly. - **No Yew/Trunk frontend** — v0 ships a single `static/index.html` (inline CSS/JS) embedded in the Worker via `include_str!`. - **Worker deploys via `wrangler deploy`**, not OpenTofu (Terraform provider can't upload module Workers with wasm). OpenTofu owns R2/D1/DNS/rate limits in `infra/`. ## Validation (run from `pages/`, in order) ```sh cargo fmt cargo check --target wasm32-unknown-unknown # worker code is wasm-only cargo check # native (pure logic modules) cargo clippy --all-targets -- -D warnings cargo clippy --target wasm32-unknown-unknown -- -D warnings cargo test # native unit tests ``` For infra changes (from `pages/infra/`): `tofu fmt` and `tofu validate`. ## wasm / workers-rs notes - Follow the `../quotesdb` pattern for the `#[worker::event(fetch)]` + axum glue (`quotesdb/src/lib.rs` bottom) and for `Cargo.toml` target-gated dependencies (getrandom `wasm_js`, worker `http` feature, tower-service). - Keep all policy logic (slug/zip/MIME/cookie parsing) in pure modules that compile natively so `cargo test` covers them; wasm-only code (`cfg(target_arch = "wasm32")`) should be thin glue. - Workers wasm is single-threaded: `unsafe impl Send/Sync` on Arc-wrapped state wrappers is the accepted pattern (as in quotesdb).