ima-claude 2.20.0 → 2.26.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 (80) hide show
  1. package/README.md +74 -9
  2. package/dist/cli.js +2 -1
  3. package/package.json +1 -1
  4. package/plugins/ima-claude/.claude-plugin/plugin.json +2 -2
  5. package/plugins/ima-claude/agents/explorer.md +29 -15
  6. package/plugins/ima-claude/agents/implementer.md +58 -13
  7. package/plugins/ima-claude/agents/memory.md +19 -19
  8. package/plugins/ima-claude/agents/reviewer.md +84 -34
  9. package/plugins/ima-claude/agents/tester.md +59 -16
  10. package/plugins/ima-claude/agents/wp-developer.md +66 -21
  11. package/plugins/ima-claude/hooks/bootstrap.sh +42 -44
  12. package/plugins/ima-claude/hooks/prompt_coach_digest.md +14 -17
  13. package/plugins/ima-claude/hooks/prompt_coach_system.md +10 -12
  14. package/plugins/ima-claude/personalities/README.md +17 -6
  15. package/plugins/ima-claude/personalities/enable-efficient.md +61 -0
  16. package/plugins/ima-claude/personalities/enable-terse.md +71 -0
  17. package/plugins/ima-claude/skills/agentic-workflows/SKILL.md +35 -71
  18. package/plugins/ima-claude/skills/architect/SKILL.md +54 -168
  19. package/plugins/ima-claude/skills/compound-bridge/SKILL.md +41 -94
  20. package/plugins/ima-claude/skills/design-to-code/SKILL.md +43 -78
  21. package/plugins/ima-claude/skills/discourse/SKILL.md +79 -194
  22. package/plugins/ima-claude/skills/discourse-admin/SKILL.md +41 -103
  23. package/plugins/ima-claude/skills/docs-organize/SKILL.md +63 -203
  24. package/plugins/ima-claude/skills/ember-discourse/SKILL.md +90 -200
  25. package/plugins/ima-claude/skills/espocrm/SKILL.md +14 -23
  26. package/plugins/ima-claude/skills/espocrm-api/SKILL.md +79 -192
  27. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +33 -237
  28. package/plugins/ima-claude/skills/gh-cli/SKILL.md +26 -65
  29. package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +71 -104
  30. package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +32 -22
  31. package/plugins/ima-claude/skills/ima-brand/SKILL.md +18 -23
  32. package/plugins/ima-claude/skills/ima-copywriting/SKILL.md +68 -179
  33. package/plugins/ima-claude/skills/ima-doc2pdf/SKILL.md +32 -102
  34. package/plugins/ima-claude/skills/ima-editorial-scorecard/SKILL.md +38 -63
  35. package/plugins/ima-claude/skills/ima-editorial-workflow/SKILL.md +69 -114
  36. package/plugins/ima-claude/skills/ima-email-creator/SKILL.md +16 -22
  37. package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +21 -37
  38. package/plugins/ima-claude/skills/ima-git/SKILL.md +81 -0
  39. package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +39 -120
  40. package/plugins/ima-claude/skills/jquery/SKILL.md +107 -233
  41. package/plugins/ima-claude/skills/js-fp/SKILL.md +75 -296
  42. package/plugins/ima-claude/skills/js-fp-api/SKILL.md +52 -162
  43. package/plugins/ima-claude/skills/js-fp-react/SKILL.md +47 -270
  44. package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +55 -209
  45. package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +59 -204
  46. package/plugins/ima-claude/skills/livecanvas/SKILL.md +19 -32
  47. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +92 -162
  48. package/plugins/ima-claude/skills/mcp-context7/SKILL.md +32 -64
  49. package/plugins/ima-claude/skills/mcp-gitea/SKILL.md +98 -188
  50. package/plugins/ima-claude/skills/mcp-github/SKILL.md +60 -124
  51. package/plugins/ima-claude/skills/mcp-memory/SKILL.md +1 -177
  52. package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +58 -115
  53. package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +32 -87
  54. package/plugins/ima-claude/skills/mcp-serena/SKILL.md +54 -80
  55. package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +40 -63
  56. package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +75 -116
  57. package/plugins/ima-claude/skills/php-authnet/SKILL.md +32 -65
  58. package/plugins/ima-claude/skills/php-fp/SKILL.md +50 -129
  59. package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +25 -73
  60. package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +103 -463
  61. package/plugins/ima-claude/skills/playwright/SKILL.md +69 -220
  62. package/plugins/ima-claude/skills/prompt-starter/SKILL.md +33 -83
  63. package/plugins/ima-claude/skills/prompt-starter/references/code-review.md +38 -0
  64. package/plugins/ima-claude/skills/py-fp/SKILL.md +78 -384
  65. package/plugins/ima-claude/skills/quasar-fp/SKILL.md +54 -255
  66. package/plugins/ima-claude/skills/quickstart/SKILL.md +7 -11
  67. package/plugins/ima-claude/skills/rails/SKILL.md +63 -184
  68. package/plugins/ima-claude/skills/resume-session/SKILL.md +14 -35
  69. package/plugins/ima-claude/skills/rg/SKILL.md +61 -146
  70. package/plugins/ima-claude/skills/ruby-fp/SKILL.md +66 -163
  71. package/plugins/ima-claude/skills/save-session/SKILL.md +10 -39
  72. package/plugins/ima-claude/skills/scorecard/SKILL.md +42 -40
  73. package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +42 -71
  74. package/plugins/ima-claude/skills/skill-creator/SKILL.md +79 -250
  75. package/plugins/ima-claude/skills/task-master/SKILL.md +11 -31
  76. package/plugins/ima-claude/skills/task-planner/SKILL.md +44 -153
  77. package/plugins/ima-claude/skills/task-runner/SKILL.md +61 -143
  78. package/plugins/ima-claude/skills/unit-testing/SKILL.md +59 -134
  79. package/plugins/ima-claude/skills/wp-ddev/SKILL.md +38 -120
  80. package/plugins/ima-claude/skills/wp-local/SKILL.md +26 -108
@@ -5,50 +5,25 @@ description: "FP patterns for React with hooks, HOCs, and pure components - refe
5
5
 
6
6
  # JavaScript FP - React
7
7
 
8
- Functional programming patterns for React components with custom hooks, higher-order components, and pure component architecture.
8
+ FP patterns for React 16.8+ (hooks era): business logic in custom hooks, HOCs for DI, appropriate memoization.
9
9
 
10
- ## When to Use This Skill
10
+ **Foundation**: Builds on `js-fp` core. See `../js-fp/SKILL.md` for purity, composition, DI, and testing patterns.
11
11
 
12
- - Building React 16.8+ components (hooks era)
13
- - Need pure, testable component logic
14
- - Implementing custom hooks with FP principles
15
- - HOC patterns for dependency injection
16
- - Performance optimization without over-engineering
12
+ ## Pure Component + Custom Hook Pattern
17
13
 
18
- ## Core Philosophy
19
-
20
- **Pure components** with **business logic in custom hooks**, **HOCs for dependency injection**, and **appropriate memoization** (not obsessive).
21
-
22
- **Foundation**: This skill builds on `js-fp` core principles. Reference `../js-fp/SKILL.md` for purity, composition, dependency injection, and testing patterns.
23
-
24
- ## Pure Component with Custom Hook Pattern
25
-
26
- **Rule**: Separate business logic (custom hooks) from presentation (components).
14
+ Separate business logic (hooks) from presentation (components).
27
15
 
28
16
  ```typescript
29
17
  import { memo, useMemo, useCallback } from 'react'
30
18
 
31
- interface UserData {
32
- id: string
33
- name: string
34
- email: string
35
- }
36
-
37
- interface UserConfig {
38
- showEmail: boolean
39
- variant: 'compact' | 'detailed'
40
- }
41
-
42
19
  // ───── Custom hook with pure business logic ─────
43
20
  const useUserLogic = (userData: UserData, config: UserConfig) => {
44
- // Pure computation - no side effects
45
21
  const displayData = useMemo(() => ({
46
22
  ...userData,
47
23
  displayName: userData.name.trim(),
48
24
  shouldShowEmail: config.showEmail && userData.email
49
25
  }), [userData, config])
50
26
 
51
- // Pre-compiled handlers
52
27
  const handleAction = useCallback((action: string) => ({
53
28
  type: 'USER_ACTION',
54
29
  payload: { userId: userData.id, action }
@@ -78,34 +53,24 @@ const UserCard = memo<UserCardProps>(({ userData, config, onAction }) => {
78
53
  UserCard.displayName = 'UserCard'
79
54
  ```
80
55
 
81
- ## HOC for Dependency Injection Pattern
56
+ ## HOC for Dependency Injection
82
57
 
83
- **Rule**: Inject dependencies via HOCs for testability.
58
+ Inject dependencies via HOCs for testability.
84
59
 
85
60
  ```typescript
86
- // ───── Service interfaces ─────
87
61
  interface ServiceDependencies {
88
- userService: {
89
- getUser: (id: string) => Promise<UserData>
90
- updateUser: (id: string, data: Partial<UserData>) => Promise<UserData>
91
- }
92
- logger: {
93
- info: (message: string, meta?: any) => void
94
- error: (message: string, meta?: any) => void
95
- }
62
+ userService: { getUser: (id: string) => Promise<UserData>; updateUser: (id: string, data: Partial<UserData>) => Promise<UserData> }
63
+ logger: { info: (message: string, meta?: any) => void; error: (message: string, meta?: any) => void }
96
64
  }
97
65
 
98
- // ───── HOC factory (core: function factories) ─────
99
66
  export const withUserService = <P extends object>(
100
67
  WrappedComponent: React.ComponentType<P & ServiceDependencies>
101
68
  ) => {
102
69
  const WithUserServiceComponent = (props: P) => {
103
- // Service injection - can be mocked for testing
104
70
  const services: ServiceDependencies = {
105
71
  userService: useUserService(),
106
72
  logger: useLogger()
107
73
  }
108
-
109
74
  return <WrappedComponent {...props} {...services} />
110
75
  }
111
76
 
@@ -115,12 +80,7 @@ export const withUserService = <P extends object>(
115
80
  return WithUserServiceComponent
116
81
  }
117
82
 
118
- // ───── Pure component with injected dependencies ─────
119
- const UserProfile = ({
120
- userId,
121
- userService,
122
- logger
123
- }: { userId: string } & ServiceDependencies) => {
83
+ const UserProfile = ({ userId, userService, logger }: { userId: string } & ServiceDependencies) => {
124
84
  const [user, setUser] = useState<UserData | null>(null)
125
85
  const [loading, setLoading] = useState(true)
126
86
 
@@ -136,57 +96,33 @@ const UserProfile = ({
136
96
  setLoading(false)
137
97
  }
138
98
  }
139
-
140
99
  loadUser()
141
100
  }, [userId, userService, logger])
142
101
 
143
102
  if (loading) return <div>Loading...</div>
144
103
  if (!user) return <div>User not found</div>
145
-
146
104
  return <UserCard userData={user} config={{ showEmail: true, variant: 'detailed' }} />
147
105
  }
148
106
 
149
- // ───── Enhanced component with service injection ─────
150
107
  export const UserProfileWithServices = withUserService(UserProfile)
151
108
  ```
152
109
 
153
110
  ## Compound Component Pattern
154
111
 
155
- **Rule**: Use composition for flexible, reusable component APIs.
112
+ Composition for flexible, reusable component APIs.
156
113
 
157
114
  ```typescript
158
- import { createContext, useContext, useState, useEffect, useCallback } from 'react'
159
-
160
- // ───── Context for compound component ─────
161
- interface ModalContextValue {
162
- isOpen: boolean
163
- onClose: () => void
164
- }
165
-
166
- const ModalContext = createContext<ModalContextValue | null>(null)
115
+ const ModalContext = createContext<{ isOpen: boolean; onClose: () => void } | null>(null)
167
116
 
168
117
  const useModalContext = () => {
169
118
  const context = useContext(ModalContext)
170
- if (!context) {
171
- throw new Error('Modal components must be used within Modal')
172
- }
119
+ if (!context) throw new Error('Modal components must be used within Modal')
173
120
  return context
174
121
  }
175
122
 
176
- // ───── Main compound component ─────
177
- interface ModalProps {
178
- isOpen: boolean
179
- onClose: () => void
180
- children: React.ReactNode
181
- }
182
-
183
123
  const Modal = ({ isOpen, onClose, children }: ModalProps) => {
184
- // Keyboard handling (side effect isolated)
185
124
  useEffect(() => {
186
- const handleEscape = (event: KeyboardEvent) => {
187
- if (event.key === 'Escape') onClose()
188
- }
189
-
125
+ const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() }
190
126
  if (isOpen) {
191
127
  document.addEventListener('keydown', handleEscape)
192
128
  return () => document.removeEventListener('keydown', handleEscape)
@@ -206,148 +142,49 @@ const Modal = ({ isOpen, onClose, children }: ModalProps) => {
206
142
  )
207
143
  }
208
144
 
209
- // ───── Compound component parts ─────
210
145
  Modal.Header = ({ children }: { children: React.ReactNode }) => {
211
146
  const { onClose } = useModalContext()
212
-
213
- return (
214
- <div className="modal-header">
215
- {children}
216
- <button onClick={onClose} aria-label="Close">×</button>
217
- </div>
218
- )
147
+ return <div className="modal-header">{children}<button onClick={onClose} aria-label="Close">×</button></div>
219
148
  }
220
-
221
- Modal.Body = ({ children }: { children: React.ReactNode }) => (
222
- <div className="modal-body">{children}</div>
223
- )
224
-
225
- Modal.Footer = ({ children }: { children: React.ReactNode }) => (
226
- <div className="modal-footer">{children}</div>
227
- )
228
-
229
- // ───── Usage - composition over configuration ─────
230
- const UserEditModal = ({ isOpen, onClose, user }: {
231
- isOpen: boolean
232
- onClose: () => void
233
- user: UserData
234
- }) => (
235
- <Modal isOpen={isOpen} onClose={onClose}>
236
- <Modal.Header>Edit User: {user.name}</Modal.Header>
237
- <Modal.Body>
238
- <UserEditForm user={user} />
239
- </Modal.Body>
240
- <Modal.Footer>
241
- <button onClick={onClose}>Cancel</button>
242
- <button type="submit" form="user-edit-form">Save</button>
243
- </Modal.Footer>
244
- </Modal>
245
- )
149
+ Modal.Body = ({ children }: { children: React.ReactNode }) => <div className="modal-body">{children}</div>
150
+ Modal.Footer = ({ children }: { children: React.ReactNode }) => <div className="modal-footer">{children}</div>
246
151
  ```
247
152
 
248
- ## Performance Optimization (Evidence-Based)
249
-
250
- **⚠️ IMPORTANT**: Follow core principles - optimize only when needed with evidence.
153
+ ## Performance (Evidence-Based Only)
251
154
 
252
155
  ```typescript
253
- // ✅ Good - memo for expensive renders
254
- const ExpensiveComponent = memo(({ data }: { data: LargeDataSet }) => {
255
- // Expensive rendering logic
256
- return <ComplexVisualization data={data} />
257
- })
258
-
259
- // ✅ Good - useMemo for expensive computations
260
- const useExpensiveComputation = (largeDataSet: LargeDataSet) => {
261
- const result = useMemo(() => {
262
- return performExpensiveCalculation(largeDataSet) // Only when actually expensive
263
- }, [largeDataSet])
264
-
265
- return result
266
- }
267
-
268
- // ✅ Good - useCallback to prevent prop changes
269
- const Parent = () => {
270
- const [count, setCount] = useState(0)
271
-
272
- const handleClick = useCallback(() => {
273
- setCount(c => c + 1)
274
- }, [])
275
-
276
- return <MemoizedChild onCount={handleClick} />
277
- }
156
+ // ✅ memo for genuinely expensive renders
157
+ const ExpensiveComponent = memo(({ data }: { data: LargeDataSet }) => <ComplexVisualization data={data} />)
278
158
 
279
- // Avoid - unnecessary optimization
280
- const SimpleComponent = memo(({ text }: { text: string }) => <p>{text}</p>) // Not needed
159
+ // useMemo for expensive computations
160
+ const result = useMemo(() => performExpensiveCalculation(largeDataSet), [largeDataSet])
281
161
 
282
- // Avoid - over-using useMemo
283
- const DisplayName = ({ first, last }: { first: string; last: string }) => {
284
- const fullName = useMemo(() => `${first} ${last}`, [first, last]) // Overkill
285
- return <p>{fullName}</p>
286
- }
162
+ // useCallback to stabilize props to memoized children
163
+ const handleClick = useCallback(() => setCount(c => c + 1), [])
287
164
 
288
- // Better - direct computation for simple operations
289
- const DisplayName = ({ first, last }: { first: string; last: string }) => {
290
- const fullName = `${first} ${last}` // Simple, no memo needed
291
- return <p>{fullName}</p>
292
- }
165
+ // memo on trivial components not needed
166
+ // useMemo for simple expressions: `${first} ${last}` just write it inline
167
+ // useCallback when child isn't memoized no benefit
293
168
  ```
294
169
 
295
- ## Testing React FP Components
296
-
297
- ### Test Custom Hooks
170
+ ## Testing
298
171
 
299
172
  ```typescript
300
- // __tests__/useUserLogic.test.ts
173
+ // Hook tests
301
174
  import { renderHook } from '@testing-library/react-hooks'
302
- import { useUserLogic } from '../useUserLogic'
303
175
 
304
176
  describe('useUserLogic', () => {
305
177
  it('processes user data correctly', () => {
306
178
  const { result } = renderHook(() =>
307
- useUserLogic(
308
- { id: '1', name: ' John ', email: 'john@test.com' },
309
- { showEmail: true, variant: 'compact' }
310
- )
179
+ useUserLogic({ id: '1', name: ' John ', email: 'john@test.com' }, { showEmail: true, variant: 'compact' })
311
180
  )
312
-
313
181
  expect(result.current.displayData.displayName).toBe('John')
314
- expect(result.current.displayData.email).toBe('john@test.com')
315
- })
316
-
317
- it('hides email when config.showEmail is false', () => {
318
- const { result } = renderHook(() =>
319
- useUserLogic(
320
- { id: '1', name: 'John', email: 'john@test.com' },
321
- { showEmail: false, variant: 'compact' }
322
- )
323
- )
324
-
325
- expect(result.current.displayData.shouldShowEmail).toBe(false)
182
+ expect(result.current.displayData.shouldShowEmail).toBe(true)
326
183
  })
327
184
  })
328
- ```
329
-
330
- ### Test Components with React Testing Library
331
-
332
- ```typescript
333
- // __tests__/UserCard.test.tsx
334
- import { render, screen, userEvent } from '@testing-library/react'
335
- import UserCard from '../UserCard'
336
185
 
186
+ // Component tests
337
187
  describe('UserCard', () => {
338
- it('renders user data correctly', () => {
339
- render(
340
- <UserCard
341
- userData={{ id: '1', name: 'John', email: 'john@test.com' }}
342
- config={{ showEmail: true, variant: 'compact' }}
343
- onAction={jest.fn()}
344
- />
345
- )
346
-
347
- expect(screen.getByText('John')).toBeInTheDocument()
348
- expect(screen.getByText('john@test.com')).toBeInTheDocument()
349
- })
350
-
351
188
  it('calls onAction when button clicked', async () => {
352
189
  const onAction = jest.fn()
353
190
  render(
@@ -357,91 +194,31 @@ describe('UserCard', () => {
357
194
  onAction={onAction}
358
195
  />
359
196
  )
360
-
361
197
  await userEvent.click(screen.getByRole('button'))
362
198
  expect(onAction).toHaveBeenCalled()
363
199
  })
364
200
  })
365
201
  ```
366
202
 
367
- ## Anti-Patterns (AVOID)
368
-
369
- ### ❌ Overusing Context
370
-
371
- ```typescript
372
- // ❌ Context for local state
373
- const UserContext = createContext<UserData | null>(null)
374
-
375
- // ✅ Props for local state (simpler)
376
- <UserCard userData={user} />
377
- ```
378
-
379
- ### ❌ Premature Memoization
203
+ ## Anti-Patterns
380
204
 
381
- ```typescript
382
- // ❌ Memoizing everything
383
- const Component = () => {
384
- const a = useMemo(() => 1 + 1, []) // Overkill
385
- const b = useMemo(() => 'hello', []) // Overkill
386
- const c = useCallback(() => {}, []) // Overkill when passed to non-memoized children
387
- }
388
-
389
- // ✅ Memoize only when needed
390
- const Component = () => {
391
- const a = 2 // Simple calculation
392
- const b = 'hello' // Simple value
393
- const c = () => {} // Only memo if passed to memoized child
394
- }
395
- ```
205
+ | Pattern | Avoid | Use Instead |
206
+ |---------|-------|-------------|
207
+ | Context for local state | `createContext` + provider for 2-component data | Props |
208
+ | Premature memoization | `useMemo(() => 1 + 1, [])` | Direct computation |
209
+ | `useCallback` on non-memoized children | Adds overhead, no benefit | Plain function |
396
210
 
397
211
  ## Quality Gates
398
212
 
399
- Before implementing any React component:
400
-
401
- 1. **Pure custom hook**: Business logic separated from presentation?
402
- 2. **HOC for DI**: Dependencies injected via HOC when appropriate?
403
- 3. **Appropriate memoization**: Using memo/useMemo/useCallback only when needed?
404
- 4. **Compound components**: Using composition for flexible APIs?
405
- 5. ✅ **Testability**: Can inject mocks for all dependencies?
406
- 6. ✅ **FP principles**: Pure functions, immutable updates?
407
- 7. ✅ **Performance**: Optimized without over-engineering?
408
-
409
- ## When to Load Additional Content
410
-
411
- ### Hooks Advanced
412
- **File**: `references/hooks-advanced.md`
413
- **When**: Complex custom hooks, advanced patterns
414
- **Contains**: Hook composition, state machines, async patterns, effect isolation
415
-
416
- ### Performance Patterns
417
- **File**: `references/performance-patterns.md`
418
- **When**: Performance optimization needed, large lists
419
- **Contains**: React.memo strategies, virtualization, code splitting
420
-
421
- ### Working Examples
422
- **File**: `examples/ProductCard.tsx`
423
- **When**: Need complete working component example
424
- **Contains**: Full ProductCard component with custom hook, types, and exports
425
-
426
- ## Foundation Reference
427
-
428
- **Core FP Principles**: `../js-fp/SKILL.md`
429
- - Purity and side effect isolation
430
- - Composition patterns
431
- - Dependency injection
432
- - Immutability
433
- - Testing strategies
434
-
435
- **Deep Dive**: `../js-fp/core-principles.md` for complete FP philosophy
436
-
437
- ## Success Metrics
438
-
439
- - **Testability**: 100% testable custom hooks
440
- - **Performance**: Appropriate memoization, sub-100ms renders
441
- - **Maintainability**: Clear separation of concerns
442
- - **Code Quality**: Simple, readable component logic
443
- - **Bundle Size**: Tree-shakeable, minimal overhead
213
+ 1. Business logic in custom hook, not component body?
214
+ 2. Dependencies injected via HOC (not imported directly)?
215
+ 3. `memo`/`useMemo`/`useCallback` only where evidence of need?
216
+ 4. Compound components for flexible APIs?
217
+ 5. All hooks testable without rendering full component tree?
218
+ 6. Immutable state updates throughout?
444
219
 
445
- ## Philosophy
220
+ ## References
446
221
 
447
- *"Pure component architecture through custom hooks, HOCs for dependency injection, and appropriate memoization - optimize for testability and simplicity over premature optimization."*
222
+ - `references/hooks-advanced.md` complex hooks, state machines, async patterns
223
+ - `references/performance-patterns.md` — React.memo strategies, virtualization, code splitting
224
+ - `examples/ProductCard.tsx` — complete working component with custom hook