Read CONTRIBUTING.md first. Reject the PR when any item below fails.
Every visitor-facing UI string that is not a documented exception must be
present in all locale catalogs (en, de, es, fil) in
src/lib/messages.ts.
- New or changed copy uses a catalog key in the same PR — no hard-coded UI
strings (except the documented exceptions in
CONTRIBUTING.md: legal body copy (English), handbook markdown bodies and handbook chapter-navigation labels (English), product tokens, switcher endonyms, stats body copy (English), document/social metadata (English)). - The four catalogs have the same key set, and every value is non-empty
after trim.
npm run typecheckfails on a missing key.src/__tests__/lib/messages.test.tsfails on a divergent key set or an empty/whitespace value. Both must pass. - Do not approve a PR that adds a key to English (or any one locale) without the matching keys in the other three.
Reject the PR when a pay sheet (or any Bitcoin payment UI) renders a QR
on a smartphone user-agent. Smartphones pay only via Wallet of Satoshi
deep links. Desktop shows QR and deep link. Detection is
isSmartphoneUserAgent, not viewport width. See CONTRIBUTING.md
“Payment QR vs deep links”.
These must be green on the PR. A missing or red gate is rejected:
npm run typechecknpm run lintnpm run handbook:checknpm run e2e:checknpm run screenshot:checknpm run test:coveragenpm run buildnpm run e2elocally (behavior + four visual combos). CI splits that intoE2E (behavior)plusVisual (desktop-light|desktop-dark|mobile-light|mobile-dark); all must be green.
Named exports, explicit return types, no any, no console.log, Tailwind
only, server components by default, TSDoc on exports, handbook / e2e /
screenshot baselines for new screenshot-gated screens/variants in the same PR
(handbook doc routes: ## Screen: prose and e2e page.goto only). New controls
follow the labeled vs icon-only table in docs/ui.md and CONTRIBUTING
Icon controls. A new control that ignores the table is rejected.