@tamsensedev/runner 0.10.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -5
- package/README.md +61 -50
- package/dist/cli.js +1188 -324
- package/dist/cli.js.map +1 -1
- package/dist/recorder.cjs +42 -6
- package/dist/recorder.cjs.map +1 -1
- package/library/.claude-plugin/plugin.json +5 -5
- package/library/THIRD_PARTY_NOTICES.md +123 -123
- package/library/agents/code-architect.md +67 -67
- package/library/agents/code-explorer.md +61 -61
- package/library/agents/code-reviewer.md +73 -73
- package/library/agents/code-simplifier.md +62 -62
- package/library/agents/design-critic.md +52 -52
- package/library/agents/second-opinion.md +64 -64
- package/library/agents/security-auditor.md +86 -86
- package/library/agents/silent-failure-hunter.md +70 -70
- package/library/agents/test-coverage-analyzer.md +78 -78
- package/library/agents/test-runner.md +48 -48
- package/library/agents/ui-tester.md +50 -50
- package/library/licenses/Apache-2.0.txt +202 -202
- package/library/skills/accessibility/SKILL.md +144 -144
- package/library/skills/accessibility/references/wcag-checks.md +168 -168
- package/library/skills/addressing-review-feedback/SKILL.md +109 -109
- package/library/skills/app-screens/SKILL.md +96 -96
- package/library/skills/app-screens/references/shell-kpis-charts.md +108 -108
- package/library/skills/app-screens/references/states-density-phone.md +54 -54
- package/library/skills/app-screens/references/tables-forms-settings.md +104 -104
- package/library/skills/avoiding-generic-ai-design/SKILL.md +92 -92
- package/library/skills/avoiding-generic-ai-design/references/tells.md +112 -112
- package/library/skills/clean-commits/SKILL.md +85 -85
- package/library/skills/design-review/SKILL.md +107 -107
- package/library/skills/design-review/references/critique-passes.md +101 -101
- package/library/skills/design-review/references/screenshot-procedure.md +121 -121
- package/library/skills/differential-security-review/LICENSE +427 -427
- package/library/skills/differential-security-review/SKILL.md +105 -105
- package/library/skills/differential-security-review/references/adversarial.md +115 -115
- package/library/skills/differential-security-review/references/methodology.md +145 -145
- package/library/skills/differential-security-review/references/patterns.md +108 -108
- package/library/skills/false-positive-check/LICENSE +427 -427
- package/library/skills/false-positive-check/SKILL.md +95 -95
- package/library/skills/false-positive-check/references/bug-class-verification.md +128 -128
- package/library/skills/false-positive-check/references/deep-verification.md +113 -113
- package/library/skills/false-positive-check/references/evidence-templates.md +93 -93
- package/library/skills/false-positive-check/references/false-positive-patterns.md +122 -122
- package/library/skills/false-positive-check/references/gate-reviews.md +36 -36
- package/library/skills/false-positive-check/references/standard-verification.md +80 -80
- package/library/skills/focused-implementation/SKILL.md +104 -104
- package/library/skills/implementation-plan/SKILL.md +66 -66
- package/library/skills/interface-design/SKILL.md +144 -144
- package/library/skills/interface-design/references/craft-defaults.md +130 -130
- package/library/skills/interface-design/references/new-direction.md +62 -62
- package/library/skills/interface-design/references/writing.md +52 -52
- package/library/skills/interface-polish/SKILL.md +103 -103
- package/library/skills/interface-polish/references/detail-rules.md +154 -154
- package/library/skills/interface-polish/references/worst-case-data.md +158 -158
- package/library/skills/motion-design/SKILL.md +106 -106
- package/library/skills/motion-design/references/recipes.md +243 -243
- package/library/skills/postgres-performance/SKILL.md +97 -97
- package/library/skills/postgres-performance/references/rules.md +265 -265
- package/library/skills/project-orientation/SKILL.md +77 -77
- package/library/skills/reviewing-changes/SKILL.md +183 -183
- package/library/skills/safe-database-changes/SKILL.md +111 -111
- package/library/skills/safe-database-changes/references/backfills.md +75 -75
- package/library/skills/safe-database-changes/references/migration-tools.md +69 -69
- package/library/skills/safe-database-changes/references/postgres-ddl.md +199 -199
- package/library/skills/security-review/SKILL.md +132 -132
- package/library/skills/security-review/references/checks-by-area.md +107 -107
- package/library/skills/security-review/references/do-not-report.md +86 -86
- package/library/skills/spec-writing/SKILL.md +144 -144
- package/library/skills/systematic-debugging/SKILL.md +130 -130
- package/library/skills/systematic-debugging/references/flaky-tests.md +51 -51
- package/library/skills/systematic-debugging/references/root-cause-tracing.md +55 -55
- package/library/skills/task-interview/SKILL.md +84 -84
- package/library/skills/test-driven-development/SKILL.md +116 -116
- package/library/skills/test-driven-development/references/writing-good-tests.md +85 -85
- package/library/skills/ui-testing/SKILL.md +102 -102
- package/library/skills/ui-testing/references/headless-check.md +295 -280
- package/library/skills/ui-testing/references/local-stand.md +51 -51
- package/library/skills/ui-testing/references/playwright-patterns.md +134 -134
- package/library/skills/ui-testing/references/recording.md +61 -58
- package/library/skills/verification-before-completion/SKILL.md +113 -113
- package/library/skills/web-interface-guidelines/SKILL.md +202 -202
- package/package.json +46 -46
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: verification-before-completion
|
|
3
|
-
description: Use right before saying work is done, fixed or passing, before the final commit, and before writing the final report or verdict: run the project's checks fresh, read their output, re-read the diff, check each acceptance criterion, and report only what the evidence shows.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Verification before completion
|
|
7
|
-
|
|
8
|
-
Evidence before claims. A claim about the state of the work ("tests pass", "bug fixed", "criterion met") is allowed only if you ran the command that proves it in this run, after your last change, and read its output.
|
|
9
|
-
|
|
10
|
-
```
|
|
11
|
-
NO COMPLETION CLAIM WITHOUT FRESH EVIDENCE
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## The gate, for every claim
|
|
15
|
-
|
|
16
|
-
1. **Identify** the command that proves the claim.
|
|
17
|
-
2. **Run** it in full, now, after your last edit.
|
|
18
|
-
3. **Read** the output: exit code, number of failures, warnings, skipped tests.
|
|
19
|
-
4. **Compare**: does the output actually support the claim?
|
|
20
|
-
5. **Only then** state it, with the evidence. If not, state the real status.
|
|
21
|
-
|
|
22
|
-
| Claim | Needs | Not enough |
|
|
23
|
-
|---|---|---|
|
|
24
|
-
| Tests pass | Test run with 0 failures, exit code 0 | An earlier run, "should pass" |
|
|
25
|
-
| Lint is clean | Linter output with 0 errors | Type check passing |
|
|
26
|
-
| Build works | Build command, exit code 0 | Lint and tests passing |
|
|
27
|
-
| Bug is fixed | The original reproduction now passes | "The code changed" |
|
|
28
|
-
| Regression test works | Seen failing without the fix, passing with it | Passing once |
|
|
29
|
-
| Criterion met | A specific check per criterion | All tests green |
|
|
30
|
-
| A helper agent did it | The diff and a check you ran yourself | The agent's summary |
|
|
31
|
-
|
|
32
|
-
## Steps
|
|
33
|
-
|
|
34
|
-
### 1. Run the project's checks
|
|
35
|
-
|
|
36
|
-
Use the commands found during `project-orientation` (CI order is a good default): build, type check, lint, tests. Run them in every repository you changed. The `test-runner` agent can run them and return a summary if the logs are long.
|
|
37
|
-
|
|
38
|
-
- Keep exit codes visible. When trimming output with a pipe, use `set -o pipefail` or check `$?` of the real command, so `| tail` does not turn a failure into success.
|
|
39
|
-
- Count results: "412 passed, 0 failed, 3 skipped", not "tests look fine".
|
|
40
|
-
- Compare with the baseline. A failure that was there before your change is pre-existing: report it, do not hide it, do not fix unrelated code for it. A new failure is yours: fix it and run again.
|
|
41
|
-
- Watch for new warnings, unhandled errors or skipped tests that your change introduced.
|
|
42
|
-
- If a check cannot run here, say which and why. Never report a check you did not run as passing.
|
|
43
|
-
|
|
44
|
-
### 2. Re-read the full diff
|
|
45
|
-
|
|
46
|
-
`git diff <base>...HEAD` plus `git diff` and `git status` for uncommitted work. Read it as a reviewer would:
|
|
47
|
-
|
|
48
|
-
- Every changed line is needed for the task.
|
|
49
|
-
- No debug output, `[DEBUG-` tags, commented-out code, stray files, temporary scripts.
|
|
50
|
-
- No secrets, tokens, personal data, `.env` files or local paths.
|
|
51
|
-
- Names, structure and style match the surrounding code and the project's rules.
|
|
52
|
-
- Nothing unrelated slipped in (formatting churn, lock file changes you did not intend).
|
|
53
|
-
|
|
54
|
-
### 3. Check each acceptance criterion
|
|
55
|
-
|
|
56
|
-
Go through the spec's criteria one by one. For each: met, partly met or not met, and how you know (test name, command output, file:line). "All tests pass" does not prove a criterion unless a test covers it.
|
|
57
|
-
|
|
58
|
-
### 4. Think about what you did not check
|
|
59
|
-
|
|
60
|
-
Other callers of changed functions, migrations and their order, configuration and environment variables, permissions, empty and error states, narrow screens for UI. Check the risky ones; list the rest under "Not verified".
|
|
61
|
-
|
|
62
|
-
### 5. Make sure the work is committed
|
|
63
|
-
|
|
64
|
-
In every repository you changed: `git status` is clean (or the leftovers are explained), and `git log --oneline <base>..HEAD` shows your commits. See `clean-commits`.
|
|
65
|
-
|
|
66
|
-
## The final report
|
|
67
|
-
|
|
68
|
-
The report is evidence, not an impression. Use this shape and fill it with real commands and real results:
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
Changes
|
|
72
|
-
- src/billing/tax.ts: default to the shop's country when the customer has none
|
|
73
|
-
- src/billing/tax.test.ts: test for customers without a country
|
|
74
|
-
|
|
75
|
-
Checks (run after the last change)
|
|
76
|
-
- pnpm typecheck: exit 0
|
|
77
|
-
- pnpm lint: exit 0, 0 warnings
|
|
78
|
-
- pnpm test -- --run: 213 passed, 1 failed (src/date.test.ts "formats in local time zone": failed in the baseline too, unrelated, not touched)
|
|
79
|
-
- new test seen failing before the fix: "expected 0.2, received NaN"
|
|
80
|
-
|
|
81
|
-
Acceptance criteria
|
|
82
|
-
1. Invoice is created for a customer without a country: met (tax.test.ts "no country")
|
|
83
|
-
2. VAT uses the shop's country: met (same test, rate 0.2 for DE shop)
|
|
84
|
-
|
|
85
|
-
Not verified
|
|
86
|
-
- Real payment provider (no sandbox credentials)
|
|
87
|
-
|
|
88
|
-
Assumptions
|
|
89
|
-
- Shop country comes from settings.shop.country; the spec does not name the field
|
|
90
|
-
|
|
91
|
-
Noticed, not changed
|
|
92
|
-
- src/billing/currency.ts rounds half-even, the rest of billing rounds half-up
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
In review and test steps the same rules apply to the report you pass with the verdict: every statement about the code is backed by something you ran or read, with the command or file:line.
|
|
96
|
-
|
|
97
|
-
## Red flags
|
|
98
|
-
|
|
99
|
-
- Words like "should", "probably", "seems to" about the state of the work.
|
|
100
|
-
- Saying "done" or "all good" before running anything.
|
|
101
|
-
- Relying on a run from before your last edit.
|
|
102
|
-
- Trusting a helper agent's "success" without looking at the diff.
|
|
103
|
-
- Running only the new test and calling the suite green.
|
|
104
|
-
- Leaving a failure out of the report because it was not yours.
|
|
105
|
-
|
|
106
|
-
| Excuse | Reality |
|
|
107
|
-
|---|---|
|
|
108
|
-
| "It should work now" | Run it. |
|
|
109
|
-
| "I'm confident" | Confidence is not evidence. |
|
|
110
|
-
| "The linter passed" | The linter does not compile or run the code. |
|
|
111
|
-
| "Partial check is enough" | It proves the part you checked, nothing more. Say which part. |
|
|
112
|
-
|
|
113
|
-
Sources: obra/superpowers (MIT, commit bb92a77) verification-before-completion and affaan-m/ECC (MIT, commit 30b6892) verification-loop. Changed: merged with our own checklist, report template added.
|
|
1
|
+
---
|
|
2
|
+
name: verification-before-completion
|
|
3
|
+
description: Use right before saying work is done, fixed or passing, before the final commit, and before writing the final report or verdict: run the project's checks fresh, read their output, re-read the diff, check each acceptance criterion, and report only what the evidence shows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Verification before completion
|
|
7
|
+
|
|
8
|
+
Evidence before claims. A claim about the state of the work ("tests pass", "bug fixed", "criterion met") is allowed only if you ran the command that proves it in this run, after your last change, and read its output.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
NO COMPLETION CLAIM WITHOUT FRESH EVIDENCE
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## The gate, for every claim
|
|
15
|
+
|
|
16
|
+
1. **Identify** the command that proves the claim.
|
|
17
|
+
2. **Run** it in full, now, after your last edit.
|
|
18
|
+
3. **Read** the output: exit code, number of failures, warnings, skipped tests.
|
|
19
|
+
4. **Compare**: does the output actually support the claim?
|
|
20
|
+
5. **Only then** state it, with the evidence. If not, state the real status.
|
|
21
|
+
|
|
22
|
+
| Claim | Needs | Not enough |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Tests pass | Test run with 0 failures, exit code 0 | An earlier run, "should pass" |
|
|
25
|
+
| Lint is clean | Linter output with 0 errors | Type check passing |
|
|
26
|
+
| Build works | Build command, exit code 0 | Lint and tests passing |
|
|
27
|
+
| Bug is fixed | The original reproduction now passes | "The code changed" |
|
|
28
|
+
| Regression test works | Seen failing without the fix, passing with it | Passing once |
|
|
29
|
+
| Criterion met | A specific check per criterion | All tests green |
|
|
30
|
+
| A helper agent did it | The diff and a check you ran yourself | The agent's summary |
|
|
31
|
+
|
|
32
|
+
## Steps
|
|
33
|
+
|
|
34
|
+
### 1. Run the project's checks
|
|
35
|
+
|
|
36
|
+
Use the commands found during `project-orientation` (CI order is a good default): build, type check, lint, tests. Run them in every repository you changed. The `test-runner` agent can run them and return a summary if the logs are long.
|
|
37
|
+
|
|
38
|
+
- Keep exit codes visible. When trimming output with a pipe, use `set -o pipefail` or check `$?` of the real command, so `| tail` does not turn a failure into success.
|
|
39
|
+
- Count results: "412 passed, 0 failed, 3 skipped", not "tests look fine".
|
|
40
|
+
- Compare with the baseline. A failure that was there before your change is pre-existing: report it, do not hide it, do not fix unrelated code for it. A new failure is yours: fix it and run again.
|
|
41
|
+
- Watch for new warnings, unhandled errors or skipped tests that your change introduced.
|
|
42
|
+
- If a check cannot run here, say which and why. Never report a check you did not run as passing.
|
|
43
|
+
|
|
44
|
+
### 2. Re-read the full diff
|
|
45
|
+
|
|
46
|
+
`git diff <base>...HEAD` plus `git diff` and `git status` for uncommitted work. Read it as a reviewer would:
|
|
47
|
+
|
|
48
|
+
- Every changed line is needed for the task.
|
|
49
|
+
- No debug output, `[DEBUG-` tags, commented-out code, stray files, temporary scripts.
|
|
50
|
+
- No secrets, tokens, personal data, `.env` files or local paths.
|
|
51
|
+
- Names, structure and style match the surrounding code and the project's rules.
|
|
52
|
+
- Nothing unrelated slipped in (formatting churn, lock file changes you did not intend).
|
|
53
|
+
|
|
54
|
+
### 3. Check each acceptance criterion
|
|
55
|
+
|
|
56
|
+
Go through the spec's criteria one by one. For each: met, partly met or not met, and how you know (test name, command output, file:line). "All tests pass" does not prove a criterion unless a test covers it.
|
|
57
|
+
|
|
58
|
+
### 4. Think about what you did not check
|
|
59
|
+
|
|
60
|
+
Other callers of changed functions, migrations and their order, configuration and environment variables, permissions, empty and error states, narrow screens for UI. Check the risky ones; list the rest under "Not verified".
|
|
61
|
+
|
|
62
|
+
### 5. Make sure the work is committed
|
|
63
|
+
|
|
64
|
+
In every repository you changed: `git status` is clean (or the leftovers are explained), and `git log --oneline <base>..HEAD` shows your commits. See `clean-commits`.
|
|
65
|
+
|
|
66
|
+
## The final report
|
|
67
|
+
|
|
68
|
+
The report is evidence, not an impression. Use this shape and fill it with real commands and real results:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Changes
|
|
72
|
+
- src/billing/tax.ts: default to the shop's country when the customer has none
|
|
73
|
+
- src/billing/tax.test.ts: test for customers without a country
|
|
74
|
+
|
|
75
|
+
Checks (run after the last change)
|
|
76
|
+
- pnpm typecheck: exit 0
|
|
77
|
+
- pnpm lint: exit 0, 0 warnings
|
|
78
|
+
- pnpm test -- --run: 213 passed, 1 failed (src/date.test.ts "formats in local time zone": failed in the baseline too, unrelated, not touched)
|
|
79
|
+
- new test seen failing before the fix: "expected 0.2, received NaN"
|
|
80
|
+
|
|
81
|
+
Acceptance criteria
|
|
82
|
+
1. Invoice is created for a customer without a country: met (tax.test.ts "no country")
|
|
83
|
+
2. VAT uses the shop's country: met (same test, rate 0.2 for DE shop)
|
|
84
|
+
|
|
85
|
+
Not verified
|
|
86
|
+
- Real payment provider (no sandbox credentials)
|
|
87
|
+
|
|
88
|
+
Assumptions
|
|
89
|
+
- Shop country comes from settings.shop.country; the spec does not name the field
|
|
90
|
+
|
|
91
|
+
Noticed, not changed
|
|
92
|
+
- src/billing/currency.ts rounds half-even, the rest of billing rounds half-up
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
In review and test steps the same rules apply to the report you pass with the verdict: every statement about the code is backed by something you ran or read, with the command or file:line.
|
|
96
|
+
|
|
97
|
+
## Red flags
|
|
98
|
+
|
|
99
|
+
- Words like "should", "probably", "seems to" about the state of the work.
|
|
100
|
+
- Saying "done" or "all good" before running anything.
|
|
101
|
+
- Relying on a run from before your last edit.
|
|
102
|
+
- Trusting a helper agent's "success" without looking at the diff.
|
|
103
|
+
- Running only the new test and calling the suite green.
|
|
104
|
+
- Leaving a failure out of the report because it was not yours.
|
|
105
|
+
|
|
106
|
+
| Excuse | Reality |
|
|
107
|
+
|---|---|
|
|
108
|
+
| "It should work now" | Run it. |
|
|
109
|
+
| "I'm confident" | Confidence is not evidence. |
|
|
110
|
+
| "The linter passed" | The linter does not compile or run the code. |
|
|
111
|
+
| "Partial check is enough" | It proves the part you checked, nothing more. Say which part. |
|
|
112
|
+
|
|
113
|
+
Sources: obra/superpowers (MIT, commit bb92a77) verification-before-completion and affaan-m/ECC (MIT, commit 30b6892) verification-loop. Changed: merged with our own checklist, report template added.
|
|
@@ -1,202 +1,202 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: web-interface-guidelines
|
|
3
|
-
description: Use when writing or reviewing web UI code for interaction and detail rules: accessibility basics, focus, forms, animation, typography details, long content, images, performance, URL state, touch, safe areas, dark mode, locale formatting, hover states and copy. A vendored checklist with file:line findings; project conventions override it.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Web interface guidelines
|
|
7
|
-
|
|
8
|
-
A terse checklist of details that make web interfaces work well, vendored from Vercel's Web Interface Guidelines so it never changes under a run and needs no network. Use it in two ways:
|
|
9
|
-
|
|
10
|
-
- **Code step:** after changing UI, check the files you touched against the rules and fix what applies.
|
|
11
|
-
- **Review step:** check the changed UI files of the branch and report findings in the format below. Do not edit product code.
|
|
12
|
-
|
|
13
|
-
## How these rules sit with the project
|
|
14
|
-
|
|
15
|
-
- The project's own conventions win: its CLAUDE.md / AGENTS.md, DESIGN.md, lint rules, component library and existing copy style.
|
|
16
|
-
- **Capitalization:** the original list asks for Title Case on headings and buttons. Our default is sentence case, unless the project already uses Title Case. Match the existing strings.
|
|
17
|
-
- **Placeholders ending with an ellipsis** and **`&` instead of "and"** are Vercel house style. Follow the project.
|
|
18
|
-
- Rules marked **[React]** use React or Next.js APIs. In other frameworks apply the idea with the framework's equivalent (Vue `v-model`, Svelte `bind:`, Angular forms, `<RouterLink>`, `<NuxtLink>`), or skip it if it has no equivalent.
|
|
19
|
-
- "Keyboard handlers" below means custom interactive elements. Native `<button>`, `<a href>` and form controls already handle the keyboard.
|
|
20
|
-
- Deeper accessibility work lives in the `accessibility` skill; visual design in `interface-design`; motion values in `motion-design`.
|
|
21
|
-
|
|
22
|
-
## Rules
|
|
23
|
-
|
|
24
|
-
### Accessibility
|
|
25
|
-
|
|
26
|
-
- Icon-only buttons need `aria-label`
|
|
27
|
-
- Form controls need `<label>` or `aria-label`
|
|
28
|
-
- Custom interactive elements need keyboard handlers (`onKeyDown`/`onKeyUp` or the framework's equivalent)
|
|
29
|
-
- `<button>` for actions, `<a>`/`<Link>` for navigation (not `<div onClick>`)
|
|
30
|
-
- Images need `alt` (or `alt=""` if decorative)
|
|
31
|
-
- Decorative icons need `aria-hidden="true"`
|
|
32
|
-
- Async updates (toasts, validation) need `aria-live="polite"`
|
|
33
|
-
- Use semantic HTML (`<button>`, `<a>`, `<label>`, `<table>`) before ARIA
|
|
34
|
-
- Headings hierarchical `<h1>` to `<h6>`; include skip link for main content
|
|
35
|
-
- `scroll-margin-top` on heading anchors
|
|
36
|
-
- Meaningful media needs captions, transcripts, or descriptions as applicable
|
|
37
|
-
- Media controls need keyboard support; decorative media needs assistive-tech hiding
|
|
38
|
-
|
|
39
|
-
### Focus states
|
|
40
|
-
|
|
41
|
-
- Interactive elements need visible focus: `focus-visible:ring-*` or equivalent
|
|
42
|
-
- Never `outline-none` / `outline: none` without focus replacement
|
|
43
|
-
- Use `:focus-visible` over `:focus` (avoid focus ring on click)
|
|
44
|
-
- Group focus with `:focus-within` for compound controls
|
|
45
|
-
- Sticky headers/footers/overlays must not cover the focused element
|
|
46
|
-
|
|
47
|
-
### Forms
|
|
48
|
-
|
|
49
|
-
- Inputs need `autocomplete` and meaningful `name`
|
|
50
|
-
- Use correct `type` (`email`, `tel`, `url`, `number`) and `inputmode`
|
|
51
|
-
- Never block paste (`onPaste` + `preventDefault`)
|
|
52
|
-
- Labels clickable (`htmlFor` [React] / `for`, or wrapping control)
|
|
53
|
-
- Disable spellcheck on emails, codes, usernames (`spellCheck={false}` [React] / `spellcheck="false"`)
|
|
54
|
-
- Checkboxes/radios: label + control share single hit target (no dead zones)
|
|
55
|
-
- Submit button stays enabled until request starts; spinner during request
|
|
56
|
-
- Errors inline next to fields; focus first error on submit
|
|
57
|
-
- Placeholders show an example pattern (Vercel style also ends them with `…`; follow the project)
|
|
58
|
-
- `autocomplete="off"` on non-auth fields to avoid password manager triggers
|
|
59
|
-
- Warn before navigation with unsaved changes (`beforeunload` or router guard)
|
|
60
|
-
|
|
61
|
-
### Animation
|
|
62
|
-
|
|
63
|
-
- Honor `prefers-reduced-motion` (provide reduced variant or disable)
|
|
64
|
-
- Animate `transform`/`opacity` only (compositor-friendly)
|
|
65
|
-
- Never `transition: all`; list properties explicitly
|
|
66
|
-
- Set correct `transform-origin`
|
|
67
|
-
- SVG: transforms on `<g>` wrapper with `transform-box: fill-box; transform-origin: center`
|
|
68
|
-
- Animations interruptible: respond to user input mid-animation
|
|
69
|
-
- Autoplay motion >5 seconds alongside other content needs pause, stop, or hide controls
|
|
70
|
-
- Muted decorative loops must stop under `prefers-reduced-motion`
|
|
71
|
-
|
|
72
|
-
### Typography
|
|
73
|
-
|
|
74
|
-
- `…` not `...`
|
|
75
|
-
- Curly quotes `“` `”` not straight `"`
|
|
76
|
-
- Non-breaking spaces: `10 MB`, `⌘ K`, brand names
|
|
77
|
-
- Loading states end with `…`: `"Loading…"`, `"Saving…"`
|
|
78
|
-
- `font-variant-numeric: tabular-nums` for number columns/comparisons
|
|
79
|
-
- Use `text-wrap: balance` or `text-pretty` on headings (prevents widows)
|
|
80
|
-
|
|
81
|
-
### Content handling
|
|
82
|
-
|
|
83
|
-
- Text containers handle long content: `truncate`, `line-clamp-*`, or `break-words`
|
|
84
|
-
- Flex children need `min-w-0` to allow text truncation
|
|
85
|
-
- Handle empty states: don't render broken UI for empty strings/arrays
|
|
86
|
-
- User-generated content: anticipate short, average, and very long inputs
|
|
87
|
-
|
|
88
|
-
### Images
|
|
89
|
-
|
|
90
|
-
- `<img>` needs explicit `width` and `height` (prevents CLS)
|
|
91
|
-
- Below-fold images: `loading="lazy"`
|
|
92
|
-
- Above-fold critical images: `priority` [Next.js] or `fetchpriority="high"`
|
|
93
|
-
|
|
94
|
-
### Performance
|
|
95
|
-
|
|
96
|
-
- Large lists (>50 items): virtualize (`virtua` [React], `content-visibility: auto`, or the framework's virtual list)
|
|
97
|
-
- No layout reads in render (`getBoundingClientRect`, `offsetHeight`, `offsetWidth`, `scrollTop`)
|
|
98
|
-
- Batch DOM reads/writes; avoid interleaving
|
|
99
|
-
- Prefer uncontrolled inputs; controlled inputs must be cheap per keystroke [React]
|
|
100
|
-
- Add `<link rel="preconnect">` for CDN/asset domains
|
|
101
|
-
- Critical fonts: `<link rel="preload" as="font">` with `font-display: swap`
|
|
102
|
-
- Prefer `<video autoplay muted loop playsinline>` over animated GIF; provide a still alternative
|
|
103
|
-
- Short non-essential loops: Safari H.264 MP4 `<picture>` source, `prefers-reduced-motion` media condition, and still fallback
|
|
104
|
-
|
|
105
|
-
### Navigation and state
|
|
106
|
-
|
|
107
|
-
- URL reflects state: filters, tabs, pagination, expanded panels in query params
|
|
108
|
-
- Links use `<a>`/`<Link>` (Cmd/Ctrl+click, middle-click support)
|
|
109
|
-
- Deep-link all stateful UI (if uses `useState`, consider URL sync via nuqs or similar) [React]
|
|
110
|
-
- Destructive actions need confirmation modal or undo window, never immediate
|
|
111
|
-
|
|
112
|
-
### Touch and interaction
|
|
113
|
-
|
|
114
|
-
- `touch-action: manipulation` (prevents double-tap zoom delay)
|
|
115
|
-
- `-webkit-tap-highlight-color` set intentionally
|
|
116
|
-
- `overscroll-behavior: contain` in modals/drawers/sheets
|
|
117
|
-
- Page rubber-band suppression: `overscroll-behavior: none` on `<html>` inside `@media (pointer: fine)`; keep coarse-pointer page defaults for pull-to-refresh. Test hybrid touch devices: `pointer` describes the primary input, and `none` also disables scroll chaining and native swipe navigation
|
|
118
|
-
- During drag: disable text selection, `inert` on dragged elements
|
|
119
|
-
- Drag/swipe/pinch/path gestures need tap/click and keyboard alternatives unless essential
|
|
120
|
-
- `autoFocus` sparingly: desktop only, single primary input; avoid on mobile
|
|
121
|
-
|
|
122
|
-
### Safe areas and layout
|
|
123
|
-
|
|
124
|
-
- Full-bleed layouts need `env(safe-area-inset-*)` for notches
|
|
125
|
-
- Avoid unwanted scrollbars: `overflow-x-hidden` on containers, fix content overflow
|
|
126
|
-
- Flex/grid over JS measurement for layout
|
|
127
|
-
|
|
128
|
-
### Dark mode and theming
|
|
129
|
-
|
|
130
|
-
- `color-scheme: dark` on `<html>` for dark themes (fixes scrollbar, inputs)
|
|
131
|
-
- `<meta name="theme-color">` matches page background
|
|
132
|
-
- Native `<select>`: explicit `background-color` and `color` (Windows dark mode)
|
|
133
|
-
|
|
134
|
-
### Locale and i18n
|
|
135
|
-
|
|
136
|
-
- Dates/times: use `Intl.DateTimeFormat` not hardcoded formats
|
|
137
|
-
- Numbers/currency: use `Intl.NumberFormat` not hardcoded formats
|
|
138
|
-
- Detect language via `Accept-Language` / `navigator.languages`, not IP
|
|
139
|
-
- Brand names, code tokens, identifiers: wrap with `translate="no"` to prevent garbled auto-translation
|
|
140
|
-
|
|
141
|
-
### Hydration safety [React, other SSR frameworks have the same class of issue]
|
|
142
|
-
|
|
143
|
-
- Inputs with `value` need `onChange` (or use `defaultValue` for uncontrolled)
|
|
144
|
-
- Date/time rendering: guard against hydration mismatch (server vs client)
|
|
145
|
-
- `suppressHydrationWarning` only where truly needed
|
|
146
|
-
|
|
147
|
-
### Hover and interactive states
|
|
148
|
-
|
|
149
|
-
- Buttons/links need `hover:` state (visual feedback)
|
|
150
|
-
- Interactive states increase contrast: hover/active/focus more prominent than rest
|
|
151
|
-
|
|
152
|
-
### Content and copy
|
|
153
|
-
|
|
154
|
-
- Active voice: "Install the CLI" not "The CLI will be installed"
|
|
155
|
-
- Sentence case for headings/buttons unless the project uses another style (Vercel's original: Title Case, Chicago style)
|
|
156
|
-
- Numerals for counts: "8 deployments" not "eight"
|
|
157
|
-
- Specific button labels: "Save API key" not "Continue"
|
|
158
|
-
- Error messages include fix/next step, not just problem
|
|
159
|
-
- Second person; avoid first person
|
|
160
|
-
- `&` over "and" where space-constrained (house style; follow the project)
|
|
161
|
-
|
|
162
|
-
### Anti-patterns (flag these)
|
|
163
|
-
|
|
164
|
-
- `user-scalable=no` or `maximum-scale=1` disabling zoom
|
|
165
|
-
- `onPaste` with `preventDefault`
|
|
166
|
-
- `transition: all`
|
|
167
|
-
- `outline-none` without focus-visible replacement
|
|
168
|
-
- Inline `onClick` navigation without `<a>`
|
|
169
|
-
- `<div>` or `<span>` with click handlers (should be `<button>`)
|
|
170
|
-
- Images without dimensions
|
|
171
|
-
- Large arrays `.map()` without virtualization
|
|
172
|
-
- Form inputs without labels
|
|
173
|
-
- Icon buttons without `aria-label`
|
|
174
|
-
- Hardcoded date/number formats (use `Intl.*`)
|
|
175
|
-
- `autoFocus` without clear justification
|
|
176
|
-
- Animated GIF when compressed video is suitable
|
|
177
|
-
- Gesture-only action without tap/click and keyboard alternative
|
|
178
|
-
|
|
179
|
-
## Output format
|
|
180
|
-
|
|
181
|
-
Group by file. Use `file:line`. Terse findings: the issue and the location; explain only when the fix is not obvious. No preamble.
|
|
182
|
-
|
|
183
|
-
```text
|
|
184
|
-
## src/Button.tsx
|
|
185
|
-
|
|
186
|
-
src/Button.tsx:42 - icon button missing aria-label
|
|
187
|
-
src/Button.tsx:55 - animation missing prefers-reduced-motion
|
|
188
|
-
src/Button.tsx:67 - transition: all -> list properties
|
|
189
|
-
|
|
190
|
-
## src/Modal.tsx
|
|
191
|
-
|
|
192
|
-
src/Modal.tsx:12 - missing overscroll-behavior: contain
|
|
193
|
-
src/Modal.tsx:34 - "..." -> "…"
|
|
194
|
-
|
|
195
|
-
## src/Card.tsx
|
|
196
|
-
|
|
197
|
-
pass
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Only report rules that apply to the changed code, and only where the project does not deliberately do otherwise.
|
|
201
|
-
|
|
202
|
-
Sources: rules text from vercel-labs/web-interface-guidelines command.md (MIT, Copyright (c) 2025 Vercel Labs; changed: vendored instead of fetched, React-specific rules marked, Title Case replaced by sentence case as the default, house-style rules marked, dashes and symbols normalised, intro and precedence notes added).
|
|
1
|
+
---
|
|
2
|
+
name: web-interface-guidelines
|
|
3
|
+
description: Use when writing or reviewing web UI code for interaction and detail rules: accessibility basics, focus, forms, animation, typography details, long content, images, performance, URL state, touch, safe areas, dark mode, locale formatting, hover states and copy. A vendored checklist with file:line findings; project conventions override it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web interface guidelines
|
|
7
|
+
|
|
8
|
+
A terse checklist of details that make web interfaces work well, vendored from Vercel's Web Interface Guidelines so it never changes under a run and needs no network. Use it in two ways:
|
|
9
|
+
|
|
10
|
+
- **Code step:** after changing UI, check the files you touched against the rules and fix what applies.
|
|
11
|
+
- **Review step:** check the changed UI files of the branch and report findings in the format below. Do not edit product code.
|
|
12
|
+
|
|
13
|
+
## How these rules sit with the project
|
|
14
|
+
|
|
15
|
+
- The project's own conventions win: its CLAUDE.md / AGENTS.md, DESIGN.md, lint rules, component library and existing copy style.
|
|
16
|
+
- **Capitalization:** the original list asks for Title Case on headings and buttons. Our default is sentence case, unless the project already uses Title Case. Match the existing strings.
|
|
17
|
+
- **Placeholders ending with an ellipsis** and **`&` instead of "and"** are Vercel house style. Follow the project.
|
|
18
|
+
- Rules marked **[React]** use React or Next.js APIs. In other frameworks apply the idea with the framework's equivalent (Vue `v-model`, Svelte `bind:`, Angular forms, `<RouterLink>`, `<NuxtLink>`), or skip it if it has no equivalent.
|
|
19
|
+
- "Keyboard handlers" below means custom interactive elements. Native `<button>`, `<a href>` and form controls already handle the keyboard.
|
|
20
|
+
- Deeper accessibility work lives in the `accessibility` skill; visual design in `interface-design`; motion values in `motion-design`.
|
|
21
|
+
|
|
22
|
+
## Rules
|
|
23
|
+
|
|
24
|
+
### Accessibility
|
|
25
|
+
|
|
26
|
+
- Icon-only buttons need `aria-label`
|
|
27
|
+
- Form controls need `<label>` or `aria-label`
|
|
28
|
+
- Custom interactive elements need keyboard handlers (`onKeyDown`/`onKeyUp` or the framework's equivalent)
|
|
29
|
+
- `<button>` for actions, `<a>`/`<Link>` for navigation (not `<div onClick>`)
|
|
30
|
+
- Images need `alt` (or `alt=""` if decorative)
|
|
31
|
+
- Decorative icons need `aria-hidden="true"`
|
|
32
|
+
- Async updates (toasts, validation) need `aria-live="polite"`
|
|
33
|
+
- Use semantic HTML (`<button>`, `<a>`, `<label>`, `<table>`) before ARIA
|
|
34
|
+
- Headings hierarchical `<h1>` to `<h6>`; include skip link for main content
|
|
35
|
+
- `scroll-margin-top` on heading anchors
|
|
36
|
+
- Meaningful media needs captions, transcripts, or descriptions as applicable
|
|
37
|
+
- Media controls need keyboard support; decorative media needs assistive-tech hiding
|
|
38
|
+
|
|
39
|
+
### Focus states
|
|
40
|
+
|
|
41
|
+
- Interactive elements need visible focus: `focus-visible:ring-*` or equivalent
|
|
42
|
+
- Never `outline-none` / `outline: none` without focus replacement
|
|
43
|
+
- Use `:focus-visible` over `:focus` (avoid focus ring on click)
|
|
44
|
+
- Group focus with `:focus-within` for compound controls
|
|
45
|
+
- Sticky headers/footers/overlays must not cover the focused element
|
|
46
|
+
|
|
47
|
+
### Forms
|
|
48
|
+
|
|
49
|
+
- Inputs need `autocomplete` and meaningful `name`
|
|
50
|
+
- Use correct `type` (`email`, `tel`, `url`, `number`) and `inputmode`
|
|
51
|
+
- Never block paste (`onPaste` + `preventDefault`)
|
|
52
|
+
- Labels clickable (`htmlFor` [React] / `for`, or wrapping control)
|
|
53
|
+
- Disable spellcheck on emails, codes, usernames (`spellCheck={false}` [React] / `spellcheck="false"`)
|
|
54
|
+
- Checkboxes/radios: label + control share single hit target (no dead zones)
|
|
55
|
+
- Submit button stays enabled until request starts; spinner during request
|
|
56
|
+
- Errors inline next to fields; focus first error on submit
|
|
57
|
+
- Placeholders show an example pattern (Vercel style also ends them with `…`; follow the project)
|
|
58
|
+
- `autocomplete="off"` on non-auth fields to avoid password manager triggers
|
|
59
|
+
- Warn before navigation with unsaved changes (`beforeunload` or router guard)
|
|
60
|
+
|
|
61
|
+
### Animation
|
|
62
|
+
|
|
63
|
+
- Honor `prefers-reduced-motion` (provide reduced variant or disable)
|
|
64
|
+
- Animate `transform`/`opacity` only (compositor-friendly)
|
|
65
|
+
- Never `transition: all`; list properties explicitly
|
|
66
|
+
- Set correct `transform-origin`
|
|
67
|
+
- SVG: transforms on `<g>` wrapper with `transform-box: fill-box; transform-origin: center`
|
|
68
|
+
- Animations interruptible: respond to user input mid-animation
|
|
69
|
+
- Autoplay motion >5 seconds alongside other content needs pause, stop, or hide controls
|
|
70
|
+
- Muted decorative loops must stop under `prefers-reduced-motion`
|
|
71
|
+
|
|
72
|
+
### Typography
|
|
73
|
+
|
|
74
|
+
- `…` not `...`
|
|
75
|
+
- Curly quotes `“` `”` not straight `"`
|
|
76
|
+
- Non-breaking spaces: `10 MB`, `⌘ K`, brand names
|
|
77
|
+
- Loading states end with `…`: `"Loading…"`, `"Saving…"`
|
|
78
|
+
- `font-variant-numeric: tabular-nums` for number columns/comparisons
|
|
79
|
+
- Use `text-wrap: balance` or `text-pretty` on headings (prevents widows)
|
|
80
|
+
|
|
81
|
+
### Content handling
|
|
82
|
+
|
|
83
|
+
- Text containers handle long content: `truncate`, `line-clamp-*`, or `break-words`
|
|
84
|
+
- Flex children need `min-w-0` to allow text truncation
|
|
85
|
+
- Handle empty states: don't render broken UI for empty strings/arrays
|
|
86
|
+
- User-generated content: anticipate short, average, and very long inputs
|
|
87
|
+
|
|
88
|
+
### Images
|
|
89
|
+
|
|
90
|
+
- `<img>` needs explicit `width` and `height` (prevents CLS)
|
|
91
|
+
- Below-fold images: `loading="lazy"`
|
|
92
|
+
- Above-fold critical images: `priority` [Next.js] or `fetchpriority="high"`
|
|
93
|
+
|
|
94
|
+
### Performance
|
|
95
|
+
|
|
96
|
+
- Large lists (>50 items): virtualize (`virtua` [React], `content-visibility: auto`, or the framework's virtual list)
|
|
97
|
+
- No layout reads in render (`getBoundingClientRect`, `offsetHeight`, `offsetWidth`, `scrollTop`)
|
|
98
|
+
- Batch DOM reads/writes; avoid interleaving
|
|
99
|
+
- Prefer uncontrolled inputs; controlled inputs must be cheap per keystroke [React]
|
|
100
|
+
- Add `<link rel="preconnect">` for CDN/asset domains
|
|
101
|
+
- Critical fonts: `<link rel="preload" as="font">` with `font-display: swap`
|
|
102
|
+
- Prefer `<video autoplay muted loop playsinline>` over animated GIF; provide a still alternative
|
|
103
|
+
- Short non-essential loops: Safari H.264 MP4 `<picture>` source, `prefers-reduced-motion` media condition, and still fallback
|
|
104
|
+
|
|
105
|
+
### Navigation and state
|
|
106
|
+
|
|
107
|
+
- URL reflects state: filters, tabs, pagination, expanded panels in query params
|
|
108
|
+
- Links use `<a>`/`<Link>` (Cmd/Ctrl+click, middle-click support)
|
|
109
|
+
- Deep-link all stateful UI (if uses `useState`, consider URL sync via nuqs or similar) [React]
|
|
110
|
+
- Destructive actions need confirmation modal or undo window, never immediate
|
|
111
|
+
|
|
112
|
+
### Touch and interaction
|
|
113
|
+
|
|
114
|
+
- `touch-action: manipulation` (prevents double-tap zoom delay)
|
|
115
|
+
- `-webkit-tap-highlight-color` set intentionally
|
|
116
|
+
- `overscroll-behavior: contain` in modals/drawers/sheets
|
|
117
|
+
- Page rubber-band suppression: `overscroll-behavior: none` on `<html>` inside `@media (pointer: fine)`; keep coarse-pointer page defaults for pull-to-refresh. Test hybrid touch devices: `pointer` describes the primary input, and `none` also disables scroll chaining and native swipe navigation
|
|
118
|
+
- During drag: disable text selection, `inert` on dragged elements
|
|
119
|
+
- Drag/swipe/pinch/path gestures need tap/click and keyboard alternatives unless essential
|
|
120
|
+
- `autoFocus` sparingly: desktop only, single primary input; avoid on mobile
|
|
121
|
+
|
|
122
|
+
### Safe areas and layout
|
|
123
|
+
|
|
124
|
+
- Full-bleed layouts need `env(safe-area-inset-*)` for notches
|
|
125
|
+
- Avoid unwanted scrollbars: `overflow-x-hidden` on containers, fix content overflow
|
|
126
|
+
- Flex/grid over JS measurement for layout
|
|
127
|
+
|
|
128
|
+
### Dark mode and theming
|
|
129
|
+
|
|
130
|
+
- `color-scheme: dark` on `<html>` for dark themes (fixes scrollbar, inputs)
|
|
131
|
+
- `<meta name="theme-color">` matches page background
|
|
132
|
+
- Native `<select>`: explicit `background-color` and `color` (Windows dark mode)
|
|
133
|
+
|
|
134
|
+
### Locale and i18n
|
|
135
|
+
|
|
136
|
+
- Dates/times: use `Intl.DateTimeFormat` not hardcoded formats
|
|
137
|
+
- Numbers/currency: use `Intl.NumberFormat` not hardcoded formats
|
|
138
|
+
- Detect language via `Accept-Language` / `navigator.languages`, not IP
|
|
139
|
+
- Brand names, code tokens, identifiers: wrap with `translate="no"` to prevent garbled auto-translation
|
|
140
|
+
|
|
141
|
+
### Hydration safety [React, other SSR frameworks have the same class of issue]
|
|
142
|
+
|
|
143
|
+
- Inputs with `value` need `onChange` (or use `defaultValue` for uncontrolled)
|
|
144
|
+
- Date/time rendering: guard against hydration mismatch (server vs client)
|
|
145
|
+
- `suppressHydrationWarning` only where truly needed
|
|
146
|
+
|
|
147
|
+
### Hover and interactive states
|
|
148
|
+
|
|
149
|
+
- Buttons/links need `hover:` state (visual feedback)
|
|
150
|
+
- Interactive states increase contrast: hover/active/focus more prominent than rest
|
|
151
|
+
|
|
152
|
+
### Content and copy
|
|
153
|
+
|
|
154
|
+
- Active voice: "Install the CLI" not "The CLI will be installed"
|
|
155
|
+
- Sentence case for headings/buttons unless the project uses another style (Vercel's original: Title Case, Chicago style)
|
|
156
|
+
- Numerals for counts: "8 deployments" not "eight"
|
|
157
|
+
- Specific button labels: "Save API key" not "Continue"
|
|
158
|
+
- Error messages include fix/next step, not just problem
|
|
159
|
+
- Second person; avoid first person
|
|
160
|
+
- `&` over "and" where space-constrained (house style; follow the project)
|
|
161
|
+
|
|
162
|
+
### Anti-patterns (flag these)
|
|
163
|
+
|
|
164
|
+
- `user-scalable=no` or `maximum-scale=1` disabling zoom
|
|
165
|
+
- `onPaste` with `preventDefault`
|
|
166
|
+
- `transition: all`
|
|
167
|
+
- `outline-none` without focus-visible replacement
|
|
168
|
+
- Inline `onClick` navigation without `<a>`
|
|
169
|
+
- `<div>` or `<span>` with click handlers (should be `<button>`)
|
|
170
|
+
- Images without dimensions
|
|
171
|
+
- Large arrays `.map()` without virtualization
|
|
172
|
+
- Form inputs without labels
|
|
173
|
+
- Icon buttons without `aria-label`
|
|
174
|
+
- Hardcoded date/number formats (use `Intl.*`)
|
|
175
|
+
- `autoFocus` without clear justification
|
|
176
|
+
- Animated GIF when compressed video is suitable
|
|
177
|
+
- Gesture-only action without tap/click and keyboard alternative
|
|
178
|
+
|
|
179
|
+
## Output format
|
|
180
|
+
|
|
181
|
+
Group by file. Use `file:line`. Terse findings: the issue and the location; explain only when the fix is not obvious. No preamble.
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
## src/Button.tsx
|
|
185
|
+
|
|
186
|
+
src/Button.tsx:42 - icon button missing aria-label
|
|
187
|
+
src/Button.tsx:55 - animation missing prefers-reduced-motion
|
|
188
|
+
src/Button.tsx:67 - transition: all -> list properties
|
|
189
|
+
|
|
190
|
+
## src/Modal.tsx
|
|
191
|
+
|
|
192
|
+
src/Modal.tsx:12 - missing overscroll-behavior: contain
|
|
193
|
+
src/Modal.tsx:34 - "..." -> "…"
|
|
194
|
+
|
|
195
|
+
## src/Card.tsx
|
|
196
|
+
|
|
197
|
+
pass
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Only report rules that apply to the changed code, and only where the project does not deliberately do otherwise.
|
|
201
|
+
|
|
202
|
+
Sources: rules text from vercel-labs/web-interface-guidelines command.md (MIT, Copyright (c) 2025 Vercel Labs; changed: vendored instead of fetched, React-specific rules marked, Title Case replaced by sentence case as the default, house-style rules marked, dashes and symbols normalised, intro and precedence notes added).
|