steid

@jamesgill /

steid/CLAUDE.md
5.9 KBCode·Blame·Raw
10ecb99docs: add CLAUDE.md1mo
1# Steid
2
3A personal-first gitforge in Rust. Hosts git repos, writing, and projects for one
4developer or an organisation. **Portfolio-first, not a Gitea clone** — the profile page
5is the product and repos are one kind of thing on it. Use that to break ties.
6
7## Read first
8
9`plans/` is the source of truth and is tracked in git. Read it at the start of a
10session rather than inferring intent from the code.
11
12| File | Holds |
13|---|---|
14| `plans/ROADMAP.md` | vision, stack, the single milestone ladder |
15| `plans/current.md` | the active milestone only — steps, watch-fors, backlog |
16| `plans/progress.md` | what shipped, and the decisions worth not rediscovering |
17| `plans/architecture.md` | layer rules and conventions |
18| `plans/runbook.md` | how to run it, config, manual verification |
19| `plans/decisions/` | ADRs; `TEMPLATE.md` defines the format |
20
21## Keep the docs current
22
23**Before reporting work complete, update `plans/`.** This is part of finishing the
24work, not a follow-up chore — the project has been restarted three times and the
25previous attempts lost their reasoning at exactly these handover points.
26
27- `current.md` — tick off finished steps; move completed work out to `progress.md`.
28 If it starts reading like a changelog, it has drifted.
29- `progress.md` — record decisions and gotchas that aren't obvious from the code. The
30 test is: would the next session waste an hour rediscovering this?
31- `ROADMAP.md` — only when a milestone's status actually changes.
32- `decisions/` — a new ADR when a choice would be expensive to reverse or constrains
33 future work. Write it when the decision is made; reconstructed rationale is fiction.
34
35Also update `current.md` when a *new* problem is found — an unfinished item, a
36shortcut taken, a hole opened. Carry those forward explicitly at milestone rollover
37rather than letting them vanish.
38
39Skip all of this for typos, formatting, and dependency bumps.
40
41## Working style
42
43- **Commit directly to `main`.** No feature branches — solo repo. Cleanliness comes
44 from small, self-contained commits that each compile, not from branching.
45- Small steps. Build up slowly; prefer a working increment over a big drop.
46- Explain *why* in commit messages, not just what.
47
48## Conventions
49
50Full detail in `plans/architecture.md`. The short version:
51
52- **Layers:** `domain` (no knowledge of HTTP/SQL/git/Topcoat) → `application` (use
53 cases and ports) → `infrastructure` (adapters, web). Dependencies point inward.
54- **Every use case takes an `Actor`** and enforces authorization before any side
55 effect — one place, reachable from a page, an `/api` route, or a future transport.
56- **Typed IDs**, never raw `String` for entity references.
57- **`new()` validates, `from_trusted()` doesn't.** Storage adapters use
58 `from_trusted`; re-validating stored rows makes a tightened rule unreadable.
59- **`from_str` returns `Result`, never `Option`.** A silently-defaulted enum surfaces
60 later as the wrong permissions.
61- **Every repository port gets two implementations** — in-memory (what makes use cases
62 testable without a database) and SQLite.
63- Request helpers are **functions taking `cx`**, not middleware or extractors. A page
64 that forgets to call one gets nothing; a route added without middleware silently
65 gets someone else's data.
66- Safe Rust only. No `unsafe`.
67
be4fac5docs: correct the Topcoat guidance in CLAUDE.md24d
68## Topcoat, as we use it
69
70Working knowledge that is easy to get wrong and slow to rediscover:
71
72- **Components are invoked bare inside `view!`**`label(attrs: …, "Text")`, not
73 `(label(…)?)`. `if`, `match`, `for` and `let` are native to the macro.
74- **`#[path_param]` is an attribute on a tuple struct**`#[path_param] struct
75 Handle(str);` — and the struct name snake-cased is the URL parameter.
76- **`#[query_params]` needs `error = …`** to be usable with `?`; otherwise the error
77 borrows from `cx` and escapes the handler.
78- **`redirect()` is an error type, `see_other()` is a response type.** A page returning
79 a view redirects with `Err(redirect(..).into())`.
80- **Static routes beat parameterised ones**, so `/auth/login` still wins over
81 `/{handle}`.
82- **Forms redirect on success and re-render on failure.** Redirecting after a validation
83 error discards what was typed and hides the reason.
84- **UI components reference theme tokens, never raw colours** — see `styles.css`. A
85 hardcoded colour follows neither a palette change nor the colour scheme. Registry
86 components are copied in by `topcoat ui add`, not depended on.
87
10ecb99docs: add CLAUDE.md1mo
88## Before saying it's done
89
90```bash
91cargo test
92cargo clippy --all-targets # expect zero warnings
93cargo fmt
94```
95
96Report counts accurately — don't state a test number without running it.
97
98Verify behaviour rather than asserting it. A passing unit test is not evidence that a
99page works; the session-cookie bug passed every test and failed silently in the
100browser. Say plainly what was checked and what wasn't.
101
102## Gotchas
103
104- **Topcoat 0.5 needs rustc ≥ 1.95.** On older toolchains `cargo add topcoat` silently
105 resolves to an empty `topcoat v0.0.0` placeholder instead of failing.
be4fac5docs: correct the Topcoat guidance in CLAUDE.md24d
106- **Read the vendored crate, not GitHub `main`.** Topcoat is very new (first release
107 2026-07-22) and its repository has already diverged from the released version. The
108 authority for the pinned version is
109 `~/.cargo/registry/src/*/topcoat-0.5.0/docs/` and the sibling `topcoat-*-0.5.0`
110 crates. Checking `main` is how `path_param` was got wrong.
10ecb99docs: add CLAUDE.md1mo
111- **`STEID_INSECURE_COOKIES=true`** is set in a gitignored `.env` for local dev,
112 because a `Secure` cookie is dropped silently over plain-HTTP localhost. Never
113 deploy it.
114- **The setup token is in memory only**, so every restart — including each `topcoat
115 dev` rebuild — mints a new one.
116- Don't leave background servers running; the user drives the app.
be4fac5docs: correct the Topcoat guidance in CLAUDE.md24d
117- **`topcoat asset bundle` after a manual build**, or the CSS served is stale.
118 `topcoat dev` does it for you.
119- In `sqlite.rs` and similar, **every implementation precedes the `mod tests` block**.
120 Appending to the end of the file otherwise lands inside the wrong block.