README: the voice rules
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s

The title is the only question; alternatives are bold statements
argued against each other; explain why input is needed, then hand
over the field; never assume the visitor's role - give the concern
its own page and let the question nav surface it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-08-12 23:29:53 +02:00
co-authored by Claude Sonnet 5
parent 309e3b43df
commit 176e2210a0
+23 -2
View File
@@ -118,14 +118,35 @@ entirely in this repo, in this order:
lint that gates every human push passes. Nothing merges on lint that gates every human push passes. Nothing merges on
autopilot. autopilot.
## Voice
The rules every page here follows:
- **The title is the only question.** A page asks one thing — its
`name`. Nothing below it asks anything.
- **Alternatives are bold statements**, argued against each other —
positions we'd like a visitor to get behind, in our voice, never
the visitor's presumed voice and never a question.
- **Explain why, then hand over the field.** Where input is needed,
the feature's name and description state the reason ("the reply is
personal — it needs an address"), and labels are nouns, not
questions.
- **Don't assume the visitor's role.** A concern that only speaks to
some visitors gets its own question page; the question nav (every
page's footer) surfaces all questions the current visitor qualifies
for, so nothing depends on front-page space. Post-submission pages
carry `followup: true` and only join the nav once the visitor holds
an answer chain.
## Schema quick reference ## Schema quick reference
The exact structs live in portal's `src/content.rs`; the shape: The exact structs live in portal's `src/content.rs`; the shape:
``` ```
Question id (doubles as the URL path), name, description, Question id (doubles as the URL path), name, description,
qualifies (Kanidm group gate), responsible {name, contact}, qualifies (Kanidm group gate), followup (nav-hidden
alternatives[] until the visitor carries a chain),
responsible {name, contact}, alternatives[]
Alternative name, description, action, consequence[label], Alternative name, description, action, consequence[label],
encouragements[], images[] (1 = banner, 2+ = card deck), encouragements[], images[] (1 = banner, 2+ = card deck),
record_as (bucket), self_transition {bucket, to, label}, record_as (bucket), self_transition {bucket, to, label},