devflow-kit 1.1.0 → 1.3.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 (152) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/README.md +23 -6
  3. package/dist/cli.js +2 -0
  4. package/dist/commands/ambient.js +5 -4
  5. package/dist/commands/init.js +4 -2
  6. package/dist/commands/memory.js +4 -4
  7. package/dist/commands/skills.d.ts +11 -0
  8. package/dist/commands/skills.js +116 -0
  9. package/dist/commands/uninstall.js +11 -1
  10. package/dist/plugins.js +67 -3
  11. package/dist/utils/installer.js +20 -2
  12. package/package.json +4 -2
  13. package/plugins/devflow-accessibility/.claude-plugin/plugin.json +22 -0
  14. package/plugins/devflow-ambient/.claude-plugin/plugin.json +4 -2
  15. package/plugins/devflow-ambient/README.md +8 -8
  16. package/plugins/devflow-ambient/commands/ambient.md +14 -14
  17. package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +16 -9
  18. package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +6 -2
  19. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
  20. package/plugins/devflow-code-review/.claude-plugin/plugin.json +13 -6
  21. package/plugins/devflow-code-review/agents/reviewer.md +8 -0
  22. package/plugins/devflow-code-review/commands/code-review-teams.md +11 -1
  23. package/plugins/devflow-code-review/commands/code-review.md +12 -2
  24. package/plugins/devflow-code-review/skills/architecture-patterns/SKILL.md +1 -1
  25. package/plugins/devflow-code-review/skills/complexity-patterns/SKILL.md +1 -1
  26. package/plugins/devflow-code-review/skills/consistency-patterns/SKILL.md +1 -1
  27. package/plugins/devflow-code-review/skills/database-patterns/SKILL.md +1 -1
  28. package/plugins/devflow-code-review/skills/dependencies-patterns/SKILL.md +1 -1
  29. package/plugins/devflow-code-review/skills/documentation-patterns/SKILL.md +1 -1
  30. package/plugins/devflow-code-review/skills/performance-patterns/SKILL.md +1 -1
  31. package/plugins/devflow-code-review/skills/regression-patterns/SKILL.md +1 -1
  32. package/plugins/devflow-code-review/skills/review-methodology/SKILL.md +1 -1
  33. package/plugins/devflow-code-review/skills/security-patterns/SKILL.md +1 -1
  34. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +10 -7
  35. package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +5 -8
  36. package/plugins/devflow-debug/.claude-plugin/plugin.json +10 -3
  37. package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +22 -0
  38. package/plugins/devflow-go/.claude-plugin/plugin.json +22 -0
  39. package/plugins/devflow-go/skills/go/SKILL.md +187 -0
  40. package/plugins/devflow-go/skills/go/references/concurrency.md +312 -0
  41. package/plugins/devflow-go/skills/go/references/detection.md +129 -0
  42. package/plugins/devflow-go/skills/go/references/patterns.md +232 -0
  43. package/plugins/devflow-go/skills/go/references/violations.md +205 -0
  44. package/plugins/devflow-implement/.claude-plugin/plugin.json +19 -5
  45. package/plugins/devflow-implement/agents/coder.md +11 -6
  46. package/plugins/devflow-implement/skills/self-review/SKILL.md +1 -1
  47. package/plugins/devflow-java/.claude-plugin/plugin.json +22 -0
  48. package/plugins/devflow-java/skills/java/SKILL.md +183 -0
  49. package/plugins/devflow-java/skills/java/references/detection.md +120 -0
  50. package/plugins/devflow-java/skills/java/references/modern-java.md +270 -0
  51. package/plugins/devflow-java/skills/java/references/patterns.md +235 -0
  52. package/plugins/devflow-java/skills/java/references/violations.md +213 -0
  53. package/plugins/devflow-python/.claude-plugin/plugin.json +22 -0
  54. package/plugins/devflow-python/skills/python/SKILL.md +188 -0
  55. package/plugins/devflow-python/skills/python/references/async.md +220 -0
  56. package/plugins/devflow-python/skills/python/references/detection.md +128 -0
  57. package/plugins/devflow-python/skills/python/references/patterns.md +226 -0
  58. package/plugins/devflow-python/skills/python/references/violations.md +204 -0
  59. package/plugins/devflow-react/.claude-plugin/plugin.json +22 -0
  60. package/plugins/{devflow-core-skills → devflow-react}/skills/react/SKILL.md +1 -1
  61. package/plugins/{devflow-core-skills → devflow-react}/skills/react/references/patterns.md +3 -3
  62. package/plugins/devflow-resolve/.claude-plugin/plugin.json +13 -3
  63. package/plugins/devflow-resolve/skills/security-patterns/SKILL.md +1 -1
  64. package/plugins/devflow-rust/.claude-plugin/plugin.json +22 -0
  65. package/plugins/devflow-rust/skills/rust/SKILL.md +193 -0
  66. package/plugins/devflow-rust/skills/rust/references/detection.md +131 -0
  67. package/plugins/devflow-rust/skills/rust/references/ownership.md +242 -0
  68. package/plugins/devflow-rust/skills/rust/references/patterns.md +210 -0
  69. package/plugins/devflow-rust/skills/rust/references/violations.md +191 -0
  70. package/plugins/devflow-self-review/.claude-plugin/plugin.json +10 -3
  71. package/plugins/devflow-self-review/skills/self-review/SKILL.md +1 -1
  72. package/plugins/devflow-specify/.claude-plugin/plugin.json +15 -4
  73. package/plugins/devflow-typescript/.claude-plugin/plugin.json +22 -0
  74. package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
  75. package/scripts/hooks/{ambient-prompt.sh → ambient-prompt} +4 -4
  76. package/scripts/hooks/{background-memory-update.sh → background-memory-update} +3 -3
  77. package/scripts/hooks/{ensure-memory-gitignore.sh → ensure-memory-gitignore} +1 -1
  78. package/scripts/hooks/{pre-compact-memory.sh → pre-compact-memory} +2 -2
  79. package/scripts/hooks/run-hook +23 -0
  80. package/scripts/hooks/session-start-memory +151 -0
  81. package/scripts/hooks/{stop-update-memory.sh → stop-update-memory} +4 -4
  82. package/shared/agents/coder.md +11 -6
  83. package/shared/agents/reviewer.md +8 -0
  84. package/shared/skills/ambient-router/SKILL.md +16 -9
  85. package/shared/skills/ambient-router/references/skill-catalog.md +6 -2
  86. package/shared/skills/architecture-patterns/SKILL.md +1 -1
  87. package/shared/skills/complexity-patterns/SKILL.md +1 -1
  88. package/shared/skills/consistency-patterns/SKILL.md +1 -1
  89. package/shared/skills/database-patterns/SKILL.md +1 -1
  90. package/shared/skills/dependencies-patterns/SKILL.md +1 -1
  91. package/shared/skills/documentation-patterns/SKILL.md +1 -1
  92. package/shared/skills/go/SKILL.md +187 -0
  93. package/shared/skills/go/references/concurrency.md +312 -0
  94. package/shared/skills/go/references/detection.md +129 -0
  95. package/shared/skills/go/references/patterns.md +232 -0
  96. package/shared/skills/go/references/violations.md +205 -0
  97. package/shared/skills/java/SKILL.md +183 -0
  98. package/shared/skills/java/references/detection.md +120 -0
  99. package/shared/skills/java/references/modern-java.md +270 -0
  100. package/shared/skills/java/references/patterns.md +235 -0
  101. package/shared/skills/java/references/violations.md +213 -0
  102. package/shared/skills/performance-patterns/SKILL.md +1 -1
  103. package/shared/skills/python/SKILL.md +188 -0
  104. package/shared/skills/python/references/async.md +220 -0
  105. package/shared/skills/python/references/detection.md +128 -0
  106. package/shared/skills/python/references/patterns.md +226 -0
  107. package/shared/skills/python/references/violations.md +204 -0
  108. package/shared/skills/react/SKILL.md +1 -1
  109. package/shared/skills/react/references/patterns.md +3 -3
  110. package/shared/skills/regression-patterns/SKILL.md +1 -1
  111. package/shared/skills/review-methodology/SKILL.md +1 -1
  112. package/shared/skills/rust/SKILL.md +193 -0
  113. package/shared/skills/rust/references/detection.md +131 -0
  114. package/shared/skills/rust/references/ownership.md +242 -0
  115. package/shared/skills/rust/references/patterns.md +210 -0
  116. package/shared/skills/rust/references/violations.md +191 -0
  117. package/shared/skills/security-patterns/SKILL.md +1 -1
  118. package/shared/skills/self-review/SKILL.md +1 -1
  119. package/shared/skills/test-driven-development/SKILL.md +5 -8
  120. package/shared/skills/typescript/references/patterns.md +3 -3
  121. package/src/templates/settings.json +3 -3
  122. package/plugins/devflow-code-review/skills/react/SKILL.md +0 -276
  123. package/plugins/devflow-code-review/skills/react/references/patterns.md +0 -1331
  124. package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +0 -229
  125. package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +0 -171
  126. package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +0 -670
  127. package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +0 -419
  128. package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +0 -254
  129. package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +0 -184
  130. package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +0 -511
  131. package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +0 -453
  132. package/plugins/devflow-core-skills/skills/react/references/violations.md +0 -565
  133. package/plugins/devflow-implement/skills/accessibility/SKILL.md +0 -229
  134. package/plugins/devflow-implement/skills/accessibility/references/detection.md +0 -171
  135. package/plugins/devflow-implement/skills/accessibility/references/patterns.md +0 -670
  136. package/plugins/devflow-implement/skills/accessibility/references/violations.md +0 -419
  137. package/plugins/devflow-implement/skills/frontend-design/SKILL.md +0 -254
  138. package/plugins/devflow-implement/skills/frontend-design/references/detection.md +0 -184
  139. package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +0 -511
  140. package/plugins/devflow-implement/skills/frontend-design/references/violations.md +0 -453
  141. package/scripts/hooks/session-start-memory.sh +0 -126
  142. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/SKILL.md +0 -0
  143. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/detection.md +0 -0
  144. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/patterns.md +0 -0
  145. /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/violations.md +0 -0
  146. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/SKILL.md +0 -0
  147. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/detection.md +0 -0
  148. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/patterns.md +0 -0
  149. /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/violations.md +0 -0
  150. /package/plugins/{devflow-code-review → devflow-react}/skills/react/references/violations.md +0 -0
  151. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/SKILL.md +0 -0
  152. /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/violations.md +0 -0
@@ -1,565 +0,0 @@
1
- # React Violation Examples
2
-
3
- Extended violation patterns for React reviews. Reference from main SKILL.md.
4
-
5
- ## Vercel Performance Violations
6
-
7
- ### Sequential Fetches
8
-
9
- ```tsx
10
- // VIOLATION: Sequential fetches (waterfall)
11
- async function loadDashboard(userId: string) {
12
- const user = await fetchUser(userId);
13
- const orders = await fetchOrders(userId); // Waits for user
14
- const prefs = await fetchPreferences(userId); // Waits for orders
15
- return { user, orders, prefs };
16
- }
17
- // Total time: T(user) + T(orders) + T(prefs)
18
- // Should be: max(T(user), T(orders), T(prefs))
19
-
20
- // VIOLATION: Sequential in useEffect
21
- useEffect(() => {
22
- async function load() {
23
- setUser(await fetchUser(id));
24
- setOrders(await fetchOrders(id)); // Sequential
25
- setStats(await fetchStats(id)); // Sequential
26
- }
27
- load();
28
- }, [id]);
29
- ```
30
-
31
- ### Barrel Import Anti-Patterns
32
-
33
- ```tsx
34
- // VIOLATION: Barrel import pulls entire library
35
- import { Button } from '@/components';
36
- import { formatDate, formatCurrency, formatNumber } from '@/utils';
37
- import { IconHome, IconUser } from '@/icons';
38
-
39
- // VIOLATION: Named imports from large packages
40
- import { debounce } from 'lodash'; // Imports entire lodash
41
- import { Button, Input, Select } from 'antd'; // Large bundle
42
-
43
- // VIOLATION: Not lazy loading heavy dependencies
44
- import Editor from '@monaco-editor/react'; // 2MB+ bundle
45
- import { Chart } from 'chart.js'; // Heavy charting library
46
-
47
- function Dashboard() {
48
- const [showChart, setShowChart] = useState(false);
49
- return (
50
- <div>
51
- {showChart && <Chart />} {/* Loaded even when not shown */}
52
- </div>
53
- );
54
- }
55
- ```
56
-
57
- ### Re-render Causing Patterns
58
-
59
- ```tsx
60
- // VIOLATION: Object literal in deps (new ref every render)
61
- useEffect(() => {
62
- fetchData(config);
63
- }, [{ page: 1, limit: 10 }]); // Always "changed"
64
-
65
- // VIOLATION: Array in deps
66
- useEffect(() => {
67
- updateFilters(filters);
68
- }, [[filter1, filter2, filter3]]); // New array every render
69
-
70
- // VIOLATION: Inline callback to memoized child
71
- const MemoChild = memo(Child);
72
-
73
- function Parent() {
74
- return (
75
- <MemoChild
76
- onClick={() => console.log('clicked')} // New fn = re-render
77
- style={{ color: 'blue' }} // New object = re-render
78
- />
79
- );
80
- }
81
-
82
- // VIOLATION: Computed value in render without memo
83
- function FilteredList({ items, filter }: Props) {
84
- const filtered = items.filter(i => i.includes(filter)); // Every render
85
- return <List items={filtered} />;
86
- }
87
- ```
88
-
89
- ### Unoptimized Images
90
-
91
- ```tsx
92
- // VIOLATION: No dimensions (causes layout shift)
93
- <img src={url} alt={alt} />
94
-
95
- // VIOLATION: No lazy loading (loads all images immediately)
96
- {images.map(img => <img src={img.src} alt={img.alt} />)}
97
-
98
- // VIOLATION: No aspect ratio (jumps on load)
99
- <img
100
- src={url}
101
- width={400}
102
- height={300}
103
- // Missing: style={{ aspectRatio: '4/3' }}
104
- />
105
-
106
- // VIOLATION: Eager loading below fold
107
- <img
108
- src={heroImage}
109
- alt="Hero"
110
- loading="eager" // Should be lazy for non-critical images
111
- />
112
- ```
113
-
114
- ### Inefficient Data Structures
115
-
116
- ```tsx
117
- // VIOLATION: Array.includes for frequent checks (O(n))
118
- function SelectableList({ items, selected }: Props) {
119
- return (
120
- <ul>
121
- {items.map(item => (
122
- <li className={selected.includes(item.id) ? 'selected' : ''}>
123
- {/* O(n) check on every item render */}
124
- {item.name}
125
- </li>
126
- ))}
127
- </ul>
128
- );
129
- }
130
-
131
- // VIOLATION: Array.find for lookups (O(n))
132
- function UserDisplay({ userId, users }: Props) {
133
- const user = users.find(u => u.id === userId); // O(n) every render
134
- return <span>{user?.name}</span>;
135
- }
136
-
137
- // VIOLATION: Filter + map in render (double iteration)
138
- function ActiveUsers({ users }: Props) {
139
- return (
140
- <ul>
141
- {users
142
- .filter(u => u.active)
143
- .map(u => <li key={u.id}>{u.name}</li>)
144
- }
145
- </ul>
146
- );
147
- }
148
-
149
- // VIOLATION: Recreating Set every render
150
- function Tags({ tags, selected }: Props) {
151
- const selectedSet = new Set(selected); // Created every render
152
- return tags.map(tag => (
153
- <Tag selected={selectedSet.has(tag)} />
154
- ));
155
- }
156
- ```
157
-
158
- ---
159
-
160
- ## Component Violations
161
-
162
- ### Prop Drilling
163
-
164
- ```tsx
165
- // VIOLATION: Passing data through multiple intermediate components
166
- function App() {
167
- const [user, setUser] = useState<User | null>(null);
168
-
169
- return (
170
- <Layout user={user}>
171
- <Sidebar user={user}>
172
- <Navigation user={user}>
173
- <UserMenu user={user} /> {/* Props drilled through 3 levels */}
174
- </Navigation>
175
- </Sidebar>
176
- </Layout>
177
- );
178
- }
179
- ```
180
-
181
- ### Rigid Component Structure
182
-
183
- ```tsx
184
- // VIOLATION: Too many props, no composition
185
- function Card({
186
- title,
187
- subtitle,
188
- content,
189
- footer,
190
- headerIcon,
191
- showCloseButton,
192
- onClose,
193
- variant,
194
- size,
195
- className
196
- }: CardProps) {
197
- return (
198
- <div className={className}>
199
- <header>
200
- {headerIcon && <Icon name={headerIcon} />}
201
- <h2>{title}</h2>
202
- <p>{subtitle}</p>
203
- {showCloseButton && <button onClick={onClose}>X</button>}
204
- </header>
205
- <div>{content}</div>
206
- <footer>{footer}</footer>
207
- </div>
208
- );
209
- }
210
- ```
211
-
212
- ### Direct State Mutation
213
-
214
- ```tsx
215
- // VIOLATION: Mutating state directly
216
- function UserList() {
217
- const [users, setUsers] = useState<User[]>([]);
218
-
219
- const updateUser = (index: number, name: string) => {
220
- users[index].name = name; // BAD: Direct mutation
221
- setUsers(users); // Won't trigger re-render
222
- };
223
- }
224
- ```
225
-
226
- ### Missing Keys
227
-
228
- ```tsx
229
- // VIOLATION: Index as key causes reconciliation issues
230
- {items.map((item, index) => (
231
- <Item key={index} {...item} /> // Index key breaks reordering
232
- ))}
233
-
234
- // VIOLATION: Missing key entirely
235
- {items.map((item) => (
236
- <Item {...item} /> // React warning, poor performance
237
- ))}
238
- ```
239
-
240
- ---
241
-
242
- ## Hooks Violations
243
-
244
- ### Missing Dependencies
245
-
246
- ```tsx
247
- // VIOLATION: Missing dependency causes stale closure
248
- function SearchResults({ query }: { query: string }) {
249
- const [results, setResults] = useState<Result[]>([]);
250
-
251
- useEffect(() => {
252
- fetchResults(query).then(setResults);
253
- }, []); // BAD: Missing 'query' dependency
254
-
255
- return <ResultsList results={results} />;
256
- }
257
- ```
258
-
259
- ### Conditional Hooks
260
-
261
- ```tsx
262
- // VIOLATION: Hook called conditionally
263
- function UserProfile({ user }: { user: User | null }) {
264
- if (!user) {
265
- return <LoginPrompt />;
266
- }
267
-
268
- // BAD: Hook called after conditional return
269
- const [isEditing, setIsEditing] = useState(false);
270
-
271
- return <ProfileEditor user={user} isEditing={isEditing} />;
272
- }
273
- ```
274
-
275
- ### Stale Closure in Callbacks
276
-
277
- ```tsx
278
- // VIOLATION: Callback captures stale state
279
- function Counter() {
280
- const [count, setCount] = useState(0);
281
-
282
- useEffect(() => {
283
- const interval = setInterval(() => {
284
- setCount(count + 1); // BAD: Always references initial count (0)
285
- }, 1000);
286
-
287
- return () => clearInterval(interval);
288
- }, []); // Missing count dependency
289
-
290
- return <span>{count}</span>;
291
- }
292
- ```
293
-
294
- ### Effects Without Cleanup
295
-
296
- ```tsx
297
- // VIOLATION: Event listener never removed
298
- function WindowSize() {
299
- const [size, setSize] = useState({ width: 0, height: 0 });
300
-
301
- useEffect(() => {
302
- const handleResize = () => {
303
- setSize({ width: window.innerWidth, height: window.innerHeight });
304
- };
305
-
306
- window.addEventListener('resize', handleResize);
307
- // BAD: Missing cleanup - memory leak
308
- }, []);
309
-
310
- return <span>{size.width} x {size.height}</span>;
311
- }
312
- ```
313
-
314
- ### Derived State in useState
315
-
316
- ```tsx
317
- // VIOLATION: Storing computed value in state
318
- function ProductList({ products, filter }: Props) {
319
- const [filteredProducts, setFilteredProducts] = useState<Product[]>([]);
320
-
321
- useEffect(() => {
322
- setFilteredProducts(products.filter(p => p.category === filter));
323
- }, [products, filter]); // BAD: Unnecessary state and effect
324
-
325
- return <List items={filteredProducts} />;
326
- }
327
- ```
328
-
329
- ---
330
-
331
- ## Forms Violations
332
-
333
- ### Uncontrolled to Controlled Switch
334
-
335
- ```tsx
336
- // VIOLATION: Switching from uncontrolled to controlled
337
- function SearchInput() {
338
- const [value, setValue] = useState<string>(); // undefined initially
339
-
340
- return (
341
- <input
342
- value={value} // BAD: undefined -> string causes warning
343
- onChange={(e) => setValue(e.target.value)}
344
- />
345
- );
346
- }
347
- ```
348
-
349
- ### Missing Form Validation
350
-
351
- ```tsx
352
- // VIOLATION: No validation, direct submission
353
- function LoginForm({ onSubmit }: Props) {
354
- const [email, setEmail] = useState('');
355
- const [password, setPassword] = useState('');
356
-
357
- const handleSubmit = (e: React.FormEvent) => {
358
- e.preventDefault();
359
- onSubmit({ email, password }); // BAD: No validation
360
- };
361
-
362
- return (
363
- <form onSubmit={handleSubmit}>
364
- <input value={email} onChange={(e) => setEmail(e.target.value)} />
365
- <input value={password} onChange={(e) => setPassword(e.target.value)} />
366
- <button type="submit">Login</button>
367
- </form>
368
- );
369
- }
370
- ```
371
-
372
- ### Missing Accessibility Attributes
373
-
374
- ```tsx
375
- // VIOLATION: Form inputs without proper accessibility
376
- function ContactForm() {
377
- return (
378
- <form>
379
- {/* BAD: No labels, no aria attributes, no error announcements */}
380
- <input placeholder="Email" />
381
- {error && <span style={{ color: 'red' }}>{error}</span>}
382
- <button>Submit</button>
383
- </form>
384
- );
385
- }
386
- ```
387
-
388
- ### Form State Not Reset After Submit
389
-
390
- ```tsx
391
- // VIOLATION: Form keeps stale data after successful submit
392
- function CommentForm({ onSubmit }: Props) {
393
- const [comment, setComment] = useState('');
394
-
395
- const handleSubmit = async (e: React.FormEvent) => {
396
- e.preventDefault();
397
- await onSubmit(comment);
398
- // BAD: Missing state reset after successful submit
399
- };
400
-
401
- return (
402
- <form onSubmit={handleSubmit}>
403
- <textarea value={comment} onChange={(e) => setComment(e.target.value)} />
404
- <button type="submit">Post</button>
405
- </form>
406
- );
407
- }
408
- ```
409
-
410
- ---
411
-
412
- ## Error Handling Violations
413
-
414
- ### Missing Error Boundaries
415
-
416
- ```tsx
417
- // VIOLATION: No error boundary around risky component
418
- function App() {
419
- return (
420
- <div>
421
- <Header />
422
- <main>
423
- <UserProfile userId={userId} /> {/* If this crashes, entire app crashes */}
424
- <OrderHistory userId={userId} />
425
- </main>
426
- <Footer />
427
- </div>
428
- );
429
- }
430
- ```
431
-
432
- ### Swallowed Errors
433
-
434
- ```tsx
435
- // VIOLATION: Error caught but not handled
436
- function DataLoader({ url }: { url: string }) {
437
- const [data, setData] = useState(null);
438
-
439
- useEffect(() => {
440
- fetch(url)
441
- .then(res => res.json())
442
- .then(setData)
443
- .catch(() => {}); // BAD: Silently swallows error
444
- }, [url]);
445
-
446
- return data ? <DataDisplay data={data} /> : <Spinner />;
447
- }
448
- ```
449
-
450
- ### No Loading/Error States
451
-
452
- ```tsx
453
- // VIOLATION: Only handles success case
454
- function UserProfile({ userId }: { userId: string }) {
455
- const [user, setUser] = useState<User | null>(null);
456
-
457
- useEffect(() => {
458
- fetchUser(userId).then(setUser);
459
- }, [userId]);
460
-
461
- // BAD: No loading spinner, no error handling
462
- return user ? <Profile user={user} /> : null;
463
- }
464
- ```
465
-
466
- ### Error State Not Cleared
467
-
468
- ```tsx
469
- // VIOLATION: Error persists after retry
470
- function DataFetcher({ url }: { url: string }) {
471
- const [data, setData] = useState(null);
472
- const [error, setError] = useState<Error | null>(null);
473
-
474
- const fetchData = async () => {
475
- try {
476
- const result = await fetch(url).then(r => r.json());
477
- setData(result);
478
- // BAD: Error state not cleared on success
479
- } catch (e) {
480
- setError(e as Error);
481
- }
482
- };
483
-
484
- return (
485
- <div>
486
- {error && <ErrorMessage error={error} />}
487
- <button onClick={fetchData}>Retry</button>
488
- </div>
489
- );
490
- }
491
- ```
492
-
493
- ---
494
-
495
- ## Performance Violations
496
-
497
- ### Inline Objects in JSX
498
-
499
- ```tsx
500
- // VIOLATION: New reference every render
501
- <Component
502
- options={{ show: true, animate: false }} // New object each render
503
- items={[1, 2, 3]} // New array each render
504
- />
505
- ```
506
-
507
- ### Inline Arrow Functions in JSX
508
-
509
- ```tsx
510
- // VIOLATION: New function every render
511
- <Button onClick={() => handleClick(item.id)} />
512
-
513
- // Also creates new function each render
514
- {items.map(item => (
515
- <Item
516
- key={item.id}
517
- onClick={() => onSelect(item)} // New function per item per render
518
- />
519
- ))}
520
- ```
521
-
522
- ### Missing useMemo for Expensive Computations
523
-
524
- ```tsx
525
- // VIOLATION: Recalculates on every render
526
- function Dashboard({ data }: { data: DataPoint[] }) {
527
- const stats = computeExpensiveStats(data); // Runs every render
528
- const chartData = transformForChart(data); // Also runs every render
529
-
530
- return (
531
- <div>
532
- <Stats data={stats} />
533
- <Chart data={chartData} />
534
- </div>
535
- );
536
- }
537
- ```
538
-
539
- ### State Updates in Render
540
-
541
- ```tsx
542
- // VIOLATION: Causes infinite loop
543
- function Sync({ value }: { value: string }) {
544
- const [state, setState] = useState(value);
545
-
546
- if (value !== state) {
547
- setState(value); // BAD: State update during render
548
- }
549
-
550
- return <span>{state}</span>;
551
- }
552
- ```
553
-
554
- ### Unthrottled Event Handlers
555
-
556
- ```tsx
557
- // VIOLATION: Fires on every scroll pixel
558
- function ParallaxEffect() {
559
- useEffect(() => {
560
- window.addEventListener('scroll', () => {
561
- updateParallax(); // 60+ calls per second
562
- });
563
- }, []);
564
- }
565
- ```