ghcopilot-hub 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 (109) hide show
  1. package/README.md +176 -0
  2. package/hub/agents/README.md +243 -0
  3. package/hub/agents/archiver.agent.md +231 -0
  4. package/hub/agents/explore.agent.md +49 -0
  5. package/hub/agents/implementador.agent.md +176 -0
  6. package/hub/agents/librarian.agent.md +34 -0
  7. package/hub/agents/momus.agent.md +130 -0
  8. package/hub/agents/oracle.agent.md +52 -0
  9. package/hub/agents/plan-guardian.agent.md +109 -0
  10. package/hub/agents/planificador.agent.md +295 -0
  11. package/hub/agents/test-sentinel.agent.md +106 -0
  12. package/hub/base/.github/copilot-instructions.md +10 -0
  13. package/hub/base/.github/instructions/ghcopilot-hub.instructions.md +6 -0
  14. package/hub/base/.github/prompts/ghcopilot-hub-maintenance.prompt.md +8 -0
  15. package/hub/base/.vscode/settings.json +1 -0
  16. package/hub/packs/base-web.json +4 -0
  17. package/hub/packs/nextjs-ssr.json +4 -0
  18. package/hub/packs/node-api.json +4 -0
  19. package/hub/packs/spa-tanstack.json +4 -0
  20. package/hub/skills/architecture-testing/SKILL.md +108 -0
  21. package/hub/skills/architecture-testing/references/archunitts.md +46 -0
  22. package/hub/skills/ghcopilot-hub-consumer/SKILL.md +115 -0
  23. package/hub/skills/ghcopilot-hub-consumer/references/workflow.md +39 -0
  24. package/hub/skills/mermaid-expert/SKILL.md +152 -0
  25. package/hub/skills/mermaid-expert/assets/examples/c4_model.md +121 -0
  26. package/hub/skills/mermaid-expert/assets/examples/flowchart.md +123 -0
  27. package/hub/skills/mermaid-expert/assets/examples/img/base_minimal.png +0 -0
  28. package/hub/skills/mermaid-expert/assets/examples/img/corporate.png +0 -0
  29. package/hub/skills/mermaid-expert/assets/examples/img/dark.png +0 -0
  30. package/hub/skills/mermaid-expert/assets/examples/img/dark_neo.png +0 -0
  31. package/hub/skills/mermaid-expert/assets/examples/img/default_neo.png +0 -0
  32. package/hub/skills/mermaid-expert/assets/examples/img/forest_corp.png +0 -0
  33. package/hub/skills/mermaid-expert/assets/examples/img/handdrawn.png +0 -0
  34. package/hub/skills/mermaid-expert/assets/examples/img/neo.png +0 -0
  35. package/hub/skills/mermaid-expert/assets/examples/img/neutral_sketch.png +0 -0
  36. package/hub/skills/mermaid-expert/assets/examples/img/retro.png +0 -0
  37. package/hub/skills/mermaid-expert/assets/examples/sequence.md +116 -0
  38. package/hub/skills/mermaid-expert/assets/examples/styles_and_looks.md +102 -0
  39. package/hub/skills/mermaid-expert/assets/examples/technical.md +130 -0
  40. package/hub/skills/mermaid-expert/assets/examples.md +57 -0
  41. package/hub/skills/mermaid-expert/references/cheatsheet.md +88 -0
  42. package/hub/skills/mermaid-expert/references/validation.md +66 -0
  43. package/hub/skills/react/SKILL.md +235 -0
  44. package/hub/skills/react/references/common-mistakes.md +518 -0
  45. package/hub/skills/react/references/composition-patterns.md +526 -0
  46. package/hub/skills/react/references/effects-patterns.md +396 -0
  47. package/hub/skills/react/references/react-compiler.md +268 -0
  48. package/hub/skills/react-hook-form/SKILL.md +291 -0
  49. package/hub/skills/react-hook-form/references/field-arrays.md +98 -0
  50. package/hub/skills/react-hook-form/references/integration.md +102 -0
  51. package/hub/skills/react-hook-form/references/performance.md +96 -0
  52. package/hub/skills/skill-creator/SKILL.md +152 -0
  53. package/hub/skills/skill-creator/assets/SKILL-TEMPLATE.md +84 -0
  54. package/hub/skills/skill-judge/README.md +261 -0
  55. package/hub/skills/skill-judge/SKILL.md +806 -0
  56. package/hub/skills/tailwind/SKILL.md +200 -0
  57. package/hub/skills/tanstack/SKILL.md +284 -0
  58. package/hub/skills/tanstack/references/loader-adapter-examples.md +79 -0
  59. package/hub/skills/tanstack/references/query-options-examples.md +115 -0
  60. package/hub/skills/tanstack/references/resilience-patterns.md +110 -0
  61. package/hub/skills/tanstack/references/suspense-consumption-examples.md +82 -0
  62. package/hub/skills/tanstack-query/SKILL.md +241 -0
  63. package/hub/skills/tanstack-query/references/advanced-hooks.md +126 -0
  64. package/hub/skills/tanstack-query/references/best-practices.md +241 -0
  65. package/hub/skills/tanstack-query/references/cache-strategies.md +474 -0
  66. package/hub/skills/tanstack-query/references/common-patterns.md +239 -0
  67. package/hub/skills/tanstack-query/references/migration-v5.md +93 -0
  68. package/hub/skills/tanstack-query/references/resilience-and-mutations.md +63 -0
  69. package/hub/skills/tanstack-query/references/testing.md +116 -0
  70. package/hub/skills/tanstack-query/references/top-errors.md +148 -0
  71. package/hub/skills/tanstack-query/references/typescript.md +176 -0
  72. package/hub/skills/tanstack-router/SKILL.md +145 -0
  73. package/hub/skills/tanstack-router/references/code-splitting.md +31 -0
  74. package/hub/skills/tanstack-router/references/errors-and-boundaries.md +44 -0
  75. package/hub/skills/tanstack-router/references/loaders-and-preload.md +51 -0
  76. package/hub/skills/tanstack-router/references/navigation.md +24 -0
  77. package/hub/skills/tanstack-router/references/private-routes.md +169 -0
  78. package/hub/skills/tanstack-router/references/router-context.md +35 -0
  79. package/hub/skills/tanstack-router/references/search-params.md +29 -0
  80. package/hub/skills/tanstack-router/references/typescript.md +24 -0
  81. package/hub/skills/testing/SKILL.md +187 -0
  82. package/hub/skills/testing/references/assertions.md +64 -0
  83. package/hub/skills/testing/references/async-testing.md +66 -0
  84. package/hub/skills/testing/references/e2e-strategy.md +69 -0
  85. package/hub/skills/testing/references/layer-matrix.md +67 -0
  86. package/hub/skills/testing/references/performance.md +49 -0
  87. package/hub/skills/testing/references/tooling-map.md +81 -0
  88. package/hub/skills/testing/references/zustand-mocking.md +84 -0
  89. package/hub/skills/typescript/SKILL.md +232 -0
  90. package/hub/skills/typescript/references/perf-additional-concerns.md +248 -0
  91. package/hub/skills/typescript/references/perf-execution-cache-locality.md +178 -0
  92. package/hub/skills/typescript/references/reduce-branching.md +147 -0
  93. package/hub/skills/typescript/references/reduce-looping.md +203 -0
  94. package/hub/skills/typescript/references/style-and-types.md +171 -0
  95. package/hub/skills/typescript/references/type-vs-interface.md +27 -0
  96. package/hub/skills/zod/SKILL.md +219 -0
  97. package/hub/skills/zustand/SKILL.md +273 -0
  98. package/package.json +59 -0
  99. package/tooling/cli/src/bin.js +11 -0
  100. package/tooling/cli/src/cli.js +409 -0
  101. package/tooling/cli/src/lib/catalog-loader.js +191 -0
  102. package/tooling/cli/src/lib/constants.js +39 -0
  103. package/tooling/cli/src/lib/errors.js +8 -0
  104. package/tooling/cli/src/lib/frontmatter.js +41 -0
  105. package/tooling/cli/src/lib/fs-utils.js +77 -0
  106. package/tooling/cli/src/lib/managed-header.js +74 -0
  107. package/tooling/cli/src/lib/manifest.js +105 -0
  108. package/tooling/cli/src/lib/resolver.js +53 -0
  109. package/tooling/cli/src/lib/sync-engine.js +262 -0
@@ -0,0 +1,518 @@
1
+ # Common React Mistakes
2
+
3
+ Frequent errors and their fixes.
4
+
5
+ ## Quick Navigation
6
+
7
+ | Symptom | Section |
8
+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
9
+ | Renders `0` unexpectedly | [Conditional Rendering with &&](#conditional-rendering-with-) |
10
+ | Ref misuse during render | [Reading/Writing Refs During Render](#readingwriting-refs-during-render) |
11
+ | Impossible state combinations | [Impossible States](#impossible-states) |
12
+ | Redundant / poorly shaped state | [State Principles](#state-principles) |
13
+ | Hook naming / lifecycle wrappers | [Custom Hooks](#custom-hooks) |
14
+ | Derived/reset logic in effects | [Effects for Derived State](#effects-for-derived-state) and [Effects to Reset State on Prop Change](#effects-to-reset-state-on-prop-change) |
15
+
16
+ ## Conditional Rendering with &&
17
+
18
+ Using a number on the left side of `&&` can render "0" instead of nothing.
19
+
20
+ ```tsx
21
+ // ❌ BUG: Renders "0" when array is empty
22
+ function UserList({ users }: { users: User[] }) {
23
+ return <div>{users.length && users.map((user) => <UserCard key={user.id} user={user} />)}</div>;
24
+ }
25
+ // When users.length is 0, React renders the number 0
26
+ ```
27
+
28
+ ```tsx
29
+ // ✅ FIX: Use explicit comparison
30
+ function UserList({ users }: { users: User[] }) {
31
+ return (
32
+ <div>{users.length > 0 && users.map((user) => <UserCard key={user.id} user={user} />)}</div>
33
+ );
34
+ }
35
+ ```
36
+
37
+ ```tsx
38
+ // ✅ ALSO VALID: Ternary operator
39
+ function UserList({ users }: { users: User[] }) {
40
+ return (
41
+ <div>
42
+ {users.length > 0 ? (
43
+ users.map((user) => <UserCard key={user.id} user={user} />)
44
+ ) : (
45
+ <EmptyState message="No users found" />
46
+ )}
47
+ </div>
48
+ );
49
+ }
50
+ ```
51
+
52
+ **Rule**: Never use values that could be `0`, `""`, `NaN` on the left of `&&`.
53
+
54
+ ---
55
+
56
+ ## Reading/Writing Refs During Render
57
+
58
+ Refs are mutable and accessing them during render breaks React's rendering model.
59
+
60
+ ```tsx
61
+ // ❌ BUG: Writing ref during render
62
+ function Counter() {
63
+ const renderCount = useRef(0);
64
+ renderCount.current += 1; // Side effect during render!
65
+
66
+ return <div>Rendered {renderCount.current} times</div>;
67
+ }
68
+ ```
69
+
70
+ ```tsx
71
+ // ✅ FIX: Use state for render-related values
72
+ function Counter() {
73
+ const [renderCount, setRenderCount] = useState(0);
74
+
75
+ useEffect(() => {
76
+ setRenderCount((prev) => prev + 1);
77
+ }, []);
78
+
79
+ return <div>Rendered {renderCount} times</div>;
80
+ }
81
+ ```
82
+
83
+ ```tsx
84
+ // ✅ FIX: Use refs only in effects/handlers
85
+ function VideoPlayer({ src }: { src: string }) {
86
+ const videoRef = useRef<HTMLVideoElement>(null);
87
+
88
+ // ❌ NEVER: Read during render
89
+ // const isPlaying = !videoRef.current?.paused;
90
+
91
+ // ✅ Read in event handler
92
+ const handleToggle = () => {
93
+ if (videoRef.current?.paused) {
94
+ videoRef.current.play();
95
+ } else {
96
+ videoRef.current?.pause();
97
+ }
98
+ };
99
+
100
+ return <video ref={videoRef} src={src} />;
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## State Updates Based on Previous State
107
+
108
+ Always use the functional update form when new state depends on previous state.
109
+
110
+ ```tsx
111
+ // ❌ BUG: May use stale state in rapid updates
112
+ function Counter() {
113
+ const [count, setCount] = useState(0);
114
+
115
+ const handleClick = () => {
116
+ setCount(count + 1);
117
+ setCount(count + 1); // Both use same stale `count`
118
+ // Result: count increases by 1, not 2
119
+ };
120
+ }
121
+ ```
122
+
123
+ ```tsx
124
+ // ✅ FIX: Use functional updates
125
+ function Counter() {
126
+ const [count, setCount] = useState(0);
127
+
128
+ const handleClick = () => {
129
+ setCount((prev) => prev + 1);
130
+ setCount((prev) => prev + 1); // Uses updated value
131
+ // Result: count increases by 2
132
+ };
133
+ }
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Impossible States
139
+
140
+ Multiple booleans can represent invalid combinations. Prefer a single status union.
141
+
142
+ ```tsx
143
+ // ❌ BUG: Impossible combinations are representable
144
+ function SearchInput() {
145
+ const [isTyping, setIsTyping] = useState(false);
146
+ const [isEmpty, setIsEmpty] = useState(true);
147
+ // isTyping=true and isEmpty=true can happen
148
+ }
149
+
150
+ // ✅ FIX: Single status source of truth
151
+ type InputStatus = "empty" | "typing" | "submitted";
152
+
153
+ function SearchInput() {
154
+ const [status, setStatus] = useState<InputStatus>("empty");
155
+
156
+ const isEmpty = status === "empty";
157
+ const isTyping = status === "typing";
158
+ }
159
+ ```
160
+
161
+ Same strategy applies to async flows:
162
+
163
+ ```tsx
164
+ type FetchStatus = "idle" | "pending" | "success" | "error";
165
+
166
+ function useAsyncData() {
167
+ const [status, setStatus] = useState<FetchStatus>("idle");
168
+
169
+ const isLoading = status === "idle" || status === "pending";
170
+ const isSuccess = status === "success";
171
+ const isError = status === "error";
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ## State Principles
178
+
179
+ ### Group Related State
180
+
181
+ ```tsx
182
+ // ❌ BUG: Separate state that changes together
183
+ const [x, setX] = useState(0);
184
+ const [y, setY] = useState(0);
185
+
186
+ // ✅ FIX: Group in one object
187
+ const [position, setPosition] = useState({ x: 0, y: 0 });
188
+ ```
189
+
190
+ ### Avoid Redundant State
191
+
192
+ ```tsx
193
+ // ❌ BUG: Derived value duplicated in state
194
+ const [firstName, setFirstName] = useState("");
195
+ const [lastName, setLastName] = useState("");
196
+ const [fullName, setFullName] = useState("");
197
+
198
+ // ✅ FIX: Derive during render
199
+ const fullName = `${firstName} ${lastName}`;
200
+ ```
201
+
202
+ ### Reset with `key`
203
+
204
+ ```tsx
205
+ function App() {
206
+ const [formKey, setFormKey] = useState(0);
207
+ const resetForm = () => setFormKey((prev) => prev + 1);
208
+
209
+ return <Form key={formKey} />;
210
+ }
211
+ ```
212
+
213
+ ### Colocate State
214
+
215
+ ```tsx
216
+ // ❌ BUG: State too high, unrelated subtree re-renders
217
+ function App() {
218
+ const [firstName, setFirstName] = useState("");
219
+ return (
220
+ <>
221
+ <input value={firstName} onChange={(e) => setFirstName(e.target.value)} />
222
+ <PageContent />
223
+ </>
224
+ );
225
+ }
226
+
227
+ // ✅ FIX: Move state to the leaf that owns it
228
+ function App() {
229
+ return (
230
+ <>
231
+ <SignupForm />
232
+ <PageContent />
233
+ </>
234
+ );
235
+ }
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Mutating State Directly
241
+
242
+ React only re-renders when state reference changes. Mutating objects/arrays doesn't trigger updates.
243
+
244
+ ```tsx
245
+ // ❌ BUG: Mutating array doesn't trigger re-render
246
+ function TodoList() {
247
+ const [todos, setTodos] = useState<Todo[]>([]);
248
+
249
+ const addTodo = (todo: Todo) => {
250
+ todos.push(todo); // Mutation!
251
+ setTodos(todos); // Same reference, no re-render
252
+ };
253
+ }
254
+ ```
255
+
256
+ ```tsx
257
+ // ✅ FIX: Create new reference
258
+ function TodoList() {
259
+ const [todos, setTodos] = useState<Todo[]>([]);
260
+
261
+ const addTodo = (todo: Todo) => {
262
+ setTodos((prev) => [...prev, todo]); // New array
263
+ };
264
+
265
+ const updateTodo = (id: string, updates: Partial<Todo>) => {
266
+ setTodos((prev) => prev.map((todo) => (todo.id === id ? { ...todo, ...updates } : todo)));
267
+ };
268
+
269
+ const removeTodo = (id: string) => {
270
+ setTodos((prev) => prev.filter((todo) => todo.id !== id));
271
+ };
272
+ }
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Missing Key or Using Index as Key
278
+
279
+ Keys help React identify which items changed. Bad keys cause bugs and performance issues.
280
+
281
+ ```tsx
282
+ // ❌ BUG: Using index as key with reorderable/filterable lists
283
+ {
284
+ todos.map((todo, index) => <TodoItem key={index} todo={todo} />);
285
+ }
286
+ // Problem: Reordering shuffles state between components
287
+ ```
288
+
289
+ ```tsx
290
+ // ❌ BUG: Missing key
291
+ {
292
+ todos.map((todo) => (
293
+ <TodoItem todo={todo} /> // Warning: Each child should have a unique "key"
294
+ ));
295
+ }
296
+ ```
297
+
298
+ ```tsx
299
+ // ✅ FIX: Use stable, unique identifier
300
+ {
301
+ todos.map((todo) => <TodoItem key={todo.id} todo={todo} />);
302
+ }
303
+ ```
304
+
305
+ **When index as key is OK**:
306
+
307
+ - Static lists that never reorder
308
+ - Items have no state
309
+ - List is never filtered
310
+
311
+ ---
312
+
313
+ ## Custom Hooks
314
+
315
+ ### Hooks Share Logic, Not State
316
+
317
+ Each hook call has isolated state.
318
+
319
+ ```tsx
320
+ function StatusBar() {
321
+ const isOnline = useOnlineStatus();
322
+ }
323
+
324
+ function SaveButton() {
325
+ const isOnline = useOnlineStatus();
326
+ }
327
+ ```
328
+
329
+ ### Name `useXxx` Only If It Uses Hooks
330
+
331
+ ```tsx
332
+ // ❌ BUG: Misleading name, no hooks inside
333
+ function useSorted(items: string[]) {
334
+ return items.slice().sort();
335
+ }
336
+
337
+ // ✅ FIX: plain utility name
338
+ function getSorted(items: string[]) {
339
+ return items.slice().sort();
340
+ }
341
+
342
+ // ✅ Valid useXxx
343
+ function useAuth() {
344
+ return useContext(AuthContext);
345
+ }
346
+ ```
347
+
348
+ ### Avoid Lifecycle Wrapper Hooks
349
+
350
+ ```tsx
351
+ // ❌ BUG: Hides dependencies from linter
352
+ function useMount(fn: () => void) {
353
+ useEffect(() => {
354
+ fn();
355
+ }, []);
356
+ }
357
+
358
+ // ✅ FIX: Keep dependency checks explicit at call site
359
+ useEffect(() => {
360
+ doSomething();
361
+ }, [doSomething]);
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Effects for Derived State
367
+
368
+ Don't use Effects to compute values that can be calculated during render.
369
+
370
+ ```tsx
371
+ // ❌ BUG: Effect for derived state
372
+ const [firstName, setFirstName] = useState("Taylor");
373
+ const [lastName, setLastName] = useState("Swift");
374
+ const [fullName, setFullName] = useState("");
375
+
376
+ useEffect(() => {
377
+ setFullName(firstName + " " + lastName);
378
+ }, [firstName, lastName]);
379
+
380
+ // ✅ FIX: Calculate during render
381
+ const [firstName, setFirstName] = useState("Taylor");
382
+ const [lastName, setLastName] = useState("Swift");
383
+ const fullName = firstName + " " + lastName;
384
+ ```
385
+
386
+ ---
387
+
388
+ ## Effects to Reset State on Prop Change
389
+
390
+ Don't use Effects to reset state when props change. Use the `key` prop.
391
+
392
+ ```tsx
393
+ // ❌ BUG: Effect to reset state
394
+ function ProfilePage({ userId }: { userId: string }) {
395
+ const [comment, setComment] = useState("");
396
+
397
+ useEffect(() => {
398
+ setComment("");
399
+ }, [userId]);
400
+ // ...
401
+ }
402
+
403
+ // ✅ FIX: Use key to reset component state
404
+ function ProfilePage({ userId }: { userId: string }) {
405
+ return <Profile userId={userId} key={userId} />;
406
+ }
407
+
408
+ function Profile({ userId }: { userId: string }) {
409
+ const [comment, setComment] = useState(""); // Resets automatically
410
+ // ...
411
+ }
412
+ ```
413
+
414
+ ---
415
+
416
+ ## useEffect for Data Fetching
417
+
418
+ Don't use `useEffect` for data fetching in components. Use TanStack Query with loaders.
419
+
420
+ ```tsx
421
+ // ❌ ANTI-PATTERN: useEffect for data fetching
422
+ function ProductList() {
423
+ const [products, setProducts] = useState<Product[]>([]);
424
+ const [loading, setLoading] = useState(true);
425
+
426
+ useEffect(() => {
427
+ fetchProducts().then((data) => {
428
+ setProducts(data);
429
+ setLoading(false);
430
+ });
431
+ }, []);
432
+
433
+ if (loading) return <Skeleton />;
434
+ return <List products={products} />;
435
+ }
436
+ ```
437
+
438
+ ```tsx
439
+ // ✅ PATTERN: Use TanStack Query with Suspense (per project architecture)
440
+ // 1. Define query in application layer
441
+ // application/product/product.queries.ts
442
+ export const productQueries = {
443
+ list: () =>
444
+ queryOptions({
445
+ queryKey: ["products"],
446
+ queryFn: () => productRepository.getAll(),
447
+ }),
448
+ };
449
+
450
+ // 2. Load in router loader
451
+ // interface/router/routes/product/productList.route.tsx
452
+ export const productListRoute = createRoute({
453
+ path: "/products",
454
+ loader: () => queryClient.ensureQueryData(productQueries.list()),
455
+ component: ProductListPage,
456
+ });
457
+
458
+ // 3. Consume with Suspense query
459
+ // presentation/product/ProductList.page.tsx
460
+ function ProductListPage() {
461
+ const { data: products } = useSuspenseQuery(productQueries.list());
462
+ return <ProductList products={products} />;
463
+ }
464
+ ```
465
+
466
+ ---
467
+
468
+ ## Overusing Context
469
+
470
+ Don't use React Context for frequently changing values. It re-renders all consumers.
471
+
472
+ ```tsx
473
+ // ❌ PERFORMANCE ISSUE: Context for frequently changing state
474
+ const MousePositionContext = createContext({ x: 0, y: 0 });
475
+
476
+ function App() {
477
+ const [position, setPosition] = useState({ x: 0, y: 0 });
478
+
479
+ return (
480
+ <MousePositionContext.Provider value={position}>
481
+ {/* ALL consumers re-render on every mouse move */}
482
+ <div onMouseMove={(e) => setPosition({ x: e.clientX, y: e.clientY })}>
483
+ <Header />
484
+ <Content />
485
+ <Footer />
486
+ </div>
487
+ </MousePositionContext.Provider>
488
+ );
489
+ }
490
+ ```
491
+
492
+ ```tsx
493
+ // ✅ FIX: Use Zustand for frequently changing client state
494
+ // application/shared/store/mouse.store.ts
495
+ export const useMouseStore = create<MouseState>()((set) => ({
496
+ position: { x: 0, y: 0 },
497
+ setPosition: (x: number, y: number) => set({ position: { x, y } }),
498
+ }));
499
+
500
+ // Components subscribe to specific slices
501
+ function Cursor() {
502
+ const position = useMouseStore((state) => state.position);
503
+ return <div style={{ left: position.x, top: position.y }} />;
504
+ }
505
+ ```
506
+
507
+ **Use Context for**:
508
+
509
+ - Themes
510
+ - Locale/i18n
511
+ - Auth state (rarely changes)
512
+ - Feature flags
513
+
514
+ **Use Zustand for**:
515
+
516
+ - Frequently updating values
517
+ - Complex client state
518
+ - State shared across many components