@jgamaraalv/ts-dev-kit 1.0.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.
Files changed (117) hide show
  1. package/.claude-plugin/marketplace.json +24 -0
  2. package/.claude-plugin/plugin.json +24 -0
  3. package/CHANGELOG.md +24 -0
  4. package/LICENSE +21 -0
  5. package/README.md +128 -0
  6. package/agents/accessibility-pro.md +139 -0
  7. package/agents/api-builder.md +110 -0
  8. package/agents/code-reviewer.md +190 -0
  9. package/agents/database-expert.md +138 -0
  10. package/agents/debugger.md +241 -0
  11. package/agents/docker-expert.md +51 -0
  12. package/agents/multi-agent-coordinator.md +378 -0
  13. package/agents/nextjs-expert.md +136 -0
  14. package/agents/performance-engineer.md +138 -0
  15. package/agents/playwright-expert.md +126 -0
  16. package/agents/react-specialist.md +97 -0
  17. package/agents/security-scanner.md +105 -0
  18. package/agents/test-generator.md +221 -0
  19. package/agents/typescript-pro.md +253 -0
  20. package/agents/ux-optimizer.md +93 -0
  21. package/docs/rules/orchestration.md.template +126 -0
  22. package/package.json +28 -0
  23. package/skills/bullmq/SKILL.md +225 -0
  24. package/skills/bullmq/references/flows-and-schedulers.md +186 -0
  25. package/skills/bullmq/references/job-types-and-options.md +163 -0
  26. package/skills/bullmq/references/patterns.md +273 -0
  27. package/skills/bullmq/references/production.md +308 -0
  28. package/skills/composition-patterns/SKILL.md +58 -0
  29. package/skills/composition-patterns/references/architecture-avoid-boolean-props.md +87 -0
  30. package/skills/composition-patterns/references/architecture-compound-components.md +107 -0
  31. package/skills/composition-patterns/references/patterns-children-over-render-props.md +77 -0
  32. package/skills/composition-patterns/references/patterns-explicit-variants.md +87 -0
  33. package/skills/composition-patterns/references/react19-no-forwardref.md +37 -0
  34. package/skills/composition-patterns/references/state-context-interface.md +194 -0
  35. package/skills/composition-patterns/references/state-decouple-implementation.md +96 -0
  36. package/skills/composition-patterns/references/state-lift-state.md +126 -0
  37. package/skills/conventional-commits/SKILL.md +148 -0
  38. package/skills/docker/SKILL.md +55 -0
  39. package/skills/docker/references/compose-configs.md +95 -0
  40. package/skills/docker/references/monorepo-dockerfile.md +111 -0
  41. package/skills/drizzle-pg/SKILL.md +202 -0
  42. package/skills/drizzle-pg/references/advanced.md +299 -0
  43. package/skills/drizzle-pg/references/migrations.md +214 -0
  44. package/skills/drizzle-pg/references/queries.md +321 -0
  45. package/skills/drizzle-pg/references/relations.md +272 -0
  46. package/skills/drizzle-pg/references/schema-pg.md +256 -0
  47. package/skills/drizzle-pg/references/sql-operator.md +215 -0
  48. package/skills/fastify-best-practices/SKILL.md +143 -0
  49. package/skills/fastify-best-practices/references/hooks-and-lifecycle.md +122 -0
  50. package/skills/fastify-best-practices/references/plugins-and-encapsulation.md +137 -0
  51. package/skills/fastify-best-practices/references/request-reply-errors.md +189 -0
  52. package/skills/fastify-best-practices/references/routes-and-handlers.md +134 -0
  53. package/skills/fastify-best-practices/references/server-and-options.md +127 -0
  54. package/skills/fastify-best-practices/references/typescript-and-logging.md +223 -0
  55. package/skills/fastify-best-practices/references/validation-and-serialization.md +190 -0
  56. package/skills/ioredis/SKILL.md +51 -0
  57. package/skills/ioredis/references/advanced-patterns.md +312 -0
  58. package/skills/ioredis/references/cluster-sentinel.md +280 -0
  59. package/skills/ioredis/references/connection-options.md +187 -0
  60. package/skills/ioredis/references/core-api.md +179 -0
  61. package/skills/nextjs-best-practices/SKILL.md +194 -0
  62. package/skills/nextjs-best-practices/references/async-patterns.md +84 -0
  63. package/skills/nextjs-best-practices/references/bundling.md +192 -0
  64. package/skills/nextjs-best-practices/references/data-patterns.md +310 -0
  65. package/skills/nextjs-best-practices/references/debug-tricks.md +127 -0
  66. package/skills/nextjs-best-practices/references/directives.md +74 -0
  67. package/skills/nextjs-best-practices/references/error-handling.md +237 -0
  68. package/skills/nextjs-best-practices/references/file-conventions.md +152 -0
  69. package/skills/nextjs-best-practices/references/font.md +175 -0
  70. package/skills/nextjs-best-practices/references/functions.md +116 -0
  71. package/skills/nextjs-best-practices/references/hydration-error.md +86 -0
  72. package/skills/nextjs-best-practices/references/image.md +184 -0
  73. package/skills/nextjs-best-practices/references/metadata.md +305 -0
  74. package/skills/nextjs-best-practices/references/parallel-routes.md +299 -0
  75. package/skills/nextjs-best-practices/references/route-handlers.md +154 -0
  76. package/skills/nextjs-best-practices/references/rsc-boundaries.md +168 -0
  77. package/skills/nextjs-best-practices/references/runtime-selection.md +40 -0
  78. package/skills/nextjs-best-practices/references/scripts.md +148 -0
  79. package/skills/nextjs-best-practices/references/self-hosting.md +210 -0
  80. package/skills/nextjs-best-practices/references/suspense-boundaries.md +67 -0
  81. package/skills/owasp-security-review/SKILL.md +98 -0
  82. package/skills/owasp-security-review/references/a01-broken-access-control.md +78 -0
  83. package/skills/owasp-security-review/references/a02-security-misconfiguration.md +81 -0
  84. package/skills/owasp-security-review/references/a03-supply-chain-failures.md +65 -0
  85. package/skills/owasp-security-review/references/a04-cryptographic-failures.md +82 -0
  86. package/skills/owasp-security-review/references/a05-injection.md +106 -0
  87. package/skills/owasp-security-review/references/a06-insecure-design.md +76 -0
  88. package/skills/owasp-security-review/references/a07-authentication-failures.md +83 -0
  89. package/skills/owasp-security-review/references/a08-integrity-failures.md +72 -0
  90. package/skills/owasp-security-review/references/a09-logging-alerting-failures.md +76 -0
  91. package/skills/owasp-security-review/references/a10-exceptional-conditions.md +131 -0
  92. package/skills/postgresql/SKILL.md +50 -0
  93. package/skills/postgresql/references/ddl-schema.md +300 -0
  94. package/skills/postgresql/references/indexes.md +257 -0
  95. package/skills/postgresql/references/jsonb.md +261 -0
  96. package/skills/postgresql/references/performance.md +291 -0
  97. package/skills/postgresql/references/psql-cli.md +153 -0
  98. package/skills/postgresql/references/queries.md +287 -0
  99. package/skills/postgresql/references/transactions.md +280 -0
  100. package/skills/react-best-practices/SKILL.md +110 -0
  101. package/skills/react-best-practices/references/advanced-patterns.md +91 -0
  102. package/skills/react-best-practices/references/async-patterns.md +233 -0
  103. package/skills/react-best-practices/references/bundle-optimization.md +201 -0
  104. package/skills/react-best-practices/references/client-patterns.md +178 -0
  105. package/skills/react-best-practices/references/js-performance.md +210 -0
  106. package/skills/react-best-practices/references/rendering-performance.md +209 -0
  107. package/skills/react-best-practices/references/rerender-optimization.md +316 -0
  108. package/skills/react-best-practices/references/server-performance.md +274 -0
  109. package/skills/service-worker/SKILL.md +195 -0
  110. package/skills/service-worker/references/api-reference.md +114 -0
  111. package/skills/service-worker/references/caching-strategies.md +202 -0
  112. package/skills/service-worker/references/push-and-sync.md +261 -0
  113. package/skills/typescript-conventions/SKILL.md +51 -0
  114. package/skills/ui-ux-guidelines/SKILL.md +105 -0
  115. package/skills/ui-ux-guidelines/references/accessibility-and-interaction.md +74 -0
  116. package/skills/ui-ux-guidelines/references/forms-content-checklist.md +126 -0
  117. package/skills/ui-ux-guidelines/references/layout-typography-animation.md +95 -0
@@ -0,0 +1,261 @@
1
+ # Push Notifications & Background Sync
2
+
3
+ ## Table of Contents
4
+
5
+ - [Push Notifications](#push-notifications)
6
+ - [Subscribe from the Page](#subscribe-from-the-page)
7
+ - [Send Push from Server](#send-push-from-server)
8
+ - [Handle Push in SW](#handle-push-in-sw)
9
+ - [Handle Notification Click](#handle-notification-click)
10
+ - [VAPID Keys](#vapid-keys)
11
+ - [Background Sync](#background-sync)
12
+ - [Register Sync from Page](#register-sync-from-page)
13
+ - [Handle Sync in SW](#handle-sync-in-sw)
14
+ - [Retry Pattern](#retry-pattern)
15
+ - [Periodic Background Sync](#periodic-background-sync)
16
+
17
+ ## Push Notifications
18
+
19
+ ### Subscribe from the Page
20
+
21
+ ```js
22
+ async function subscribeToPush() {
23
+ const reg = await navigator.serviceWorker.ready;
24
+
25
+ // Check permission
26
+ const permission = await Notification.requestPermission();
27
+ if (permission !== "granted") return null;
28
+
29
+ // Subscribe with VAPID public key
30
+ const subscription = await reg.pushManager.subscribe({
31
+ userVisibleOnly: true, // Required: must show a notification for each push
32
+ applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
33
+ });
34
+
35
+ // Send subscription to your server
36
+ await fetch("/api/push/subscribe", {
37
+ method: "POST",
38
+ headers: { "Content-Type": "application/json" },
39
+ body: JSON.stringify(subscription),
40
+ });
41
+
42
+ return subscription;
43
+ }
44
+
45
+ // Helper: convert VAPID key
46
+ function urlBase64ToUint8Array(base64String) {
47
+ const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
48
+ const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
49
+ const raw = atob(base64);
50
+ return Uint8Array.from([...raw].map((char) => char.charCodeAt(0)));
51
+ }
52
+ ```
53
+
54
+ ### Send Push from Server
55
+
56
+ Using the `web-push` npm package (Node.js):
57
+
58
+ ```js
59
+ import webpush from "web-push";
60
+
61
+ webpush.setVapidDetails(
62
+ "mailto:admin@example.com",
63
+ process.env.VAPID_PUBLIC_KEY,
64
+ process.env.VAPID_PRIVATE_KEY,
65
+ );
66
+
67
+ // subscription = the PushSubscription JSON from the client
68
+ await webpush.sendNotification(
69
+ subscription,
70
+ JSON.stringify({
71
+ title: "New message",
72
+ body: "You have a new notification",
73
+ icon: "/icon-192.png",
74
+ url: "/messages",
75
+ }),
76
+ );
77
+ ```
78
+
79
+ Generate VAPID keys: `npx web-push generate-vapid-keys`
80
+
81
+ ### Handle Push in SW
82
+
83
+ ```js
84
+ self.addEventListener("push", (event) => {
85
+ const data = event.data?.json() ?? {};
86
+ const { title = "Notification", body, icon, url } = data;
87
+
88
+ event.waitUntil(
89
+ self.registration.showNotification(title, {
90
+ body,
91
+ icon: icon || "/icon-192.png",
92
+ badge: "/badge-72.png",
93
+ data: { url }, // Pass URL to notificationclick handler
94
+ vibrate: [100, 50, 100],
95
+ actions: [
96
+ { action: "open", title: "Open" },
97
+ { action: "dismiss", title: "Dismiss" },
98
+ ],
99
+ }),
100
+ );
101
+ });
102
+ ```
103
+
104
+ ### Handle Notification Click
105
+
106
+ ```js
107
+ self.addEventListener("notificationclick", (event) => {
108
+ event.notification.close();
109
+
110
+ if (event.action === "dismiss") return;
111
+
112
+ const url = event.notification.data?.url || "/";
113
+
114
+ event.waitUntil(
115
+ self.clients.matchAll({ type: "window", includeUncontrolled: true }).then((clients) => {
116
+ // Focus existing tab if one matches
117
+ for (const client of clients) {
118
+ if (client.url === url && "focus" in client) {
119
+ return client.focus();
120
+ }
121
+ }
122
+ // Otherwise open a new window
123
+ return self.clients.openWindow(url);
124
+ }),
125
+ );
126
+ });
127
+
128
+ self.addEventListener("notificationclose", (event) => {
129
+ // Track dismissals (analytics)
130
+ });
131
+ ```
132
+
133
+ ### VAPID Keys
134
+
135
+ VAPID (Voluntary Application Server Identification) authenticates your server to the push service.
136
+
137
+ ```bash
138
+ # Generate keys (do this once, store securely)
139
+ npx web-push generate-vapid-keys
140
+ ```
141
+
142
+ Output:
143
+
144
+ ```
145
+ Public Key: BNbxG... (use in client subscribe call)
146
+ Private Key: 3KW9e... (use on server only, keep secret)
147
+ ```
148
+
149
+ Store as environment variables:
150
+
151
+ ```
152
+ VAPID_PUBLIC_KEY=BNbxG...
153
+ VAPID_PRIVATE_KEY=3KW9e...
154
+ ```
155
+
156
+ ## Background Sync
157
+
158
+ Defers actions until the user has connectivity. Chromium-only (Chrome, Edge).
159
+
160
+ > **Safari/iOS caveat:** Background Sync is not supported in Safari/iOS. Use periodic polling as fallback.
161
+
162
+ ### Register Sync from Page
163
+
164
+ ```js
165
+ async function saveForSync(data) {
166
+ // Store the pending action in IndexedDB
167
+ await saveToIndexedDB("pending-actions", data);
168
+
169
+ // Register a sync
170
+ const reg = await navigator.serviceWorker.ready;
171
+ await reg.sync.register("sync-pending-actions");
172
+ }
173
+ ```
174
+
175
+ ### Handle Sync in SW
176
+
177
+ ```js
178
+ self.addEventListener("sync", (event) => {
179
+ if (event.tag === "sync-pending-actions") {
180
+ event.waitUntil(processPendingActions());
181
+ }
182
+ });
183
+
184
+ async function processPendingActions() {
185
+ const actions = await getFromIndexedDB("pending-actions");
186
+
187
+ for (const action of actions) {
188
+ try {
189
+ await fetch("/api/action", {
190
+ method: "POST",
191
+ headers: { "Content-Type": "application/json" },
192
+ body: JSON.stringify(action),
193
+ });
194
+ await removeFromIndexedDB("pending-actions", action.id);
195
+ } catch {
196
+ // Will retry on next sync event
197
+ throw new Error("Sync failed, will retry");
198
+ }
199
+ }
200
+ }
201
+ ```
202
+
203
+ ### Retry Pattern
204
+
205
+ The browser retries `sync` events with exponential backoff when the promise passed to `waitUntil` rejects. The event includes `event.lastChance` — if `true`, this is the final retry:
206
+
207
+ ```js
208
+ self.addEventListener("sync", (event) => {
209
+ if (event.tag === "sync-form-data") {
210
+ event.waitUntil(
211
+ submitFormData().catch((err) => {
212
+ if (event.lastChance) {
213
+ // Final attempt failed — notify user via notification
214
+ return self.registration.showNotification("Sync failed", {
215
+ body: "Your data could not be submitted. Please try again.",
216
+ });
217
+ }
218
+ throw err; // Reject to trigger retry
219
+ }),
220
+ );
221
+ }
222
+ });
223
+ ```
224
+
225
+ ## Periodic Background Sync
226
+
227
+ Runs at periodic intervals even when the page is closed. Chromium-only, requires site engagement score.
228
+
229
+ ```js
230
+ // Register from page
231
+ const reg = await navigator.serviceWorker.ready;
232
+ const status = await navigator.permissions.query({ name: "periodic-background-sync" });
233
+
234
+ if (status.state === "granted") {
235
+ await reg.periodicSync.register("update-content", {
236
+ minInterval: 24 * 60 * 60 * 1000, // Once per day minimum
237
+ });
238
+ }
239
+
240
+ // Handle in SW
241
+ self.addEventListener("periodicsync", (event) => {
242
+ if (event.tag === "update-content") {
243
+ event.waitUntil(updateCachedContent());
244
+ }
245
+ });
246
+
247
+ async function updateCachedContent() {
248
+ const cache = await caches.open("content-v1");
249
+ const response = await fetch("/api/latest-content");
250
+ if (response.ok) {
251
+ await cache.put("/api/latest-content", response);
252
+ }
253
+ }
254
+ ```
255
+
256
+ **Notes:**
257
+
258
+ - `minInterval` is a hint — the browser decides actual frequency based on site engagement
259
+ - Requires a minimum site engagement score (user must visit regularly)
260
+ - Not supported in Firefox or Safari
261
+ - Always check for API availability before registering
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: typescript-conventions
3
+ description: "TypeScript coding conventions for strict, type-safe projects. Use when: (1) writing or reviewing TypeScript code, (2) choosing between `any` and `unknown`, (3) structuring imports with verbatimModuleSyntax, (4) naming functions, booleans, queries, and commands, (5) handling errors with guard clauses and early returns, or (6) avoiding common anti-patterns like primitive obsession, magic strings, and premature abstraction."
4
+ ---
5
+
6
+ # TypeScript Conventions
7
+
8
+ Project-wide TypeScript standards that complement agent-specific instructions.
9
+
10
+ ## Type Safety
11
+
12
+ - **No `any`**: Use `unknown` if the type is truly dynamic, then narrow.
13
+ - **Strict config**: `strict: true`, `noUncheckedIndexedAccess`, `verbatimModuleSyntax`.
14
+ - Use `Readonly<T>`, `Pick`, `Omit`, and `Record` for precise types.
15
+ - Use branded types for entity IDs (e.g., `UserId`, `OrderId`) to prevent mixing.
16
+ - Prefer `z.infer<typeof schema>` over hand-written types when a Zod schema exists.
17
+
18
+ ## Imports
19
+
20
+ ```typescript
21
+ // Type-only imports (required by verbatimModuleSyntax)
22
+ import type { FastifyInstance } from "fastify";
23
+
24
+ // Mixed imports: separate values and types
25
+ import { z } from "zod/v4";
26
+ import type { ZodType } from "zod/v4";
27
+
28
+ // ioredis: always named import
29
+ import { Redis } from "ioredis";
30
+ ```
31
+
32
+ ## Error Handling
33
+
34
+ - Handle errors at the beginning of functions with early returns / guard clauses.
35
+ - Avoid deep nesting -- use if-return pattern instead of else chains.
36
+ - In Fastify routes, throw `httpErrors` or use `reply.status().send()` -- the centralized `setErrorHandler` formats the response.
37
+ - Custom error classes for domain-specific errors (e.g., `NotFoundError`, `ConflictError`).
38
+
39
+ ## Naming
40
+
41
+ - **Functions**: `getUserById`, `createReport`, `isActive`, `hasPermission`
42
+ - **Booleans**: `is/has/can/should` prefix
43
+ - **Query** (returns data): `get`, `find`, `list`, `fetch`
44
+ - **Command** (changes state): `create`, `update`, `delete`, `add`, `remove`
45
+
46
+ ## Anti-Patterns
47
+
48
+ - **Primitive obsession**: Use branded types or Zod enums, not raw strings for IDs and statuses.
49
+ - **Magic numbers/strings**: Use constants from a shared package (e.g., `RATE_LIMITS`, `PAGINATION`, `CACHE`).
50
+ - **Long parameter lists**: Use an options object or a Zod schema.
51
+ - **Premature abstraction**: Three similar lines > one premature helper. Abstract on the third repetition.
@@ -0,0 +1,105 @@
1
+ ---
2
+ name: ui-ux-guidelines
3
+ description: "Review UI code for Web Interface Guidelines compliance. Use when asked to review UI, check accessibility, audit design, review UX, or check against best practices."
4
+ ---
5
+
6
+ # Web Interface Guidelines
7
+
8
+ Dispatch hub for UI/UX rules. Load the relevant reference file for full details.
9
+
10
+ ## Contents
11
+
12
+ 1. [Rule Categories](#rule-categories-by-priority)
13
+ 2. [Workflows](#workflows)
14
+ 3. [Anti-patterns](#anti-patterns-flag-these)
15
+ 4. [Output Format](#code-review-output-format)
16
+ 5. [Reference Files](#reference-files)
17
+
18
+ ---
19
+
20
+ ## Rule Categories by Priority
21
+
22
+ | Priority | Category | Impact | Reference File |
23
+ | -------- | -------------------- | -------- | ------------------------------- |
24
+ | 1 | Accessibility | CRITICAL | `accessibility-and-interaction` |
25
+ | 2 | Touch & Interaction | CRITICAL | `accessibility-and-interaction` |
26
+ | 3 | Performance | HIGH | `layout-typography-animation` |
27
+ | 4 | Layout & Responsive | HIGH | `layout-typography-animation` |
28
+ | 5 | Typography & Color | MEDIUM | `layout-typography-animation` |
29
+ | 6 | Animation | MEDIUM | `layout-typography-animation` |
30
+ | 7 | Forms | HIGH | `forms-content-checklist` |
31
+ | 8 | Content & Navigation | MEDIUM | `forms-content-checklist` |
32
+ | 9 | Charts & Data | LOW | `layout-typography-animation` |
33
+
34
+ ---
35
+
36
+ ## Workflows
37
+
38
+ ### 1. Review UI code
39
+
40
+ 1. Read the target file(s).
41
+ 2. Load the relevant reference file(s) from `references/` based on what the code contains.
42
+ 3. Check each applicable rule. Report violations in the output format below.
43
+
44
+ ### 2. Build new component
45
+
46
+ 1. Load `references/accessibility-and-interaction.md` -- all components must meet CRITICAL rules.
47
+ 2. Load additional references based on component type:
48
+ - Form component -> `references/forms-content-checklist.md`
49
+ - Layout/visual component -> `references/layout-typography-animation.md`
50
+ 3. Follow rules during implementation.
51
+
52
+ ### 3. Pre-delivery checklist
53
+
54
+ 1. Load `references/forms-content-checklist.md` for the full checklist.
55
+ 2. Load `references/accessibility-and-interaction.md` for the interaction checklist.
56
+ 3. Walk through every checkbox before shipping.
57
+
58
+ ---
59
+
60
+ ## Anti-patterns (flag these)
61
+
62
+ - `user-scalable=no` or `maximum-scale=1` -- disables zoom
63
+ - `onPaste` with `preventDefault` -- blocks paste
64
+ - `transition: all` -- list properties explicitly
65
+ - `outline-none` without `:focus-visible` replacement
66
+ - `<div>`/`<span>` with click handlers -- use `<button>` or `<a>`
67
+ - `<img>` without `width` and `height` (causes CLS)
68
+ - Inline `onClick` navigation without `<a>` (breaks Cmd+click)
69
+ - Large `.map()` without virtualization (>50 items)
70
+ - Hardcoded date/number formats -- use `Intl.*`
71
+ - Icon-only buttons without `aria-label`
72
+
73
+ ---
74
+
75
+ ## Code Review Output Format
76
+
77
+ Group findings by file. Use `file:line` format (VS Code clickable). Be terse -- state issue and location. Skip explanation unless fix is non-obvious.
78
+
79
+ ```text
80
+ ## src/Button.tsx
81
+
82
+ src/Button.tsx:42 - icon button missing aria-label
83
+ src/Button.tsx:18 - input lacks label
84
+ src/Button.tsx:55 - animation missing prefers-reduced-motion
85
+ src/Button.tsx:67 - transition: all -> list properties explicitly
86
+
87
+ ## src/Modal.tsx
88
+
89
+ src/Modal.tsx:12 - missing overscroll-behavior: contain
90
+ src/Modal.tsx:34 - "..." -> "..."
91
+
92
+ ## src/Card.tsx
93
+
94
+ pass
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Reference Files
100
+
101
+ Load these as needed during reviews and implementation:
102
+
103
+ - **[Accessibility & Interaction](references/accessibility-and-interaction.md)** -- Focus, ARIA, keyboard, touch targets, cursors, drag UX
104
+ - **[Layout, Typography & Animation](references/layout-typography-animation.md)** -- Performance, responsive, fonts, color, motion, charts
105
+ - **[Forms, Content & Checklist](references/forms-content-checklist.md)** -- Forms, content handling, navigation, dark mode, locale, hydration, pre-delivery checklist
@@ -0,0 +1,74 @@
1
+ # Accessibility & Interaction Reference
2
+
3
+ Rules for accessible, touch-friendly interfaces. Loaded by the dispatch hub when reviewing accessibility or interaction code.
4
+
5
+ ---
6
+
7
+ ## Accessibility (CRITICAL)
8
+
9
+ ### Focus & Keyboard
10
+
11
+ - `focus-states` — Visible focus rings on all interactive elements; use `:focus-visible` over `:focus`
12
+ - `keyboard-nav` — Tab order matches visual order; interactive elements need `onKeyDown`/`onKeyUp` handlers
13
+ - `focus-within` — Use `:focus-within` for compound controls (e.g., search with icon)
14
+ - `scroll-margin` — `scroll-margin-top` on heading anchors to avoid content hidden behind fixed headers
15
+ - `heading-hierarchy` — `<h1>`--`<h6>` hierarchical; include skip link for main content
16
+
17
+ ### ARIA & Semantics
18
+
19
+ - `aria-labels` — `aria-label` for icon-only buttons; `aria-hidden="true"` for decorative icons
20
+ - `aria-live` — Async updates (toasts, loading, validation) need `aria-live="polite"`
21
+ - `semantic-first` — Use semantic HTML (`<button>`, `<a>`, `<label>`, `<table>`) before reaching for ARIA
22
+ - `color-contrast` — Minimum 4.5:1 ratio for normal text; color must not be the only indicator
23
+
24
+ ### Form Accessibility
25
+
26
+ - `form-labels` — Use `<label>` with `htmlFor` or wrapping control on all inputs
27
+ - Checkboxes/radios: label and control share a single hit target (no dead zones)
28
+
29
+ ---
30
+
31
+ ## Touch & Interaction (CRITICAL)
32
+
33
+ ### Touch Targets
34
+
35
+ - `touch-target-size` — Minimum 44x44px touch targets
36
+ - `touch-action` — Add `touch-action: manipulation` to interactive elements (prevents double-tap zoom delay)
37
+ - `tap-highlight` — Set `-webkit-tap-highlight-color` intentionally (don't leave as default)
38
+
39
+ ### Click & Hover
40
+
41
+ - `hover-vs-tap` — Use click/tap for primary interactions, never hover-only
42
+ - `cursor-pointer` — Add `cursor-pointer` to all clickable elements
43
+ - `loading-buttons` — Disable button during async operations; show loading state
44
+ - `error-feedback` — Clear error messages placed near the problem field
45
+
46
+ ### Containment & Drag
47
+
48
+ - `overscroll` — Add `overscroll-behavior: contain` in modals, drawers, and sheets
49
+ - `drag-ux` — During drag operations: disable text selection, use `inert` on dragged elements
50
+ - `autofocus` — Use `autoFocus` sparingly — desktop only, single primary input; avoid on mobile
51
+
52
+ ---
53
+
54
+ ## Anti-patterns to Flag
55
+
56
+ - `user-scalable=no` or `maximum-scale=1` — disables zoom (accessibility violation)
57
+ - `outline-none` / `outline: 0` without a `:focus-visible` replacement
58
+ - `<div>` or `<span>` with click handlers — use `<button>` or `<a>`
59
+ - Icon-only buttons without `aria-label`
60
+ - Form inputs without associated labels
61
+ - `autoFocus` without clear justification on mobile
62
+
63
+ ---
64
+
65
+ ## Interaction Review Checklist
66
+
67
+ - [ ] All clickable elements have `cursor-pointer`
68
+ - [ ] Hover states provide clear visual feedback without layout shift
69
+ - [ ] Transitions are smooth (150--300ms)
70
+ - [ ] Focus states visible for keyboard navigation (`:focus-visible`)
71
+ - [ ] Destructive actions have confirmation modal or undo
72
+ - [ ] All images have descriptive alt text (or `alt=""` for decorative)
73
+ - [ ] Async updates (toasts, validation) use `aria-live="polite"`
74
+ - [ ] Interactive elements have keyboard handlers
@@ -0,0 +1,126 @@
1
+ # Forms, Content & Pre-Delivery Checklist
2
+
3
+ Rules for forms, content handling, navigation, dark mode, locale, and hydration. Includes the pre-delivery checklist. Loaded by the dispatch hub for form reviews and final delivery checks.
4
+
5
+ ---
6
+
7
+ ## Forms
8
+
9
+ - Inputs need `autocomplete` attribute and meaningful `name`
10
+ - Use correct `type` (`email`, `tel`, `url`, `number`, `search`) and `inputmode` for virtual keyboards
11
+ - Never block paste (`onPaste` + `preventDefault`)
12
+ - Labels must be clickable: use `htmlFor` matching `id`, or wrap control in `<label>`
13
+ - Disable spellcheck on emails, codes, and usernames: `spellCheck={false}`
14
+ - Checkboxes/radios: label and control share a single hit target (no dead zones)
15
+ - Submit button stays enabled until request starts; show spinner during request
16
+ - Errors inline next to fields; focus the first error field on submit
17
+ - Placeholders end with `…` and show an example pattern (e.g., `"Ex: nome@email.com…"`)
18
+ - Use `autocomplete="off"` on non-auth fields where password manager triggers are unwanted
19
+ - Warn before navigation with unsaved changes (`beforeunload` event or router guard)
20
+
21
+ ---
22
+
23
+ ## Content Handling
24
+
25
+ - Text containers must handle long content: use `truncate`, `line-clamp-*`, or `break-words`
26
+ - Flex children that contain text need `min-w-0` to allow text truncation to work
27
+ - Always handle empty states — never render broken UI for empty strings or arrays
28
+ - User-generated content: design and test for short, average, and very long inputs
29
+
30
+ ---
31
+
32
+ ## Navigation & State
33
+
34
+ - URL reflects state — filters, tabs, pagination, and expanded panels belong in query params
35
+ - Links must use `<a>`/`<Link>` to support Cmd/Ctrl+click and middle-click
36
+ - Deep-link all stateful UI — if it uses `useState`, consider URL sync via `nuqs` or similar
37
+ - Destructive actions require a confirmation modal or undo window — never immediate execution
38
+
39
+ ---
40
+
41
+ ## Dark Mode & Theming
42
+
43
+ - Set `color-scheme: dark` on `<html>` for dark themes (fixes scrollbar and native input appearance)
44
+ - `<meta name="theme-color">` must match the page background color
45
+ - Native `<select>` elements need explicit `background-color` and `color` for Windows dark mode
46
+
47
+ ---
48
+
49
+ ## Locale & i18n
50
+
51
+ - Dates and times: use `Intl.DateTimeFormat` — never hardcode date formats
52
+ - Numbers and currency: use `Intl.NumberFormat` — never hardcode number/currency formats
53
+ - Detect language via `Accept-Language` header or `navigator.languages` — not by IP geolocation
54
+
55
+ ---
56
+
57
+ ## Hydration Safety
58
+
59
+ - Controlled inputs with `value` need `onChange` (or use `defaultValue` for uncontrolled)
60
+ - Date/time rendering: guard against hydration mismatch between server and client
61
+ - `suppressHydrationWarning` only where truly necessary (e.g., system clock, browser extensions)
62
+
63
+ ---
64
+
65
+ ## Content & Copy
66
+
67
+ - Active voice: "Install the CLI" not "The CLI will be installed"
68
+ - Sentence case for headings (e.g., "Configure notifications")
69
+ - Numerals for counts: "8 items" not "eight items"
70
+ - Specific button labels: "Save API Key" not "Continue"
71
+ - Error messages include the fix or next step — not just the problem description
72
+ - Second person ("you"); avoid first person ("I")
73
+ - Use `&` over "and" where space is constrained
74
+
75
+ ---
76
+
77
+ ## Pre-Delivery Checklist
78
+
79
+ Before delivering UI code, verify all items below.
80
+
81
+ ### Visual Quality
82
+
83
+ - [ ] No emojis used as icons (SVG only)
84
+ - [ ] All icons from a consistent icon set (Lucide for this project)
85
+ - [ ] Brand logos verified from Simple Icons
86
+ - [ ] Hover states do not cause layout shift
87
+ - [ ] Theme colors used directly (e.g., `bg-primary`), not wrapped in `var()`
88
+
89
+ ### Forms
90
+
91
+ - [ ] All inputs have `autocomplete` and meaningful `name`
92
+ - [ ] Correct `type` and `inputmode` on inputs
93
+ - [ ] Paste is not blocked
94
+ - [ ] All labels are clickable (`htmlFor` or wrapping)
95
+ - [ ] Submit button disabled + spinner during request
96
+ - [ ] Errors shown inline; first error focused on submit
97
+
98
+ ### Light/Dark Mode
99
+
100
+ - [ ] Light mode text meets 4.5:1 contrast minimum
101
+ - [ ] Glass/transparent elements are visible in light mode
102
+ - [ ] Borders visible in both light and dark modes
103
+ - [ ] Both modes tested before delivery
104
+ - [ ] `color-scheme` set on `<html>` for dark themes
105
+
106
+ ### Layout
107
+
108
+ - [ ] Floating elements have proper spacing from viewport edges
109
+ - [ ] No content hidden behind fixed navbars
110
+ - [ ] Responsive at 375px, 768px, 1024px, 1440px
111
+ - [ ] No horizontal scroll on mobile
112
+ - [ ] Safe area insets applied for full-bleed layouts
113
+
114
+ ### Typography & Copy
115
+
116
+ - [ ] `…` (U+2026) used instead of `...` (three dots)
117
+ - [ ] Loading states end with `…`
118
+ - [ ] `font-variant-numeric: tabular-nums` on number columns
119
+ - [ ] `text-wrap: balance` on headings
120
+ - [ ] Error messages include the next step, not just the problem
121
+
122
+ ### i18n & Hydration
123
+
124
+ - [ ] Dates use `Intl.DateTimeFormat`
125
+ - [ ] Numbers/currency use `Intl.NumberFormat`
126
+ - [ ] Controlled inputs have `onChange`; date/time rendering guarded against hydration mismatch