mcp-probe-kit 3.0.14 → 3.0.16

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 (43) hide show
  1. package/README.md +17 -11
  2. package/build/lib/__tests__/gitnexus-bridge.unit.test.js +9 -1
  3. package/build/lib/gitnexus-bridge.d.ts +1 -0
  4. package/build/lib/gitnexus-bridge.js +29 -1
  5. package/build/lib/skill-bridge.d.ts +31 -0
  6. package/build/lib/skill-bridge.js +100 -0
  7. package/build/resources/ui-ux-data/charts.json +302 -0
  8. package/build/resources/ui-ux-data/colors.json +1058 -0
  9. package/build/resources/ui-ux-data/icons.json +1102 -0
  10. package/build/resources/ui-ux-data/landing.json +262 -0
  11. package/build/resources/ui-ux-data/metadata.json +6 -0
  12. package/build/resources/ui-ux-data/products.json +1058 -0
  13. package/build/resources/ui-ux-data/react-performance.json +574 -0
  14. package/build/resources/ui-ux-data/stacks/astro.json +266 -0
  15. package/build/resources/ui-ux-data/stacks/flutter.json +626 -0
  16. package/build/resources/ui-ux-data/stacks/html-tailwind.json +662 -0
  17. package/build/resources/ui-ux-data/stacks/jetpack-compose.json +626 -0
  18. package/build/resources/ui-ux-data/stacks/nextjs.json +218 -0
  19. package/build/resources/ui-ux-data/stacks/nuxt-ui.json +14 -0
  20. package/build/resources/ui-ux-data/stacks/nuxtjs.json +182 -0
  21. package/build/resources/ui-ux-data/stacks/react-native.json +350 -0
  22. package/build/resources/ui-ux-data/stacks/react.json +530 -0
  23. package/build/resources/ui-ux-data/stacks/shadcn.json +566 -0
  24. package/build/resources/ui-ux-data/stacks/svelte.json +134 -0
  25. package/build/resources/ui-ux-data/stacks/swiftui.json +26 -0
  26. package/build/resources/ui-ux-data/stacks/vue.json +170 -0
  27. package/build/resources/ui-ux-data/styles.json +1610 -0
  28. package/build/resources/ui-ux-data/typography.json +743 -0
  29. package/build/resources/ui-ux-data/ui-reasoning.json +1431 -0
  30. package/build/resources/ui-ux-data/ux-guidelines.json +1190 -0
  31. package/build/resources/ui-ux-data/web-interface.json +389 -0
  32. package/build/schemas/ui-ux-schemas.js +1 -1
  33. package/build/tools/start_product.js +8 -1
  34. package/build/tools/start_ui.js +14 -3
  35. package/build/tools/ui-ux-tools.js +21 -17
  36. package/build/utils/ui-data-loader.d.ts +18 -2
  37. package/build/utils/ui-data-loader.js +74 -12
  38. package/docs/i18n/en.json +4 -2
  39. package/docs/i18n/ja.json +4 -2
  40. package/docs/i18n/ko.json +4 -2
  41. package/docs/i18n/zh-CN.json +4 -2
  42. package/docs/pages/getting-started.html +3 -0
  43. package/package.json +2 -1
@@ -0,0 +1,574 @@
1
+ [
2
+ {
3
+ "No": "1",
4
+ "Category": "Async Waterfall",
5
+ "Issue": "Defer Await",
6
+ "Keywords": "async await defer branch",
7
+ "Platform": "React/Next.js",
8
+ "Description": "Move await into branches where actually used to avoid blocking unused code paths",
9
+ "Do": "Move await operations into branches where they're needed",
10
+ "Don't": "Await at top of function blocking all branches",
11
+ "Code Example Good": "if (skip) return { skipped: true }; const data = await fetch()",
12
+ "Code Example Bad": "const data = await fetch(); if (skip) return { skipped: true }",
13
+ "Severity": "Critical"
14
+ },
15
+ {
16
+ "No": "2",
17
+ "Category": "Async Waterfall",
18
+ "Issue": "Promise.all Parallel",
19
+ "Keywords": "promise all parallel concurrent",
20
+ "Platform": "React/Next.js",
21
+ "Description": "Execute independent async operations concurrently using Promise.all()",
22
+ "Do": "Use Promise.all() for independent operations",
23
+ "Don't": "Sequential await for independent operations",
24
+ "Code Example Good": "const [user, posts] = await Promise.all([fetchUser(), fetchPosts()])",
25
+ "Code Example Bad": "const user = await fetchUser(); const posts = await fetchPosts()",
26
+ "Severity": "Critical"
27
+ },
28
+ {
29
+ "No": "3",
30
+ "Category": "Async Waterfall",
31
+ "Issue": "Dependency Parallelization",
32
+ "Keywords": "better-all dependency parallel",
33
+ "Platform": "React/Next.js",
34
+ "Description": "Use better-all for operations with partial dependencies to maximize parallelism",
35
+ "Do": "Use better-all to start each task at earliest possible moment",
36
+ "Don't": "Wait for unrelated data before starting dependent fetch",
37
+ "Code Example Good": "await all({ user() {}, config() {}, profile() { return fetch((await this.$.user).id) } })",
38
+ "Code Example Bad": "const [user, config] = await Promise.all([...]); const profile = await fetchProfile(user.id)",
39
+ "Severity": "Critical"
40
+ },
41
+ {
42
+ "No": "4",
43
+ "Category": "Async Waterfall",
44
+ "Issue": "API Route Optimization",
45
+ "Keywords": "api route waterfall promise",
46
+ "Platform": "React/Next.js",
47
+ "Description": "In API routes start independent operations immediately even if not awaited yet",
48
+ "Do": "Start promises early and await late",
49
+ "Don't": "Sequential awaits in API handlers",
50
+ "Code Example Good": "const sessionP = auth(); const configP = fetchConfig(); const session = await sessionP",
51
+ "Code Example Bad": "const session = await auth(); const config = await fetchConfig()",
52
+ "Severity": "Critical"
53
+ },
54
+ {
55
+ "No": "5",
56
+ "Category": "Async Waterfall",
57
+ "Issue": "Suspense Boundaries",
58
+ "Keywords": "suspense streaming boundary",
59
+ "Platform": "React/Next.js",
60
+ "Description": "Use Suspense to show wrapper UI faster while data loads",
61
+ "Do": "Wrap async components in Suspense boundaries",
62
+ "Don't": "Await data blocking entire page render",
63
+ "Code Example Good": "<Suspense fallback={<Skeleton />}><DataDisplay /></Suspense>",
64
+ "Code Example Bad": "const data = await fetchData(); return <DataDisplay data={data} />",
65
+ "Severity": "High"
66
+ },
67
+ {
68
+ "No": "6",
69
+ "Category": "Bundle Size",
70
+ "Issue": "Barrel Imports",
71
+ "Keywords": "barrel import direct path",
72
+ "Platform": "React/Next.js",
73
+ "Description": "Import directly from source files instead of barrel files to avoid loading unused modules",
74
+ "Do": "Import directly from source path",
75
+ "Don't": "Import from barrel/index files",
76
+ "Code Example Good": "import Check from 'lucide-react/dist/esm/icons/check'",
77
+ "Code Example Bad": "import { Check } from 'lucide-react'",
78
+ "Severity": "Critical"
79
+ },
80
+ {
81
+ "No": "7",
82
+ "Category": "Bundle Size",
83
+ "Issue": "Dynamic Imports",
84
+ "Keywords": "dynamic import lazy next",
85
+ "Platform": "React/Next.js",
86
+ "Description": "Use next/dynamic to lazy-load large components not needed on initial render",
87
+ "Do": "Use dynamic() for heavy components",
88
+ "Don't": "Import heavy components at top level",
89
+ "Code Example Good": "const Monaco = dynamic(() => import('./monaco'), { ssr: false })",
90
+ "Code Example Bad": "import { MonacoEditor } from './monaco-editor'",
91
+ "Severity": "Critical"
92
+ },
93
+ {
94
+ "No": "8",
95
+ "Category": "Bundle Size",
96
+ "Issue": "Defer Third Party",
97
+ "Keywords": "analytics defer third-party",
98
+ "Platform": "React/Next.js",
99
+ "Description": "Load analytics and logging after hydration since they don't block interaction",
100
+ "Do": "Load non-critical scripts after hydration",
101
+ "Don't": "Include analytics in main bundle",
102
+ "Code Example Good": "const Analytics = dynamic(() => import('@vercel/analytics'), { ssr: false })",
103
+ "Code Example Bad": "import { Analytics } from '@vercel/analytics/react'",
104
+ "Severity": "Medium"
105
+ },
106
+ {
107
+ "No": "9",
108
+ "Category": "Bundle Size",
109
+ "Issue": "Conditional Loading",
110
+ "Keywords": "conditional module lazy",
111
+ "Platform": "React/Next.js",
112
+ "Description": "Load large data or modules only when a feature is activated",
113
+ "Do": "Dynamic import when feature enabled",
114
+ "Don't": "Import large modules unconditionally",
115
+ "Code Example Good": "useEffect(() => { if (enabled) import('./heavy.js') }, [enabled])",
116
+ "Code Example Bad": "import { heavyData } from './heavy.js'",
117
+ "Severity": "High"
118
+ },
119
+ {
120
+ "No": "10",
121
+ "Category": "Bundle Size",
122
+ "Issue": "Preload Intent",
123
+ "Keywords": "preload hover focus intent",
124
+ "Platform": "React/Next.js",
125
+ "Description": "Preload heavy bundles on hover/focus before they're needed",
126
+ "Do": "Preload on user intent signals",
127
+ "Don't": "Load only on click",
128
+ "Code Example Good": "onMouseEnter={() => import('./editor')}",
129
+ "Code Example Bad": "onClick={() => import('./editor')}",
130
+ "Severity": "Medium"
131
+ },
132
+ {
133
+ "No": "11",
134
+ "Category": "Server",
135
+ "Issue": "React.cache Dedup",
136
+ "Keywords": "react cache deduplicate request",
137
+ "Platform": "React/Next.js",
138
+ "Description": "Use React.cache() for server-side request deduplication within single request",
139
+ "Do": "Wrap data fetchers with cache()",
140
+ "Don't": "Fetch same data multiple times in tree",
141
+ "Code Example Good": "export const getUser = cache(async () => await db.user.find())",
142
+ "Code Example Bad": "export async function getUser() { return await db.user.find() }",
143
+ "Severity": "Medium"
144
+ },
145
+ {
146
+ "No": "12",
147
+ "Category": "Server",
148
+ "Issue": "LRU Cache Cross-Request",
149
+ "Keywords": "lru cache cross request",
150
+ "Platform": "React/Next.js",
151
+ "Description": "Use LRU cache for data shared across sequential requests",
152
+ "Do": "Use LRU for cross-request caching",
153
+ "Don't": "Refetch same data on every request",
154
+ "Code Example Good": "const cache = new LRUCache({ max: 1000, ttl: 5*60*1000 })",
155
+ "Code Example Bad": "Always fetch from database",
156
+ "Severity": "High"
157
+ },
158
+ {
159
+ "No": "13",
160
+ "Category": "Server",
161
+ "Issue": "Minimize Serialization",
162
+ "Keywords": "serialization rsc boundary",
163
+ "Platform": "React/Next.js",
164
+ "Description": "Only pass fields that client actually uses across RSC boundaries",
165
+ "Do": "Pass only needed fields to client components",
166
+ "Don't": "Pass entire objects to client",
167
+ "Code Example Good": "<Profile name={user.name} />",
168
+ "Code Example Bad": "<Profile user={user} /> // 50 fields serialized",
169
+ "Severity": "High"
170
+ },
171
+ {
172
+ "No": "14",
173
+ "Category": "Server",
174
+ "Issue": "Parallel Fetching",
175
+ "Keywords": "parallel fetch component composition",
176
+ "Platform": "React/Next.js",
177
+ "Description": "Restructure components to parallelize data fetching in RSC",
178
+ "Do": "Use component composition for parallel fetches",
179
+ "Don't": "Sequential fetches in parent component",
180
+ "Code Example Good": "<Header /><Sidebar /> // both fetch in parallel",
181
+ "Code Example Bad": "const header = await fetchHeader(); return <><div>{header}</div><Sidebar /></>",
182
+ "Severity": "Critical"
183
+ },
184
+ {
185
+ "No": "15",
186
+ "Category": "Server",
187
+ "Issue": "After Non-blocking",
188
+ "Keywords": "after non-blocking logging",
189
+ "Platform": "React/Next.js",
190
+ "Description": "Use Next.js after() to schedule work after response is sent",
191
+ "Do": "Use after() for logging/analytics",
192
+ "Don't": "Block response for non-critical operations",
193
+ "Code Example Good": "after(async () => { await logAction() }); return Response.json(data)",
194
+ "Code Example Bad": "await logAction(); return Response.json(data)",
195
+ "Severity": "Medium"
196
+ },
197
+ {
198
+ "No": "16",
199
+ "Category": "Client",
200
+ "Issue": "SWR Deduplication",
201
+ "Keywords": "swr dedup cache revalidate",
202
+ "Platform": "React/Next.js",
203
+ "Description": "Use SWR for automatic request deduplication and caching",
204
+ "Do": "Use useSWR for client data fetching",
205
+ "Don't": "Manual fetch in useEffect",
206
+ "Code Example Good": "const { data } = useSWR('/api/users', fetcher)",
207
+ "Code Example Bad": "useEffect(() => { fetch('/api/users').then(setUsers) }, [])",
208
+ "Severity": "Medium-High"
209
+ },
210
+ {
211
+ "No": "17",
212
+ "Category": "Client",
213
+ "Issue": "Event Listener Dedup",
214
+ "Keywords": "event listener deduplicate global",
215
+ "Platform": "React/Next.js",
216
+ "Description": "Share global event listeners across component instances",
217
+ "Do": "Use useSWRSubscription for shared listeners",
218
+ "Don't": "Register listener per component instance",
219
+ "Code Example Good": "useSWRSubscription('global-keydown', () => { window.addEventListener... })",
220
+ "Code Example Bad": "useEffect(() => { window.addEventListener('keydown', handler) }, [])",
221
+ "Severity": "Low"
222
+ },
223
+ {
224
+ "No": "18",
225
+ "Category": "Rerender",
226
+ "Issue": "Defer State Reads",
227
+ "Keywords": "state read callback subscription",
228
+ "Platform": "React/Next.js",
229
+ "Description": "Don't subscribe to state only used in callbacks",
230
+ "Do": "Read state on-demand in callbacks",
231
+ "Don't": "Subscribe to state used only in handlers",
232
+ "Code Example Good": "const handleClick = () => { const params = new URLSearchParams(location.search) }",
233
+ "Code Example Bad": "const params = useSearchParams(); const handleClick = () => { params.get('ref') }",
234
+ "Severity": "Medium"
235
+ },
236
+ {
237
+ "No": "19",
238
+ "Category": "Rerender",
239
+ "Issue": "Memoized Components",
240
+ "Keywords": "memo extract expensive",
241
+ "Platform": "React/Next.js",
242
+ "Description": "Extract expensive work into memoized components for early returns",
243
+ "Do": "Extract to memo() components",
244
+ "Don't": "Compute expensive values before early return",
245
+ "Code Example Good": "const UserAvatar = memo(({ user }) => ...); if (loading) return <Skeleton />",
246
+ "Code Example Bad": "const avatar = useMemo(() => compute(user)); if (loading) return <Skeleton />",
247
+ "Severity": "Medium"
248
+ },
249
+ {
250
+ "No": "20",
251
+ "Category": "Rerender",
252
+ "Issue": "Narrow Dependencies",
253
+ "Keywords": "effect dependency primitive",
254
+ "Platform": "React/Next.js",
255
+ "Description": "Specify primitive dependencies instead of objects in effects",
256
+ "Do": "Use primitive values in dependency arrays",
257
+ "Don't": "Use object references as dependencies",
258
+ "Code Example Good": "useEffect(() => { console.log(user.id) }, [user.id])",
259
+ "Code Example Bad": "useEffect(() => { console.log(user.id) }, [user])",
260
+ "Severity": "Low"
261
+ },
262
+ {
263
+ "No": "21",
264
+ "Category": "Rerender",
265
+ "Issue": "Derived State",
266
+ "Keywords": "derived boolean subscription",
267
+ "Platform": "React/Next.js",
268
+ "Description": "Subscribe to derived booleans instead of continuous values",
269
+ "Do": "Use derived boolean state",
270
+ "Don't": "Subscribe to continuous values",
271
+ "Code Example Good": "const isMobile = useMediaQuery('(max-width: 767px)')",
272
+ "Code Example Bad": "const width = useWindowWidth(); const isMobile = width < 768",
273
+ "Severity": "Medium"
274
+ },
275
+ {
276
+ "No": "22",
277
+ "Category": "Rerender",
278
+ "Issue": "Functional setState",
279
+ "Keywords": "functional setstate callback",
280
+ "Platform": "React/Next.js",
281
+ "Description": "Use functional setState updates for stable callbacks and no stale closures",
282
+ "Do": "Use functional form: setState(curr => ...)",
283
+ "Don't": "Reference state directly in setState",
284
+ "Code Example Good": "setItems(curr => [...curr, newItem])",
285
+ "Code Example Bad": "setItems([...items, newItem]) // items in deps",
286
+ "Severity": "Medium"
287
+ },
288
+ {
289
+ "No": "23",
290
+ "Category": "Rerender",
291
+ "Issue": "Lazy State Init",
292
+ "Keywords": "usestate lazy initialization",
293
+ "Platform": "React/Next.js",
294
+ "Description": "Pass function to useState for expensive initial values",
295
+ "Do": "Use function form for expensive init",
296
+ "Don't": "Compute expensive value directly",
297
+ "Code Example Good": "useState(() => buildSearchIndex(items))",
298
+ "Code Example Bad": "useState(buildSearchIndex(items)) // runs every render",
299
+ "Severity": "Medium"
300
+ },
301
+ {
302
+ "No": "24",
303
+ "Category": "Rerender",
304
+ "Issue": "Transitions",
305
+ "Keywords": "starttransition non-urgent",
306
+ "Platform": "React/Next.js",
307
+ "Description": "Mark frequent non-urgent state updates as transitions",
308
+ "Do": "Use startTransition for non-urgent updates",
309
+ "Don't": "Block UI on every state change",
310
+ "Code Example Good": "startTransition(() => setScrollY(window.scrollY))",
311
+ "Code Example Bad": "setScrollY(window.scrollY) // blocks on every scroll",
312
+ "Severity": "Medium"
313
+ },
314
+ {
315
+ "No": "25",
316
+ "Category": "Rendering",
317
+ "Issue": "SVG Animation Wrapper",
318
+ "Keywords": "svg animation wrapper div",
319
+ "Platform": "React/Next.js",
320
+ "Description": "Wrap SVG in div and animate wrapper for hardware acceleration",
321
+ "Do": "Animate div wrapper around SVG",
322
+ "Don't": "Animate SVG element directly",
323
+ "Code Example Good": "<div class='animate-spin'><svg>...</svg></div>",
324
+ "Code Example Bad": "<svg class='animate-spin'>...</svg>",
325
+ "Severity": "Low"
326
+ },
327
+ {
328
+ "No": "26",
329
+ "Category": "Rendering",
330
+ "Issue": "Content Visibility",
331
+ "Keywords": "content-visibility auto",
332
+ "Platform": "React/Next.js",
333
+ "Description": "Apply content-visibility: auto to defer off-screen rendering",
334
+ "Do": "Use content-visibility for long lists",
335
+ "Don't": "Render all list items immediately",
336
+ "Code Example Good": ".item { content-visibility: auto; contain-intrinsic-size: 0 80px }",
337
+ "Code Example Bad": "Render 1000 items without optimization",
338
+ "Severity": "High"
339
+ },
340
+ {
341
+ "No": "27",
342
+ "Category": "Rendering",
343
+ "Issue": "Hoist Static JSX",
344
+ "Keywords": "hoist static jsx element",
345
+ "Platform": "React/Next.js",
346
+ "Description": "Extract static JSX outside components to avoid re-creation",
347
+ "Do": "Hoist static elements to module scope",
348
+ "Don't": "Create static elements inside components",
349
+ "Code Example Good": "const skeleton = <div class='animate-pulse' />; function C() { return skeleton }",
350
+ "Code Example Bad": "function C() { return <div class='animate-pulse' /> }",
351
+ "Severity": "Low"
352
+ },
353
+ {
354
+ "No": "28",
355
+ "Category": "Rendering",
356
+ "Issue": "Hydration No Flicker",
357
+ "Keywords": "hydration mismatch flicker",
358
+ "Platform": "React/Next.js",
359
+ "Description": "Use inline script to set client-only data before hydration",
360
+ "Do": "Inject sync script for client-only values",
361
+ "Don't": "Use useEffect causing flash",
362
+ "Code Example Good": "<script dangerouslySetInnerHTML={{ __html: 'el.className = localStorage.theme' }} />",
363
+ "Code Example Bad": "useEffect(() => setTheme(localStorage.theme), []) // flickers",
364
+ "Severity": "Medium"
365
+ },
366
+ {
367
+ "No": "29",
368
+ "Category": "Rendering",
369
+ "Issue": "Conditional Render",
370
+ "Keywords": "conditional render ternary",
371
+ "Platform": "React/Next.js",
372
+ "Description": "Use ternary instead of && when condition can be 0 or NaN",
373
+ "Do": "Use explicit ternary for conditionals",
374
+ "Don't": "Use && with potentially falsy numbers",
375
+ "Code Example Good": "{count > 0 ? <Badge>{count}</Badge> : null}",
376
+ "Code Example Bad": "{count && <Badge>{count}</Badge>} // renders '0'",
377
+ "Severity": "Low"
378
+ },
379
+ {
380
+ "No": "30",
381
+ "Category": "Rendering",
382
+ "Issue": "Activity Component",
383
+ "Keywords": "activity show hide preserve",
384
+ "Platform": "React/Next.js",
385
+ "Description": "Use Activity component to preserve state/DOM for toggled components",
386
+ "Do": "Use Activity for expensive toggle components",
387
+ "Don't": "Unmount/remount on visibility toggle",
388
+ "Code Example Good": "<Activity mode={isOpen ? 'visible' : 'hidden'}><Menu /></Activity>",
389
+ "Code Example Bad": "{isOpen && <Menu />} // loses state",
390
+ "Severity": "Medium"
391
+ },
392
+ {
393
+ "No": "31",
394
+ "Category": "JS Perf",
395
+ "Issue": "Batch DOM CSS",
396
+ "Keywords": "batch dom css reflow",
397
+ "Platform": "React/Next.js",
398
+ "Description": "Group CSS changes via classes or cssText to minimize reflows",
399
+ "Do": "Use class toggle or cssText",
400
+ "Don't": "Change styles one property at a time",
401
+ "Code Example Good": "element.classList.add('highlighted')",
402
+ "Code Example Bad": "el.style.width='100px'; el.style.height='200px'",
403
+ "Severity": "Medium"
404
+ },
405
+ {
406
+ "No": "32",
407
+ "Category": "JS Perf",
408
+ "Issue": "Index Map Lookup",
409
+ "Keywords": "map index lookup find",
410
+ "Platform": "React/Next.js",
411
+ "Description": "Build Map for repeated lookups instead of multiple .find() calls",
412
+ "Do": "Build index Map for O(1) lookups",
413
+ "Don't": "Use .find() in loops",
414
+ "Code Example Good": "const byId = new Map(users.map(u => [u.id, u])); byId.get(id)",
415
+ "Code Example Bad": "users.find(u => u.id === order.userId) // O(n) each time",
416
+ "Severity": "Low-Medium"
417
+ },
418
+ {
419
+ "No": "33",
420
+ "Category": "JS Perf",
421
+ "Issue": "Cache Property Access",
422
+ "Keywords": "cache property loop",
423
+ "Platform": "React/Next.js",
424
+ "Description": "Cache object property lookups in hot paths",
425
+ "Do": "Cache values before loops",
426
+ "Don't": "Access nested properties in loops",
427
+ "Code Example Good": "const val = obj.config.settings.value; for (...) process(val)",
428
+ "Code Example Bad": "for (...) process(obj.config.settings.value)",
429
+ "Severity": "Low-Medium"
430
+ },
431
+ {
432
+ "No": "34",
433
+ "Category": "JS Perf",
434
+ "Issue": "Cache Function Results",
435
+ "Keywords": "memoize cache function",
436
+ "Platform": "React/Next.js",
437
+ "Description": "Use module-level Map to cache repeated function results",
438
+ "Do": "Use Map cache for repeated calls",
439
+ "Don't": "Recompute same values repeatedly",
440
+ "Code Example Good": "const cache = new Map(); if (cache.has(x)) return cache.get(x)",
441
+ "Code Example Bad": "slugify(name) // called 100 times same input",
442
+ "Severity": "Medium"
443
+ },
444
+ {
445
+ "No": "35",
446
+ "Category": "JS Perf",
447
+ "Issue": "Cache Storage API",
448
+ "Keywords": "localstorage cache read",
449
+ "Platform": "React/Next.js",
450
+ "Description": "Cache localStorage/sessionStorage reads in memory",
451
+ "Do": "Cache storage reads in Map",
452
+ "Don't": "Read storage on every call",
453
+ "Code Example Good": "if (!cache.has(key)) cache.set(key, localStorage.getItem(key))",
454
+ "Code Example Bad": "localStorage.getItem('theme') // every call",
455
+ "Severity": "Low-Medium"
456
+ },
457
+ {
458
+ "No": "36",
459
+ "Category": "JS Perf",
460
+ "Issue": "Combine Iterations",
461
+ "Keywords": "combine filter map loop",
462
+ "Platform": "React/Next.js",
463
+ "Description": "Combine multiple filter/map into single loop",
464
+ "Do": "Single loop for multiple categorizations",
465
+ "Don't": "Chain multiple filter() calls",
466
+ "Code Example Good": "for (u of users) { if (u.isAdmin) admins.push(u); if (u.isTester) testers.push(u) }",
467
+ "Code Example Bad": "users.filter(admin); users.filter(tester); users.filter(inactive)",
468
+ "Severity": "Low-Medium"
469
+ },
470
+ {
471
+ "No": "37",
472
+ "Category": "JS Perf",
473
+ "Issue": "Length Check First",
474
+ "Keywords": "length check array compare",
475
+ "Platform": "React/Next.js",
476
+ "Description": "Check array lengths before expensive comparisons",
477
+ "Do": "Early return if lengths differ",
478
+ "Don't": "Always run expensive comparison",
479
+ "Code Example Good": "if (a.length !== b.length) return true; // then compare",
480
+ "Code Example Bad": "a.sort().join() !== b.sort().join() // even when lengths differ",
481
+ "Severity": "Medium-High"
482
+ },
483
+ {
484
+ "No": "38",
485
+ "Category": "JS Perf",
486
+ "Issue": "Early Return",
487
+ "Keywords": "early return exit function",
488
+ "Platform": "React/Next.js",
489
+ "Description": "Return early when result is determined to skip processing",
490
+ "Do": "Return immediately on first error",
491
+ "Don't": "Process all items then check errors",
492
+ "Code Example Good": "for (u of users) { if (!u.email) return { error: 'Email required' } }",
493
+ "Code Example Bad": "let hasError; for (...) { if (!email) hasError=true }; if (hasError)...",
494
+ "Severity": "Low-Medium"
495
+ },
496
+ {
497
+ "No": "39",
498
+ "Category": "JS Perf",
499
+ "Issue": "Hoist RegExp",
500
+ "Keywords": "regexp hoist module",
501
+ "Platform": "React/Next.js",
502
+ "Description": "Don't create RegExp inside render - hoist or memoize",
503
+ "Do": "Hoist RegExp to module scope",
504
+ "Don't": "Create RegExp every render",
505
+ "Code Example Good": "const EMAIL_RE = /^[^@]+@[^@]+$/; function validate() { EMAIL_RE.test(x) }",
506
+ "Code Example Bad": "function C() { const re = new RegExp(pattern); re.test(x) }",
507
+ "Severity": "Low-Medium"
508
+ },
509
+ {
510
+ "No": "40",
511
+ "Category": "JS Perf",
512
+ "Issue": "Loop Min Max",
513
+ "Keywords": "loop min max sort",
514
+ "Platform": "React/Next.js",
515
+ "Description": "Use loop for min/max instead of sort - O(n) vs O(n log n)",
516
+ "Do": "Single pass loop for min/max",
517
+ "Don't": "Sort array to find min/max",
518
+ "Code Example Good": "let max = arr[0]; for (x of arr) if (x > max) max = x",
519
+ "Code Example Bad": "arr.sort((a,b) => b-a)[0] // O(n log n)",
520
+ "Severity": "Low"
521
+ },
522
+ {
523
+ "No": "41",
524
+ "Category": "JS Perf",
525
+ "Issue": "Set Map Lookups",
526
+ "Keywords": "set map includes has",
527
+ "Platform": "React/Next.js",
528
+ "Description": "Use Set/Map for O(1) lookups instead of array.includes()",
529
+ "Do": "Convert to Set for membership checks",
530
+ "Don't": "Use .includes() for repeated checks",
531
+ "Code Example Good": "const allowed = new Set(['a','b']); allowed.has(id)",
532
+ "Code Example Bad": "const allowed = ['a','b']; allowed.includes(id)",
533
+ "Severity": "Low-Medium"
534
+ },
535
+ {
536
+ "No": "42",
537
+ "Category": "JS Perf",
538
+ "Issue": "toSorted Immutable",
539
+ "Keywords": "tosorted sort immutable",
540
+ "Platform": "React/Next.js",
541
+ "Description": "Use toSorted() instead of sort() to avoid mutating arrays",
542
+ "Do": "Use toSorted() for immutability",
543
+ "Don't": "Mutate arrays with sort()",
544
+ "Code Example Good": "users.toSorted((a,b) => a.name.localeCompare(b.name))",
545
+ "Code Example Bad": "users.sort((a,b) => a.name.localeCompare(b.name)) // mutates",
546
+ "Severity": "Medium-High"
547
+ },
548
+ {
549
+ "No": "43",
550
+ "Category": "Advanced",
551
+ "Issue": "Event Handler Refs",
552
+ "Keywords": "useeffectevent ref handler",
553
+ "Platform": "React/Next.js",
554
+ "Description": "Store callbacks in refs for stable effect subscriptions",
555
+ "Do": "Use useEffectEvent for stable handlers",
556
+ "Don't": "Re-subscribe on every callback change",
557
+ "Code Example Good": "const onEvent = useEffectEvent(handler); useEffect(() => { listen(onEvent) }, [])",
558
+ "Code Example Bad": "useEffect(() => { listen(handler) }, [handler]) // re-subscribes",
559
+ "Severity": "Low"
560
+ },
561
+ {
562
+ "No": "44",
563
+ "Category": "Advanced",
564
+ "Issue": "useLatest Hook",
565
+ "Keywords": "uselatest ref callback",
566
+ "Platform": "React/Next.js",
567
+ "Description": "Access latest values in callbacks without adding to dependency arrays",
568
+ "Do": "Use useLatest for fresh values in stable callbacks",
569
+ "Don't": "Add callback to effect dependencies",
570
+ "Code Example Good": "const cbRef = useLatest(cb); useEffect(() => { setTimeout(() => cbRef.current()) }, [])",
571
+ "Code Example Bad": "useEffect(() => { setTimeout(() => cb()) }, [cb]) // re-runs",
572
+ "Severity": "Low"
573
+ }
574
+ ]