@baldurpan/create-ai-workflow 0.2.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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -0
  3. package/dist/agents-block.js +70 -0
  4. package/dist/bin.js +14 -0
  5. package/dist/check/markdown.js +47 -0
  6. package/dist/check/parse.js +113 -0
  7. package/dist/check/rules.js +245 -0
  8. package/dist/cli.js +109 -0
  9. package/dist/commands/check.js +41 -0
  10. package/dist/commands/install.js +76 -0
  11. package/dist/commands/standards-add.js +145 -0
  12. package/dist/commands/update.js +214 -0
  13. package/dist/layout.js +115 -0
  14. package/dist/log.js +20 -0
  15. package/dist/manifest.js +53 -0
  16. package/dist/paths.js +41 -0
  17. package/package.json +37 -0
  18. package/templates/blocks/agents-block.md +30 -0
  19. package/templates/claude/agents/planner.agent.md +60 -0
  20. package/templates/claude/agents/reviewer.agent.md +77 -0
  21. package/templates/context/README.md +81 -0
  22. package/templates/context/plan-template.md +69 -0
  23. package/templates/context/plan-template.notes.md +55 -0
  24. package/templates/context/roles/coder.md +76 -0
  25. package/templates/context/workflow.md +143 -0
  26. package/templates/skills/feature-close/SKILL.md +102 -0
  27. package/templates/skills/feature-implement/SKILL.md +142 -0
  28. package/templates/skills/feature-plan/SKILL.md +138 -0
  29. package/templates/skills/feature-status/SKILL.md +86 -0
  30. package/templates/skills/onboard/SKILL.md +122 -0
  31. package/templates/skills/orchestrate/SKILL.md +92 -0
  32. package/templates/skills/roadmap/SKILL.md +97 -0
  33. package/templates/standards/.source +8 -0
  34. package/templates/standards/README.md +104 -0
  35. package/templates/standards/architecture/api-design.md +212 -0
  36. package/templates/standards/architecture/dependency-boundaries.md +104 -0
  37. package/templates/standards/architecture/feature-driven.md +102 -0
  38. package/templates/standards/architecture/folder-structure.md +108 -0
  39. package/templates/standards/architecture/monorepos.md +107 -0
  40. package/templates/standards/architecture/refactoring.md +97 -0
  41. package/templates/standards/architecture/shared-code.md +81 -0
  42. package/templates/standards/docs/PHP-SPEC.md +1195 -0
  43. package/templates/standards/docs/SPEC.md +540 -0
  44. package/templates/standards/examples/bad/data-fetching.tsx +52 -0
  45. package/templates/standards/examples/bad/derived-state.tsx +60 -0
  46. package/templates/standards/examples/bad/feature-component.tsx +80 -0
  47. package/templates/standards/examples/bad/prop-drilling.tsx +70 -0
  48. package/templates/standards/examples/good/data-fetching.tsx +53 -0
  49. package/templates/standards/examples/good/derived-state.tsx +52 -0
  50. package/templates/standards/examples/good/feature-component.tsx +141 -0
  51. package/templates/standards/examples/good/invoice.schema.ts +20 -0
  52. package/templates/standards/examples/good/prop-drilling.tsx +83 -0
  53. package/templates/standards/philosophy/ai-agent-behavior.md +93 -0
  54. package/templates/standards/philosophy/core-principles.md +49 -0
  55. package/templates/standards/philosophy/incremental-abstraction.md +56 -0
  56. package/templates/standards/philosophy/maintainability.md +66 -0
  57. package/templates/standards/philosophy/readability.md +87 -0
  58. package/templates/standards/php/README.md +62 -0
  59. package/templates/standards/php/anti-patterns.md +259 -0
  60. package/templates/standards/php/architecture.md +241 -0
  61. package/templates/standards/php/frameworks.md +197 -0
  62. package/templates/standards/php/rules.md +205 -0
  63. package/templates/standards/php/security.md +190 -0
  64. package/templates/standards/php/testing.md +139 -0
  65. package/templates/standards/php/tooling.md +245 -0
  66. package/templates/standards/react/accessibility.md +130 -0
  67. package/templates/standards/react/anti-patterns.md +187 -0
  68. package/templates/standards/react/component-design.md +139 -0
  69. package/templates/standards/react/error-boundaries.md +195 -0
  70. package/templates/standards/react/forms.md +147 -0
  71. package/templates/standards/react/hooks.md +88 -0
  72. package/templates/standards/react/memoization.md +87 -0
  73. package/templates/standards/react/state-management.md +123 -0
  74. package/templates/standards/react/testing.md +118 -0
  75. package/templates/standards/react/use-effect.md +110 -0
  76. package/templates/standards/security/api-security.md +136 -0
  77. package/templates/standards/security/auth.md +112 -0
  78. package/templates/standards/security/secrets.md +105 -0
  79. package/templates/standards/security/validation.md +89 -0
  80. package/templates/standards/templates/.editorconfig +16 -0
  81. package/templates/standards/templates/.nvmrc +1 -0
  82. package/templates/standards/templates/AGENTS.md +46 -0
  83. package/templates/standards/templates/CLAUDE.md +3 -0
  84. package/templates/standards/templates/_dot_gitignore +50 -0
  85. package/templates/standards/templates/biome.json +53 -0
  86. package/templates/standards/templates/eslint.config.js +61 -0
  87. package/templates/standards/templates/project-readme.md +76 -0
  88. package/templates/standards/templates/pull-request-template.md +46 -0
  89. package/templates/standards/templates/tsconfig.json +35 -0
  90. package/templates/standards/tooling/biome.md +92 -0
  91. package/templates/standards/tooling/ci.md +128 -0
  92. package/templates/standards/tooling/dates.md +194 -0
  93. package/templates/standards/tooling/dependencies.md +90 -0
  94. package/templates/standards/tooling/nx.md +113 -0
  95. package/templates/standards/tooling/observability.md +183 -0
  96. package/templates/standards/tooling/prisma.md +152 -0
  97. package/templates/standards/tooling/shadcn.md +115 -0
  98. package/templates/standards/tooling/tailwind.md +135 -0
  99. package/templates/standards/tooling/tanstack-query.md +214 -0
  100. package/templates/standards/tooling/tanstack-router.md +365 -0
  101. package/templates/standards/tooling/tanstack.md +31 -0
  102. package/templates/standards/tooling/vite.md +135 -0
  103. package/templates/standards/typescript/anti-patterns.md +107 -0
  104. package/templates/standards/typescript/error-handling.md +216 -0
  105. package/templates/standards/typescript/naming.md +78 -0
  106. package/templates/standards/typescript/rules.md +159 -0
  107. package/templates/standards/typescript/tsconfig/base.json +32 -0
  108. package/templates/standards/typescript/tsconfig/nextjs.json +12 -0
  109. package/templates/standards/typescript/tsconfig/react.json +9 -0
  110. package/templates/standards/typescript/validation.md +104 -0
  111. package/templates/stubs/executors.md +49 -0
  112. package/templates/stubs/findings.md +40 -0
  113. package/templates/stubs/history.md +13 -0
  114. package/templates/stubs/roadmap.md +29 -0
  115. package/templates/stubs/stack.md +35 -0
  116. package/templates/stubs/verify.md +48 -0
@@ -0,0 +1,540 @@
1
+ # AI Engineering Standards Repository
2
+
3
+ ## Goal
4
+
5
+ Build a personal AI-native engineering standards repository intended primarily for AI agent consumption (Claude Code, AGENTS.md, Cursor, Continue, etc.), while still remaining readable for humans.
6
+
7
+ This repository should serve as:
8
+
9
+ - A reusable engineering standards system
10
+ - A source of truth for TypeScript and React best practices
11
+ - A reusable starter/reference kit for new projects
12
+ - A refactoring guide for older codebases
13
+ - A retrieval-friendly knowledge base for AI coding agents
14
+
15
+ The repository should optimize for:
16
+
17
+ - deterministic AI guidance
18
+ - maintainability
19
+ - composability
20
+ - readability
21
+ - scalability
22
+ - accessibility
23
+ - incremental architecture
24
+
25
+ The repository should NOT optimize for:
26
+
27
+ - excessive prose
28
+ - philosophical essays
29
+ - premature abstraction
30
+ - enterprise boilerplate
31
+ - giant generalized frameworks
32
+
33
+ ---
34
+
35
+ # Core Engineering Philosophy
36
+
37
+ ## Core Principle
38
+
39
+ Prefer explicit, composable, feature-oriented architecture over generalized abstractions and centralized complexity.
40
+
41
+ ## Architectural Values
42
+
43
+ - Composition over inheritance
44
+ - Readability over cleverness
45
+ - Explicitness over magic
46
+ - Feature ownership over centralized organization
47
+ - Incremental abstraction over premature DRY
48
+ - Maintainability over premature optimization
49
+ - Colocation over fragmentation
50
+ - Accessibility-first development
51
+ - Strong type safety
52
+ - Predictable data flow
53
+
54
+ ---
55
+
56
+ # AI Agent Behavior Rules
57
+
58
+ AI agents working with these standards should:
59
+
60
+ ## Prioritize
61
+
62
+ - readability
63
+ - accessibility
64
+ - composability
65
+ - maintainability
66
+ - type safety
67
+ - feature isolation
68
+ - incremental refactoring
69
+ - explicit APIs
70
+ - predictable architecture
71
+
72
+ ## Avoid
73
+
74
+ - giant files
75
+ - useEffect abuse
76
+ - premature abstractions
77
+ - hook mini-frameworks
78
+ - defensive memoization
79
+ - over-generalized utilities
80
+ - excessive inheritance
81
+ - Redux
82
+ - hidden side effects
83
+ - implementation testing
84
+ - state synchronization effects
85
+ - aggressive rewrites without approval
86
+
87
+ ## Refactoring Rules
88
+
89
+ - Preserve behavior
90
+ - Prefer additive refactors
91
+ - Preserve architecture boundaries
92
+ - Ask before major architectural divergence
93
+ - Gently migrate legacy systems
94
+ - If possible, write tests before refactoring untested code
95
+ - Avoid massive rewrites unless explicitly requested
96
+
97
+ ---
98
+
99
+ # Repository Structure
100
+
101
+ Create the repository roughly with this structure:
102
+
103
+ ai-engineering-standards/
104
+ ├── README.md
105
+
106
+ ├── philosophy/
107
+ │ ├── core-principles.md
108
+ │ ├── ai-agent-behavior.md
109
+ │ ├── incremental-abstraction.md
110
+ │ ├── maintainability.md
111
+ │ └── readability.md
112
+
113
+ ├── typescript/
114
+ │ ├── rules.md
115
+ │ ├── anti-patterns.md
116
+ │ ├── validation.md
117
+ │ ├── naming.md
118
+ │ ├── error-handling.md
119
+ │ └── tsconfig/
120
+ │ ├── base.json
121
+ │ ├── react.json
122
+ │ └── nextjs.json
123
+
124
+ ├── react/
125
+ │ ├── component-design.md
126
+ │ ├── hooks.md
127
+ │ ├── use-effect.md
128
+ │ ├── memoization.md
129
+ │ ├── state-management.md
130
+ │ ├── forms.md
131
+ │ ├── accessibility.md
132
+ │ ├── testing.md
133
+ │ └── anti-patterns.md
134
+
135
+ ├── architecture/
136
+ │ ├── feature-driven.md
137
+ │ ├── shared-code.md
138
+ │ ├── monorepos.md
139
+ │ ├── folder-structure.md
140
+ │ ├── refactoring.md
141
+ │ └── dependency-boundaries.md
142
+
143
+ ├── tooling/
144
+ │ ├── tanstack.md
145
+ │ ├── nx.md
146
+ │ ├── vite.md
147
+ │ ├── biome.md
148
+ │ ├── tailwind.md
149
+ │ ├── shadcn.md
150
+ │ └── prisma.md
151
+
152
+ ├── security/
153
+ │ ├── validation.md
154
+ │ ├── secrets.md
155
+ │ ├── auth.md
156
+ │ └── api-security.md
157
+
158
+ ├── examples/
159
+ │ ├── good/
160
+ │ └── bad/
161
+
162
+ ├── templates/
163
+ │ ├── CLAUDE.md
164
+ │ ├── AGENTS.md
165
+ │ ├── project-readme.md
166
+ │ └── pull-request-template.md
167
+
168
+ └── packages/
169
+ ├── tsconfig/
170
+ ├── eslint-config/
171
+ └── biome-config/
172
+
173
+ ---
174
+
175
+ # Documentation Style Requirements
176
+
177
+ Optimize all documentation for AI retrieval quality.
178
+
179
+ Documentation should be:
180
+
181
+ - directive
182
+ - concise
183
+ - hierarchical
184
+ - example-heavy
185
+ - low ambiguity
186
+ - deterministic
187
+ - composable
188
+
189
+ Avoid:
190
+
191
+ - giant essays
192
+ - vague wording
193
+ - contradictory guidance
194
+ - excessive prose
195
+
196
+ Preferred style:
197
+
198
+ md # Rules ## DO - ... ## DO NOT - ... ## PRIORITY Readability > micro-optimization
199
+
200
+ Separate:
201
+
202
+ - rules
203
+ - rationale
204
+ - examples
205
+
206
+ where appropriate.
207
+
208
+ ---
209
+
210
+ # TypeScript Standards
211
+
212
+ ## General
213
+
214
+ - "strict": true
215
+ - Avoid any
216
+ - Prefer unions over enums
217
+ - Avoid type assertions when possible
218
+ - Prefer generated API types
219
+ - Prefer schema-driven validation
220
+ - Prefer explicit naming
221
+ - Avoid type gymnastics
222
+ - Avoid unnecessary DTO duplication
223
+
224
+ ## tsconfig Preferences
225
+
226
+ Include strong strictness rules such as:
227
+
228
+ - noUnusedLocals
229
+ - noUnusedParameters
230
+ - noUncheckedIndexedAccess
231
+ - noPropertyAccessFromIndexSignature
232
+ - noFallthroughCasesInSwitch
233
+ - allowUnreachableCode: false
234
+ - allowUnusedLabels: false
235
+ - noUncheckedSideEffectImports
236
+ - erasableSyntaxOnly
237
+
238
+ Use:
239
+
240
+ - ~/\* absolute imports
241
+
242
+ ## Validation
243
+
244
+ - Prefer Zod
245
+ - Investigate Valibot
246
+ - Schema-first validation is encouraged
247
+ - Shared FE/BE schemas are preferred
248
+
249
+ ---
250
+
251
+ # React Standards
252
+
253
+ ## Architecture
254
+
255
+ - Prefer feature-driven architecture
256
+ - Colocate feature-specific logic
257
+ - Avoid organization-by-type for large apps
258
+ - Prefer composition over deeply nested prop drilling
259
+ - Compound components are encouraged
260
+
261
+ ## Components
262
+
263
+ - Keep components reasonably scoped
264
+ - Avoid gigantic files
265
+ - Large files should trigger decomposition review
266
+ - One file should generally have one primary responsibility
267
+
268
+ ## Hooks
269
+
270
+ ## DO
271
+
272
+ - Encapsulate reusable behavior
273
+ - Keep hooks composable
274
+ - Keep effects explicit
275
+
276
+ ## DO NOT
277
+
278
+ - Create hook mini-frameworks
279
+ - Wrap useState purely for renaming
280
+ - Hide side effects unexpectedly
281
+
282
+ Before creating custom hooks:
283
+
284
+ - Check whether an existing solution already exists
285
+ - Investigate @uidotdev/usehooks
286
+
287
+ ## useEffect Doctrine
288
+
289
+ useEffect should primarily be used for:
290
+
291
+ - external system synchronization
292
+ - subscriptions
293
+ - DOM APIs
294
+ - timers
295
+ - imperative bridges
296
+
297
+ Avoid useEffect for:
298
+
299
+ - state synchronization
300
+ - derived state
301
+ - unnecessary data flow orchestration
302
+
303
+ ## Memoization
304
+
305
+ ## DO
306
+
307
+ - Optimize proven bottlenecks
308
+ - Use useCallback for stable drilled callbacks when needed
309
+
310
+ ## DO NOT
311
+
312
+ - Defensively memoize
313
+ - Abuse useMemo
314
+ - Use memoization to silence dependency warnings
315
+ - Overuse React.memo
316
+
317
+ Priority:
318
+
319
+ - Readability > micro-optimization
320
+
321
+ ## State Management Hierarchy
322
+
323
+ Preferred order:
324
+
325
+ 1. URL state
326
+ 2. Server state (TanStack Query)
327
+ 3. Local component state
328
+ 4. Context
329
+ 5. Zustand only when truly necessary
330
+ 6. Never Redux
331
+
332
+ ## Forms
333
+
334
+ - Prefer TanStack ecosystem where possible
335
+ - React Hook Form is acceptable
336
+ - Prefer controlled inputs
337
+ - Prefer shared schema validation
338
+ - Optimistic updates are encouraged
339
+
340
+ ---
341
+
342
+ # Styling Standards
343
+
344
+ Preferred stack:
345
+
346
+ - Tailwind CSS
347
+ - Shadcn UI
348
+ - CSS variables for theming
349
+ - Design tokens
350
+ - Minimal arbitrary values
351
+
352
+ Avoid:
353
+
354
+ - CSS Modules unless necessary
355
+ - Excessive arbitrary Tailwind values
356
+
357
+ Preferred theming approach:
358
+
359
+ - CSS variable-based themes
360
+ - Tailwind integration
361
+ - Runtime-friendly tokens
362
+ - Dark/light mode support
363
+
364
+ ---
365
+
366
+ # Testing Standards
367
+
368
+ ## Philosophy
369
+
370
+ - Integration tests over implementation tests
371
+ - Test behavior, not implementation details
372
+ - Avoid snapshot tests
373
+ - Unit test pure utilities and logic
374
+ - Use Playwright only for critical E2E flows
375
+
376
+ ## Preferred Tooling
377
+
378
+ - Vitest
379
+ - Testing Library
380
+ - Playwright
381
+
382
+ Follow the philosophy from:
383
+ https://kentcdodds.com/blog/common-mistakes-with-react-testing-library
384
+
385
+ ---
386
+
387
+ # Accessibility Standards
388
+
389
+ Accessibility standards should be strict.
390
+
391
+ ## Requirements
392
+
393
+ - Semantic HTML first
394
+ - Keyboard navigation mandatory
395
+ - Screenreader friendliness mandatory
396
+ - Form labeling mandatory
397
+ - ARIA only when necessary
398
+ - Avoid clickable divs
399
+ - Ensure color contrast compliance
400
+
401
+ ---
402
+
403
+ # Error Handling Standards
404
+
405
+ ## Rules
406
+
407
+ - Never swallow errors
408
+ - Never hide original error context
409
+ - Avoid generic "Something went wrong" messages
410
+ - Preserve HTTP status codes and payloads
411
+ - Use contextual logging
412
+ - Avoid large ambiguous try/catch blocks
413
+ - Use custom error classes where appropriate
414
+ - Validate inputs before transitions
415
+
416
+ ## Async Rules
417
+
418
+ - Avoid unhandled promise rejections
419
+ - Await async operations properly
420
+ - Use .catch() where appropriate
421
+
422
+ ## User-Facing Errors
423
+
424
+ Every user-facing error should:
425
+
426
+ - explain the failure
427
+ - explain the next step
428
+ - remain actionable
429
+
430
+ ---
431
+
432
+ # Dependency Philosophy
433
+
434
+ ## DO
435
+
436
+ - Prefer browser-native APIs
437
+ - Prefer mature maintained libraries
438
+ - Check bundle impact
439
+
440
+ ## DO NOT
441
+
442
+ - Add tiny unnecessary dependencies
443
+ - Add bloated libraries
444
+ - Use abandoned packages
445
+
446
+ ---
447
+
448
+ # Monorepo Philosophy
449
+
450
+ Preferred tooling:
451
+
452
+ - Nx
453
+ - pnpm
454
+
455
+ Guidelines:
456
+
457
+ - Preserve feature isolation
458
+ - Avoid circular dependencies
459
+ - Avoid publishable packages unless explicitly required
460
+ - Group packages by domain when scaling
461
+
462
+ Example:
463
+
464
+ txt packages/ frontend/ backend/
465
+
466
+ ---
467
+
468
+ # CI / PR Standards
469
+
470
+ Required:
471
+
472
+ - lint gating
473
+ - typecheck gating
474
+ - test gating
475
+ - formatting gating
476
+
477
+ Guidance:
478
+
479
+ - Smaller PRs are preferred for reviewability
480
+ - Large PRs are acceptable when necessary
481
+ - Prefer squash merges
482
+ - Prioritize high-quality PR titles/descriptions
483
+
484
+ When using PR workflows:
485
+
486
+ - Investigate @burglekitt/worktree
487
+
488
+ ---
489
+
490
+ # Initial Implementation Plan
491
+
492
+ Start implementation in phases.
493
+
494
+ ## Phase 1
495
+
496
+ - Repository structure
497
+ - README
498
+ - Core philosophy documents
499
+ - AI behavior document
500
+ - tsconfig package
501
+ - biome/eslint configs
502
+
503
+ ## Phase 2
504
+
505
+ - React/TypeScript standards docs
506
+ - Examples
507
+ - AGENTS.md templates
508
+ - CLAUDE.md templates
509
+
510
+ ## Phase 3
511
+
512
+ - Advanced architecture docs
513
+ - Security docs
514
+ - Monorepo docs
515
+ - Starter templates
516
+ - Scaffolding utilities
517
+
518
+ ---
519
+
520
+ # Important Final Guidance
521
+
522
+ This repository is primarily intended for:
523
+
524
+ - AI retrieval
525
+ - deterministic engineering guidance
526
+ - reusable architectural consistency
527
+
528
+ Optimize for:
529
+
530
+ - clarity
531
+ - consistency
532
+ - composability
533
+ - maintainability
534
+ - AI adherence
535
+
536
+ Not for:
537
+
538
+ - excessive prose
539
+ - academic writing
540
+ - generalized enterprise abstraction
@@ -0,0 +1,52 @@
1
+ /**
2
+ * BAD: Manual data fetching with useEffect
3
+ *
4
+ * Problems:
5
+ * - Race condition: if `userId` changes mid-fetch, the older response can overwrite the newer one
6
+ * - No caching: every mount triggers a fetch
7
+ * - No deduplication: two components mounting in parallel each fetch
8
+ * - Error state has no handling
9
+ * - No request cancellation on unmount
10
+ * - State sprawl: 3 useState calls to track what TanStack Query gives for free
11
+ */
12
+
13
+ import { useEffect, useState } from "react";
14
+
15
+ interface User {
16
+ id: string;
17
+ name: string;
18
+ email: string;
19
+ }
20
+
21
+ interface UserProfileProps {
22
+ userId: string;
23
+ }
24
+
25
+ export function UserProfile({ userId }: UserProfileProps) {
26
+ const [user, setUser] = useState<User | null>(null);
27
+ const [isLoading, setIsLoading] = useState(true);
28
+ // ✗ no error state — failures are silently swallowed below
29
+
30
+ useEffect(() => {
31
+ setIsLoading(true);
32
+ fetch(`/api/users/${userId}`)
33
+ .then((r) => r.json())
34
+ .then((data) => {
35
+ // ✗ if userId changed during this fetch, this overwrites the newer result
36
+ setUser(data);
37
+ setIsLoading(false);
38
+ });
39
+ // ✗ no .catch — network errors silently leave isLoading=true forever
40
+ // ✗ no AbortController — cancelled fetches still fire setState on unmount
41
+ }, [userId]);
42
+
43
+ if (isLoading) return <div>Loading…</div>;
44
+ if (!user) return null;
45
+
46
+ return (
47
+ <article>
48
+ <h1>{user.name}</h1>
49
+ <p>{user.email}</p>
50
+ </article>
51
+ );
52
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * BAD: Syncing derived values into state with useEffect
3
+ *
4
+ * Problems:
5
+ * - `filtered` and `total` are duplicate state — they can drift from `items`/`search`
6
+ * - Extra render on every input change (state update → effect → state update → render)
7
+ * - More code, more bugs, no benefit over computing during render
8
+ * - Initial render shows stale values until the effect runs
9
+ */
10
+
11
+ import { useEffect, useState } from "react";
12
+
13
+ interface Item {
14
+ id: string;
15
+ name: string;
16
+ price: number;
17
+ }
18
+
19
+ interface ItemListProps {
20
+ items: Item[];
21
+ }
22
+
23
+ export function ItemList({ items }: ItemListProps) {
24
+ const [search, setSearch] = useState("");
25
+ // ✗ derived values stored as state
26
+ const [filtered, setFiltered] = useState<Item[]>([]);
27
+ const [total, setTotal] = useState(0);
28
+
29
+ // ✗ effect syncs derived state — entirely unnecessary
30
+ useEffect(() => {
31
+ const result = items.filter((item) =>
32
+ item.name.toLowerCase().includes(search.toLowerCase()),
33
+ );
34
+ setFiltered(result);
35
+ setTotal(result.reduce((sum, item) => sum + item.price, 0));
36
+ }, [items, search]);
37
+
38
+ return (
39
+ <section>
40
+ <label>
41
+ Search
42
+ <input
43
+ type="search"
44
+ value={search}
45
+ onChange={(event) => setSearch(event.target.value)}
46
+ />
47
+ </label>
48
+ <p>
49
+ {filtered.length} items — total ${total.toFixed(2)}
50
+ </p>
51
+ <ul>
52
+ {filtered.map((item) => (
53
+ <li key={item.id}>
54
+ {item.name} — ${item.price.toFixed(2)}
55
+ </li>
56
+ ))}
57
+ </ul>
58
+ </section>
59
+ );
60
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * BAD EXAMPLE: God component with multiple anti-patterns
3
+ *
4
+ * Anti-patterns demonstrated:
5
+ * - useEffect for data fetching (use TanStack Query instead)
6
+ * - useEffect for derived state (compute during render instead)
7
+ * - Giant single component (decompose instead)
8
+ * - No types / implicit any
9
+ * - No error handling
10
+ * - No loading state
11
+ * - No accessibility (clickable div, no labels, no semantic markup)
12
+ * - Index as key
13
+ * - Unhandled promise (missing await / .catch)
14
+ * - Defensive unnecessary memoization
15
+ */
16
+
17
+ import { useEffect, useMemo, useState } from "react";
18
+
19
+ // ✗ No types defined — all data is implicitly any
20
+
21
+ export default function Invoices() {
22
+ // ✗ Manual fetch state instead of TanStack Query
23
+ const [data, setData] = useState(null);
24
+ const [loading, setLoading] = useState(false);
25
+
26
+ // ✗ useEffect for data fetching — race conditions, no caching, no deduplication
27
+ useEffect(() => {
28
+ setLoading(true);
29
+ fetch("/api/invoices")
30
+ .then((r) => r.json())
31
+ .then((d) => {
32
+ setData(d);
33
+ setLoading(false);
34
+ // ✗ No error handling — silently fails on network errors
35
+ });
36
+ }, []);
37
+
38
+ // ✗ useEffect for derived state — should be computed during render
39
+ const [total, setTotal] = useState(0);
40
+ useEffect(() => {
41
+ if (data) {
42
+ // @ts-ignore
43
+ setTotal(data.reduce((sum, inv) => sum + inv.amount, 0));
44
+ }
45
+ }, [data]);
46
+
47
+ // ✗ Defensive memoization of a trivial computation
48
+ const label = useMemo(() => `Total: $${total}`, [total]);
49
+
50
+ // ✗ No loading state rendered to user
51
+ if (loading) return null;
52
+
53
+ return (
54
+ // ✗ No semantic markup — div soup
55
+ <div>
56
+ <div>{label}</div>
57
+ <div>
58
+ {/* ✗ Index as key — unstable, causes rendering bugs */}
59
+ {/* ✗ any type throughout */}
60
+ {(data as any)?.map((invoice: any, i: number) => (
61
+ <div
62
+ key={i}
63
+ // ✗ Clickable div — not keyboard accessible, not a button
64
+ onClick={() => window.location.href = `/invoices/${invoice.id}`}
65
+ style={{ cursor: "pointer" }}
66
+ >
67
+ {/* ✗ No accessible label, no semantic structure */}
68
+ <span>{invoice.title}</span>
69
+ <span>{invoice.status}</span>
70
+ <span>{invoice.amount}</span>
71
+ {/* ✗ Unhandled promise — fire and forget without .catch */}
72
+ <span onClick={() => fetch(`/api/invoices/${invoice.id}/archive`, { method: "POST" })}>
73
+ Archive
74
+ </span>
75
+ </div>
76
+ ))}
77
+ </div>
78
+ </div>
79
+ );
80
+ }