clone

nostr relays on demand at <name>.bind.ws: claim one with your key, pay in zaps past the free allowance

dependabot/github_actions/actions-9b61906d8b
bindws / STYLE.md
STYLE.md 7.4K rendered
1# Style23How this repository writes things down: prose, commits, comments, code and4tests. Every rule is drawn from what is already here, so this file describes5the repository rather than an opinion about it.67## The through-line89**Say what is true, not what was done or what to do.** Present indicative,10active, no hedging. This one habit produces most of the rest of this file.1112| Instead of | Write |13|---|---|14| Add a catalog table to the templates README | the README is a catalog, one line per template on when to choose it |15| You can switch features off | a relay's information document lists what its owner left on |16| Store the blob and return it | storeBlob puts bytes in R2 and a row in the table unless the hash is already there |1718The reason travels with the fact, in the same sentence, when the reason is not19obvious:2021> it is a generated module rather than a text-module rule in `wrangler.jsonc`22> because celld deploy refuses a config with `rules`2324> the celld suite runs on demand in its own workflow, since the runner's25> timing makes the sync test flaky on every push2627Sentences are short. Fragments are fine when they are deliberate. There is no28marketing voice, no filler, and no sentence whose only job is to introduce the29next one.3031## Commits3233The form is `<area>: <what is now true>`, lowercase after the colon.3435```36views: a view's setting is its trigger or off; the owner picks on write, hourly or daily for a stored view and on or off for presence, the scheduler and the write-time republish read it, and true or false still mean the default and off37kinds: every special event kind in one module, by NIP; 30078 had three names in three files, and the NIP-46 and report kinds lived in relay.ts38docs: main takes commits, not pull requests39```4041- **The area** is the module, folder or concern the change belongs to:42 `views`, `kinds`, `config`, `routes`, `console`, `docs`, `test`, `ci`,43 `host`, `rules`, `relay-templates`, `connection-templates`, `connections`,44 `scripts`, `tidy`.45- **No imperative mood and no Conventional Commits.** There is no `feat:`,46 `fix:`, `chore:`, and no "add", "update" or "refactor" opening a subject.47- **Length is not a constraint.** The median subject is 75 characters and the48 longest is 332. Clauses join with commas and semicolons. Say the whole49 thing.50- **The body stays empty.** One commit in 167 has one. If a subject needs a51 body, it is usually two commits.52- **Say why when why is not obvious**, in the same subject.53- **No attribution or co-author trailers.**5455Each commit typechecks on its own.5657## Documentation5859- `docs/` is numbered with two digits: `00` to `05` for users, `10` to `17`60 for developers, `20` and up for draft NIPs the repository implements ahead61 of upstream.62- Each file opens with frontmatter naming its `title` and its `audience`63 (`user` or `developer`).64- `README.md` is the front door. It links every doc with a one-line gloss of65 what that doc answers.66- Cross-link by relative path, using the target's own title as the link text.67- User docs use "you" and "your relay". Developer docs describe the system in68 the third person.69- A tutorial names an npm script, never `node` and a path. Every tool has an70 npm name, and the docs, the file headers and the workflow use it.71- Anything with more than about three parallel facts becomes a table.7273## Comments7475**Module headers** say what the module is, why it exists, and what its surface76looks like. A list of routes or a small diagram belongs here.7778```ts79// The relay card: something a name can be linked to from a profile.80//81// GET /card.json the facts: name, owner, members, rules, fuel, naddr, nprofile82// GET /card.svg an open graph sized picture with a QR of the naddr83//84// Cards are public and cached for five minutes. Unclaimed and leased relays85// get a smaller card that says so.86```8788**Function comments open with the function's own name**, then say what it89does and what it returns.9091```ts92// blobBlocked says whether a hash was removed by a moderator: a resolved93// report puts the sha256 on the banned id list, so it cannot come back94// through any door.95```9697A comment that restates its code is deleted. A comment that records a98constraint, a reason or a surprise is kept.99100## Code101102- TypeScript with explicit `.ts` in import paths.103- **A function returns `""` on success and the reason on failure**, rather104 than throwing or returning a bare boolean. Callers read the reason and pass105 it on.106- **Reasons carry a NIP-01 prefix.** The vocabulary in use, by frequency:107 `invalid:`, `restricted:`, `blocked:`, `error:`, `auth-required:`,108 `unsupported:`, `duplicate:`, `pow:`, and the bare `not found`. Do not109 invent a new prefix without a reason.110- **One registry per concern, read by everything that needs it.** `ROUTES`111 in `routes.ts`, `METHODS` in `manage.ts`, `VIEWS` in `views.ts`,112 `FEATURE_NAMES` in `settings.ts`, every special kind in `kinds.ts`, the113 presets in `presets.ts`. The failure this prevents is on the record: three114 lists in three files that had to agree.115- Small helpers are arrow consts. Long lines are fine.116- **Modules are extracted from `relay.ts` when it grows.** The gates, fuel,117 views, succession, invites, routes and the information document each left it118 for a module of their own.119- Generated files (`src/gen/`) are committed, and `npm run typecheck` fails120 when one is stale.121- Unused locals fail the typecheck.122123## The console124125Already written down in `docs/12-develop-extend.md`, repeated here because it126is style:127128- No middle dots.129- No purposeless subtext.130- Tables scroll inside their card on narrow screens.131- Decorative elements are not selectable.132- A multi-field form uses the labelled grid, not one row of inputs.133- The copy above a block is one sentence.134- New pages stay inside the shared shell in `ui.ts`.135136## Tests137138- `test/unit` is pure functions on node. `test/object` runs in workerd, one139 file per feature or module. `test/conformance` is black box, one file per140 NIP.141- **A test file is named after the module it exercises**, not the NIP. A NIP142 number names a file only where the feature has no other name (`nip05`,143 `nip11`, `nip66`).144- Test descriptions are full sentences saying what holds: "are all on by145 default, and setpolicy takes a map that survives export and import".146- `test/object/exposure.test.ts` walks every door as a stranger and as a147 signed-in non-member. **Every new path is added to its list.**148149## Typography150151ASCII punctuation only. The README, every doc and every source file contain152zero em-dashes, en-dashes, middle dots and smart quotes. This is measured, not153aspirational.154155- Never the middle dot `U+00B7`, in any file, for any purpose. Use a comma, a156 hyphen or a pipe.157- No em-dash or en-dash. Start a new sentence, or use a comma or a colon.158- Straight quotes and apostrophes.159160## Catalogs that must not drift161162Several lists are load-bearing, and some are enforced by the build. Adding a163file means adding its row.164165| Catalog | Where | Enforced |166|---|---|---|167| one row per template | `relay-templates/README.md` | yes, the build fails without it |168| one row per connection template | `connection-templates/README.md` | yes, the build fails without it |169| one link per doc | `README.md` | by review |170| one entry per generated file | `src/gen/` staleness check | yes, in `npm run typecheck` |171| every door | `test/object/exposure.test.ts` | by review |172| every special kind | `src/kinds.ts` | by review |173| the supported NIP list | `src/nip11.ts` | by review |