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.

65 lines
2.1 KiB
Markdown

@../CLAUDE.md
# CLAUDE.md — pages
`pages` is a micro static-site host: upload an `.html` or `.zip`, get it
served at `pages.elijah.run/<slug>/`. 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`
<working-directory>
Run all commands from `pages/` (or `pages/infra/` for OpenTofu).
</working-directory>
<beans>
Beans are scoped to this directory — run `beans` commands from `pages/`.
</beans>
<deviations>
## 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/`.
</deviations>
<validation>
## 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`.
</validation>
<wasm-notes>
## 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).
</wasm-notes>