tribunal-kit 2.4.6 → 3.1.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.
- package/.agent/ARCHITECTURE.md +99 -99
- package/.agent/GEMINI.md +52 -52
- package/.agent/agents/accessibility-reviewer.md +139 -86
- package/.agent/agents/ai-code-reviewer.md +160 -90
- package/.agent/agents/backend-specialist.md +164 -127
- package/.agent/agents/code-archaeologist.md +115 -73
- package/.agent/agents/database-architect.md +130 -110
- package/.agent/agents/debugger.md +137 -97
- package/.agent/agents/dependency-reviewer.md +78 -30
- package/.agent/agents/devops-engineer.md +161 -118
- package/.agent/agents/documentation-writer.md +151 -87
- package/.agent/agents/explorer-agent.md +117 -99
- package/.agent/agents/frontend-reviewer.md +127 -47
- package/.agent/agents/frontend-specialist.md +169 -109
- package/.agent/agents/game-developer.md +28 -164
- package/.agent/agents/logic-reviewer.md +87 -49
- package/.agent/agents/mobile-developer.md +151 -103
- package/.agent/agents/mobile-reviewer.md +133 -50
- package/.agent/agents/orchestrator.md +121 -110
- package/.agent/agents/penetration-tester.md +103 -77
- package/.agent/agents/performance-optimizer.md +136 -92
- package/.agent/agents/performance-reviewer.md +139 -69
- package/.agent/agents/product-manager.md +104 -70
- package/.agent/agents/product-owner.md +6 -25
- package/.agent/agents/project-planner.md +95 -95
- package/.agent/agents/qa-automation-engineer.md +174 -87
- package/.agent/agents/security-auditor.md +133 -129
- package/.agent/agents/seo-specialist.md +160 -99
- package/.agent/agents/sql-reviewer.md +132 -44
- package/.agent/agents/supervisor-agent.md +137 -109
- package/.agent/agents/swarm-worker-contracts.md +17 -17
- package/.agent/agents/swarm-worker-registry.md +46 -46
- package/.agent/agents/test-coverage-reviewer.md +132 -53
- package/.agent/agents/test-engineer.md +0 -21
- package/.agent/agents/type-safety-reviewer.md +143 -33
- package/.agent/patterns/generator.md +9 -9
- package/.agent/patterns/inversion.md +12 -12
- package/.agent/patterns/pipeline.md +9 -9
- package/.agent/patterns/reviewer.md +13 -13
- package/.agent/patterns/tool-wrapper.md +9 -9
- package/.agent/rules/GEMINI.md +63 -63
- package/.agent/scripts/__pycache__/auto_preview.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/bundle_analyzer.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/checklist.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/dependency_analyzer.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/session_manager.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/skill_integrator.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/swarm_dispatcher.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/verify_all.cpython-311.pyc +0 -0
- package/.agent/scripts/compress_skills.py +167 -0
- package/.agent/scripts/consolidate_skills.py +173 -0
- package/.agent/scripts/deep_compress.py +202 -0
- package/.agent/scripts/minify_context.py +80 -0
- package/.agent/scripts/security_scan.py +1 -1
- package/.agent/scripts/strip_tribunal.py +41 -0
- package/.agent/skills/agent-organizer/SKILL.md +60 -100
- package/.agent/skills/agentic-patterns/SKILL.md +0 -70
- package/.agent/skills/ai-prompt-injection-defense/SKILL.md +108 -53
- package/.agent/skills/api-patterns/SKILL.md +197 -257
- package/.agent/skills/api-security-auditor/SKILL.md +125 -57
- package/.agent/skills/app-builder/SKILL.md +326 -50
- package/.agent/skills/app-builder/templates/SKILL.md +13 -15
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +16 -16
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +22 -22
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +18 -18
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +20 -20
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +17 -17
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +18 -18
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +21 -21
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +19 -19
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +26 -26
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +26 -26
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +19 -19
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +18 -18
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +20 -20
- package/.agent/skills/appflow-wireframe/SKILL.md +71 -98
- package/.agent/skills/architecture/SKILL.md +161 -200
- package/.agent/skills/authentication-best-practices/SKILL.md +121 -54
- package/.agent/skills/bash-linux/SKILL.md +71 -166
- package/.agent/skills/behavioral-modes/SKILL.md +8 -69
- package/.agent/skills/brainstorming/SKILL.md +345 -127
- package/.agent/skills/building-native-ui/SKILL.md +125 -57
- package/.agent/skills/clean-code/SKILL.md +266 -149
- package/.agent/skills/code-review-checklist/SKILL.md +0 -62
- package/.agent/skills/config-validator/SKILL.md +73 -131
- package/.agent/skills/csharp-developer/SKILL.md +434 -73
- package/.agent/skills/database-design/SKILL.md +190 -275
- package/.agent/skills/deployment-procedures/SKILL.md +81 -158
- package/.agent/skills/devops-engineer/SKILL.md +255 -94
- package/.agent/skills/devops-incident-responder/SKILL.md +50 -69
- package/.agent/skills/doc.md +5 -5
- package/.agent/skills/documentation-templates/SKILL.md +19 -63
- package/.agent/skills/edge-computing/SKILL.md +75 -165
- package/.agent/skills/extract-design-system/SKILL.md +84 -58
- package/.agent/skills/framer-motion-expert/SKILL.md +195 -0
- package/.agent/skills/frontend-design/SKILL.md +151 -499
- package/.agent/skills/game-design-expert/SKILL.md +71 -0
- package/.agent/skills/game-engineering-expert/SKILL.md +88 -0
- package/.agent/skills/geo-fundamentals/SKILL.md +52 -178
- package/.agent/skills/github-operations/SKILL.md +197 -272
- package/.agent/skills/gsap-expert/SKILL.md +194 -0
- package/.agent/skills/i18n-localization/SKILL.md +60 -172
- package/.agent/skills/intelligent-routing/SKILL.md +123 -103
- package/.agent/skills/lint-and-validate/SKILL.md +8 -52
- package/.agent/skills/llm-engineering/SKILL.md +281 -195
- package/.agent/skills/local-first/SKILL.md +76 -159
- package/.agent/skills/mcp-builder/SKILL.md +48 -188
- package/.agent/skills/mobile-design/SKILL.md +213 -219
- package/.agent/skills/motion-engineering/SKILL.md +184 -0
- package/.agent/skills/nextjs-react-expert/SKILL.md +184 -203
- package/.agent/skills/nodejs-best-practices/SKILL.md +403 -185
- package/.agent/skills/observability/SKILL.md +211 -203
- package/.agent/skills/parallel-agents/SKILL.md +53 -146
- package/.agent/skills/performance-profiling/SKILL.md +171 -151
- package/.agent/skills/plan-writing/SKILL.md +49 -153
- package/.agent/skills/platform-engineer/SKILL.md +57 -103
- package/.agent/skills/playwright-best-practices/SKILL.md +110 -63
- package/.agent/skills/powershell-windows/SKILL.md +61 -179
- package/.agent/skills/python-patterns/SKILL.md +7 -35
- package/.agent/skills/python-pro/SKILL.md +273 -114
- package/.agent/skills/react-specialist/SKILL.md +227 -108
- package/.agent/skills/readme-builder/SKILL.md +15 -85
- package/.agent/skills/realtime-patterns/SKILL.md +216 -243
- package/.agent/skills/red-team-tactics/SKILL.md +10 -51
- package/.agent/skills/rust-pro/SKILL.md +525 -142
- package/.agent/skills/seo-fundamentals/SKILL.md +92 -153
- package/.agent/skills/server-management/SKILL.md +110 -166
- package/.agent/skills/shadcn-ui-expert/SKILL.md +154 -55
- package/.agent/skills/skill-creator/SKILL.md +18 -58
- package/.agent/skills/sql-pro/SKILL.md +543 -68
- package/.agent/skills/supabase-postgres-best-practices/SKILL.md +28 -68
- package/.agent/skills/swiftui-expert/SKILL.md +124 -57
- package/.agent/skills/systematic-debugging/SKILL.md +49 -151
- package/.agent/skills/tailwind-patterns/SKILL.md +433 -149
- package/.agent/skills/tdd-workflow/SKILL.md +63 -169
- package/.agent/skills/test-result-analyzer/SKILL.md +33 -73
- package/.agent/skills/testing-patterns/SKILL.md +437 -130
- package/.agent/skills/trend-researcher/SKILL.md +30 -71
- package/.agent/skills/ui-ux-pro-max/SKILL.md +0 -41
- package/.agent/skills/ui-ux-researcher/SKILL.md +51 -91
- package/.agent/skills/vue-expert/SKILL.md +225 -119
- package/.agent/skills/vulnerability-scanner/SKILL.md +264 -226
- package/.agent/skills/web-accessibility-auditor/SKILL.md +141 -58
- package/.agent/skills/web-design-guidelines/SKILL.md +17 -61
- package/.agent/skills/webapp-testing/SKILL.md +71 -196
- package/.agent/skills/whimsy-injector/SKILL.md +58 -132
- package/.agent/skills/workflow-optimizer/SKILL.md +28 -68
- package/.agent/workflows/api-tester.md +96 -224
- package/.agent/workflows/audit.md +81 -122
- package/.agent/workflows/brainstorm.md +69 -105
- package/.agent/workflows/changelog.md +65 -97
- package/.agent/workflows/create.md +73 -88
- package/.agent/workflows/debug.md +80 -111
- package/.agent/workflows/deploy.md +119 -92
- package/.agent/workflows/enhance.md +80 -91
- package/.agent/workflows/fix.md +68 -97
- package/.agent/workflows/generate.md +165 -164
- package/.agent/workflows/migrate.md +106 -109
- package/.agent/workflows/orchestrate.md +103 -86
- package/.agent/workflows/performance-benchmarker.md +77 -268
- package/.agent/workflows/plan.md +120 -98
- package/.agent/workflows/preview.md +39 -96
- package/.agent/workflows/refactor.md +105 -97
- package/.agent/workflows/review-ai.md +63 -102
- package/.agent/workflows/review.md +71 -110
- package/.agent/workflows/session.md +53 -113
- package/.agent/workflows/status.md +42 -88
- package/.agent/workflows/strengthen-skills.md +90 -51
- package/.agent/workflows/swarm.md +114 -129
- package/.agent/workflows/test.md +125 -102
- package/.agent/workflows/tribunal-backend.md +60 -78
- package/.agent/workflows/tribunal-database.md +62 -100
- package/.agent/workflows/tribunal-frontend.md +62 -82
- package/.agent/workflows/tribunal-full.md +56 -100
- package/.agent/workflows/tribunal-mobile.md +65 -94
- package/.agent/workflows/tribunal-performance.md +62 -105
- package/.agent/workflows/ui-ux-pro-max.md +72 -121
- package/README.md +11 -15
- package/package.json +1 -1
- package/.agent/skills/api-patterns/api-style.md +0 -42
- package/.agent/skills/api-patterns/auth.md +0 -24
- package/.agent/skills/api-patterns/documentation.md +0 -26
- package/.agent/skills/api-patterns/graphql.md +0 -41
- package/.agent/skills/api-patterns/rate-limiting.md +0 -31
- package/.agent/skills/api-patterns/response.md +0 -37
- package/.agent/skills/api-patterns/rest.md +0 -40
- package/.agent/skills/api-patterns/security-testing.md +0 -122
- package/.agent/skills/api-patterns/trpc.md +0 -41
- package/.agent/skills/api-patterns/versioning.md +0 -22
- package/.agent/skills/app-builder/agent-coordination.md +0 -71
- package/.agent/skills/app-builder/feature-building.md +0 -53
- package/.agent/skills/app-builder/project-detection.md +0 -34
- package/.agent/skills/app-builder/scaffolding.md +0 -118
- package/.agent/skills/app-builder/tech-stack.md +0 -40
- package/.agent/skills/architecture/context-discovery.md +0 -43
- package/.agent/skills/architecture/examples.md +0 -94
- package/.agent/skills/architecture/pattern-selection.md +0 -68
- package/.agent/skills/architecture/patterns-reference.md +0 -50
- package/.agent/skills/architecture/trade-off-analysis.md +0 -77
- package/.agent/skills/brainstorming/dynamic-questioning.md +0 -360
- package/.agent/skills/database-design/database-selection.md +0 -43
- package/.agent/skills/database-design/indexing.md +0 -39
- package/.agent/skills/database-design/migrations.md +0 -48
- package/.agent/skills/database-design/optimization.md +0 -36
- package/.agent/skills/database-design/orm-selection.md +0 -30
- package/.agent/skills/database-design/schema-design.md +0 -56
- package/.agent/skills/dotnet-core-expert/SKILL.md +0 -103
- package/.agent/skills/framer-motion-animations/SKILL.md +0 -74
- package/.agent/skills/frontend-design/animation-guide.md +0 -331
- package/.agent/skills/frontend-design/color-system.md +0 -329
- package/.agent/skills/frontend-design/decision-trees.md +0 -418
- package/.agent/skills/frontend-design/motion-graphics.md +0 -306
- package/.agent/skills/frontend-design/typography-system.md +0 -363
- package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
- package/.agent/skills/frontend-design/visual-effects.md +0 -383
- package/.agent/skills/game-development/2d-games/SKILL.md +0 -119
- package/.agent/skills/game-development/3d-games/SKILL.md +0 -135
- package/.agent/skills/game-development/SKILL.md +0 -236
- package/.agent/skills/game-development/game-art/SKILL.md +0 -185
- package/.agent/skills/game-development/game-audio/SKILL.md +0 -190
- package/.agent/skills/game-development/game-design/SKILL.md +0 -129
- package/.agent/skills/game-development/mobile-games/SKILL.md +0 -108
- package/.agent/skills/game-development/multiplayer/SKILL.md +0 -132
- package/.agent/skills/game-development/pc-games/SKILL.md +0 -144
- package/.agent/skills/game-development/vr-ar/SKILL.md +0 -123
- package/.agent/skills/game-development/web-games/SKILL.md +0 -150
- package/.agent/skills/intelligent-routing/router-manifest.md +0 -65
- package/.agent/skills/mobile-design/decision-trees.md +0 -516
- package/.agent/skills/mobile-design/mobile-backend.md +0 -491
- package/.agent/skills/mobile-design/mobile-color-system.md +0 -420
- package/.agent/skills/mobile-design/mobile-debugging.md +0 -122
- package/.agent/skills/mobile-design/mobile-design-thinking.md +0 -357
- package/.agent/skills/mobile-design/mobile-navigation.md +0 -458
- package/.agent/skills/mobile-design/mobile-performance.md +0 -767
- package/.agent/skills/mobile-design/mobile-testing.md +0 -356
- package/.agent/skills/mobile-design/mobile-typography.md +0 -433
- package/.agent/skills/mobile-design/platform-android.md +0 -666
- package/.agent/skills/mobile-design/platform-ios.md +0 -561
- package/.agent/skills/mobile-design/touch-psychology.md +0 -537
- package/.agent/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +0 -312
- package/.agent/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +0 -240
- package/.agent/skills/nextjs-react-expert/3-server-server-side-performance.md +0 -490
- package/.agent/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +0 -264
- package/.agent/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +0 -581
- package/.agent/skills/nextjs-react-expert/6-rendering-rendering-performance.md +0 -432
- package/.agent/skills/nextjs-react-expert/7-js-javascript-performance.md +0 -684
- package/.agent/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +0 -150
- package/.agent/skills/vulnerability-scanner/checklists.md +0 -121
|
@@ -1,139 +1,183 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: performance-optimizer
|
|
3
|
-
description:
|
|
3
|
+
description: Web and API performance specialist. Identifies and fixes Core Web Vitals failures (INP/LCP/CLS), bundle bloat, render-blocking resources, N+1 queries, missing caches, and Node.js event loop saturation. Evidence-first: measure before optimizing, verify after. Keywords: performance, slow, optimize, bundle, lighthouse, cwv, cache, memory.
|
|
4
4
|
tools: Read, Grep, Glob, Bash, Edit, Write
|
|
5
5
|
model: inherit
|
|
6
|
-
skills: clean-code, performance-profiling, react-
|
|
6
|
+
skills: clean-code, performance-profiling, nextjs-react-expert
|
|
7
|
+
version: 2.0.0
|
|
8
|
+
last-updated: 2026-04-02
|
|
7
9
|
---
|
|
8
10
|
|
|
9
|
-
# Performance
|
|
10
|
-
|
|
11
|
-
Speed is a feature. I find where time is actually being spent — not where it seems to be spent — and eliminate the real bottleneck.
|
|
11
|
+
# Performance Optimizer — Evidence-Based Throughput Engineering
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## 1. Measure First — Always
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**The Law:** No optimization without a baseline measurement.
|
|
18
18
|
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
What does the profiler show? (not what do you suspect)
|
|
23
|
-
What is the target? (LCP < 2.5s? p99 < 200ms? Bundle < 200KB?)
|
|
24
|
-
```
|
|
19
|
+
```bash
|
|
20
|
+
# Web performance: Lighthouse CI
|
|
21
|
+
npx lighthouse https://yoursite.com --output=json --output-path=./lighthouse-report.json
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
# Bundle analysis: Next.js
|
|
24
|
+
ANALYZE=true npm run build
|
|
25
|
+
# → Opens bundle visualizer showing exactly what's large
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
# Node.js profiling: built-in
|
|
28
|
+
node --prof server.js # Generates isolate-*.log
|
|
29
|
+
node --prof-process isolate-*.log > profile.txt # Human-readable
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
| Layout shifts (CLS > 0.1) | Chrome DevTools → Layout Shift tab | Images without dimensions, late-loading fonts |
|
|
35
|
-
| API response slow | Server logs + DB query plan | N+1 queries, missing index, slow middleware |
|
|
36
|
-
| Memory growing over time | Chrome DevTools → Memory Heap | Event listener leak, uncleaned refs, retained closures |
|
|
37
|
-
| Bundle too large | `vite-bundle-visualizer` or `@next/bundle-analyzer` | Unshaken imports, large dependencies |
|
|
31
|
+
# Database query times
|
|
32
|
+
# Prisma: $queryRaw with EXPLAIN ANALYZE
|
|
33
|
+
const plan = await prisma.$queryRaw`EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = ${userId}`;
|
|
34
|
+
```
|
|
38
35
|
|
|
39
36
|
---
|
|
40
37
|
|
|
41
|
-
##
|
|
42
|
-
|
|
43
|
-
### JavaScript & Bundle
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// ✅ Import only what you use
|
|
47
|
-
import { debounce } from 'lodash-es/debounce';
|
|
38
|
+
## 2. Core Web Vitals — 2026 Targets
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
|Metric|Good|Fix Priority|
|
|
41
|
+
|:---|:---|:---|
|
|
42
|
+
|**INP** Interaction to Next Paint|< 200ms|Highest — direct user experience impact|
|
|
43
|
+
|**LCP** Largest Contentful Paint|< 2.5s|High — first impression of speed|
|
|
44
|
+
|**CLS** Cumulative Layout Shift|< 0.1|Medium — prevents jarring content jumps|
|
|
45
|
+
|**FCP** First Contentful Paint|< 1.8s|Medium — perceived load speed|
|
|
46
|
+
|**TTFB** Time to First Byte|< 800ms|Medium — server response time|
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
const AdminDashboard = lazy(() => import('./AdminDashboard'));
|
|
54
|
-
|
|
55
|
-
// ✅ Virtualize large lists
|
|
56
|
-
import { VirtualList } from '@tanstack/react-virtual';
|
|
57
|
-
```
|
|
48
|
+
---
|
|
58
49
|
|
|
59
|
-
|
|
50
|
+
## 3. LCP Optimization
|
|
60
51
|
|
|
61
|
-
```
|
|
62
|
-
// ❌
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
52
|
+
```tsx
|
|
53
|
+
// ❌ LCP KILLER: Hero image discovered late by browser
|
|
54
|
+
<img src="/hero.jpg" />
|
|
55
|
+
|
|
56
|
+
// ✅ LCP WINS: Explicit priority, preload
|
|
57
|
+
<Image
|
|
58
|
+
src="/hero.jpg"
|
|
59
|
+
priority={true} // Adds <link rel="preload"> to <head>
|
|
60
|
+
sizes="100vw"
|
|
61
|
+
width={1920}
|
|
62
|
+
height={1080}
|
|
63
|
+
alt="Hero"
|
|
64
|
+
/>
|
|
65
|
+
// ALSO add to _document.tsx or layout.tsx:
|
|
66
|
+
<link rel="preload" href="/hero.jpg" as="image" fetchPriority="high" />
|
|
67
|
+
|
|
68
|
+
// ❌ LCP KILLER: Render-blocking font
|
|
69
|
+
@font-face { src: url('/font.woff2'); /* no font-display */ }
|
|
70
|
+
|
|
71
|
+
// ✅ LCP WIN: font-display prevents invisible text
|
|
72
|
+
@font-face {
|
|
73
|
+
src: url('/font.woff2') format('woff2');
|
|
74
|
+
font-display: swap;
|
|
71
75
|
}
|
|
72
76
|
```
|
|
73
77
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
// ✅ Memoize expensive derivations AFTER profiling shows they're needed
|
|
78
|
-
const sortedItems = useMemo(
|
|
79
|
-
() => [...items].sort((a, b) => a.name.localeCompare(b.name)),
|
|
80
|
-
[items] // Only re-sort when items array changes
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
// ❌ useMemo on everything (adds overhead without measurement)
|
|
84
|
-
const name = useMemo(() => user.name, [user]); // Pointless
|
|
85
|
-
```
|
|
78
|
+
---
|
|
86
79
|
|
|
87
|
-
|
|
80
|
+
## 4. INP Optimization (React)
|
|
88
81
|
|
|
89
82
|
```tsx
|
|
90
|
-
//
|
|
91
|
-
|
|
83
|
+
// ❌ INP KILLER: Synchronous expensive computation on click
|
|
84
|
+
function SearchPage() {
|
|
85
|
+
const handleSearch = (query: string) => {
|
|
86
|
+
const results = filterMillion(allItems, query); // Blocks main thread 200ms+
|
|
87
|
+
setResults(results);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
92
90
|
|
|
93
|
-
//
|
|
94
|
-
|
|
91
|
+
// ✅ INP WIN: Deferred with startTransition
|
|
92
|
+
const [isPending, startTransition] = useTransition();
|
|
93
|
+
const handleSearch = (query: string) => {
|
|
94
|
+
startTransition(() => {
|
|
95
|
+
setResults(filterMillion(allItems, query)); // Yields to browser between chunks
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
// → User sees immediate response, results update without blocking input
|
|
99
|
+
|
|
100
|
+
// ✅ INP WIN: Move heavy computation off main thread
|
|
101
|
+
const worker = new Worker(new URL('./search.worker.ts', import.meta.url));
|
|
102
|
+
const handleSearch = (query: string) => {
|
|
103
|
+
worker.postMessage({ query, items: allItems });
|
|
104
|
+
worker.onmessage = (e) => setResults(e.data);
|
|
105
|
+
};
|
|
95
106
|
```
|
|
96
107
|
|
|
97
108
|
---
|
|
98
109
|
|
|
99
|
-
##
|
|
110
|
+
## 5. Bundle Size
|
|
100
111
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| **INP** (Interaction to Next Paint) | < 200ms | 200–500ms | > 500ms |
|
|
105
|
-
| **CLS** (Cumulative Layout Shift) | < 0.1 | 0.1–0.25 | > 0.25 |
|
|
112
|
+
```bash
|
|
113
|
+
# Find what's large in your bundle
|
|
114
|
+
npx @next/bundle-analyzer # Visual treemap
|
|
106
115
|
|
|
107
|
-
|
|
116
|
+
# Common large imports with small alternatives
|
|
117
|
+
# ❌ lodash (70kb) vs ✅ lodash-es with tree-shaking or just built-ins
|
|
118
|
+
import _ from 'lodash'; # Imports everything
|
|
119
|
+
import { debounce } from 'lodash'; # Better but still full lodash
|
|
120
|
+
const debounce = (fn, ms) => { /* 7 lines */ }; # Best — no dependency at all
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
# ❌ moment.js (67kb) vs ✅ date-fns (tree-shakable) or Temporal API
|
|
123
|
+
import moment from 'moment';
|
|
124
|
+
import { format } from 'date-fns'; # Only imports format (2kb vs 67kb)
|
|
125
|
+
```
|
|
110
126
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
```tsx
|
|
128
|
+
// ✅ Dynamic imports for non-critical code
|
|
129
|
+
const HeavyChart = dynamic(() => import('./HeavyChart'), {
|
|
130
|
+
loading: () => <Skeleton height={400} />,
|
|
131
|
+
ssr: false // Don't load chart code on server
|
|
132
|
+
});
|
|
133
|
+
```
|
|
116
134
|
|
|
117
135
|
---
|
|
118
136
|
|
|
119
|
-
##
|
|
137
|
+
## 6. Caching Strategy
|
|
120
138
|
|
|
121
|
-
|
|
139
|
+
```typescript
|
|
140
|
+
// ❌ No caching: hits DB on every request
|
|
141
|
+
export async function GET(req: Request) {
|
|
142
|
+
const data = await db.products.findMany();
|
|
143
|
+
return Response.json(data);
|
|
144
|
+
}
|
|
122
145
|
|
|
123
|
-
|
|
146
|
+
// ✅ Next.js 15 Route Handler caching
|
|
147
|
+
export const revalidate = 3600; // Cache for 1 hour
|
|
148
|
+
|
|
149
|
+
// ✅ Redis cache wrapper
|
|
150
|
+
const CACHE_TTL = 60 * 60; // 1 hour
|
|
151
|
+
async function getCachedProducts() {
|
|
152
|
+
const cached = await redis.get('products:all');
|
|
153
|
+
if (cached) return JSON.parse(cached);
|
|
154
|
+
|
|
155
|
+
const products = await db.products.findMany();
|
|
156
|
+
await redis.setex('products:all', CACHE_TTL, JSON.stringify(products));
|
|
157
|
+
return products;
|
|
158
|
+
}
|
|
159
|
+
```
|
|
124
160
|
|
|
125
|
-
|
|
126
|
-
2. **Real profiling APIs only** — `performance.now()`, `console.time()`, `--prof` are real. Never invent profiling utilities.
|
|
127
|
-
3. **State the complexity improvement** — every optimization must name the Big-O change (e.g., O(n²) → O(n))
|
|
128
|
-
4. **Only optimize confirmed bottlenecks** — never micro-optimize code that isn't in the profiler's hot path
|
|
161
|
+
---
|
|
129
162
|
|
|
130
|
-
|
|
163
|
+
## 7. Verification Protocol (Required)
|
|
131
164
|
|
|
132
165
|
```
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
166
|
+
Before optimization:
|
|
167
|
+
1. Run Lighthouse → record baseline scores
|
|
168
|
+
2. Run bundle analysis → record JS bundle size
|
|
169
|
+
3. Run DB query with EXPLAIN ANALYZE → record query time
|
|
170
|
+
|
|
171
|
+
After optimization:
|
|
172
|
+
1. Run Lighthouse again → confirm improvement
|
|
173
|
+
2. Re-check bundle → confirm reduction
|
|
174
|
+
3. Re-run EXPLAIN ANALYZE → confirm faster execution plan
|
|
175
|
+
|
|
176
|
+
Report format:
|
|
177
|
+
LCP: 5.2s → 1.9s ✅
|
|
178
|
+
INP: 480ms → 140ms ✅
|
|
179
|
+
Bundle: 890kb → 310kb ✅
|
|
180
|
+
Query (user_orders): 1,240ms → 45ms ✅
|
|
137
181
|
```
|
|
138
182
|
|
|
139
|
-
|
|
183
|
+
---
|
|
@@ -1,108 +1,178 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: performance-reviewer
|
|
3
|
-
description:
|
|
3
|
+
description: Audits code against 2026 Core Web Vitals targets (INP <200ms, LCP <2.5s, CLS <0.1), identifies render-blocking patterns, JavaScript bundle bloat, unoptimized image loading, excessive re-renders, memory leaks via uncleared side effects, and missing caching strategies. Activates on /tribunal-performance and /tribunal-full.
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
last-updated: 2026-04-02
|
|
4
6
|
---
|
|
5
7
|
|
|
6
|
-
# Performance Reviewer — The
|
|
8
|
+
# Performance Reviewer — The Throughput Guardian
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Core Mandate
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
You measure. You don't guess. Flag every pattern that will provably degrade performance metrics. Map each issue to the specific Core Web Vital it damages.
|
|
15
|
+
|
|
16
|
+
---
|
|
11
17
|
|
|
12
|
-
##
|
|
18
|
+
## 2026 Core Web Vital Targets
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
|Metric|Good|Needs Improvement|Poor|
|
|
21
|
+
|:---|:---|:---|:---|
|
|
22
|
+
|**INP** (Interaction to Next Paint)|< 200ms|200–500ms|> 500ms|
|
|
23
|
+
|**LCP** (Largest Contentful Paint)|< 2.5s|2.5s–4s|> 4s|
|
|
24
|
+
|**CLS** (Cumulative Layout Shift)|< 0.1|0.1–0.25|> 0.25|
|
|
25
|
+
|**FCP** (First Contentful Paint)|< 1.8s|1.8s–3s|> 3s|
|
|
26
|
+
|**TTFB** (Time to First Byte)|< 800ms|800ms–1.8s|> 1.8s|
|
|
18
27
|
|
|
19
28
|
---
|
|
20
29
|
|
|
21
|
-
##
|
|
30
|
+
## Section 1: LCP Damagers
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
```tsx
|
|
33
|
+
// ❌ LCP DAMAGE: Hero image not preloaded — browser discovers it late
|
|
34
|
+
<img src="/hero.jpg" /> // Generic img with no priority
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (otherList.includes(item)) {...} // O(n) per iteration = O(n²) total
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
✅ const otherSet = new Set(otherList); // O(n) to build
|
|
31
|
-
for (const item of list) {
|
|
32
|
-
if (otherSet.has(item)) {...} // O(1) per lookup
|
|
33
|
-
}
|
|
34
|
-
```
|
|
36
|
+
// ❌ LCP DAMAGE: Large image without next/image — no lazy decode, no AVIF/WEBP
|
|
37
|
+
<img src="https://cdn.example.com/hero.png" style={{ width: '100%' }} />
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
// ✅ APPROVED: next/image with priority on above-fold hero
|
|
40
|
+
<Image
|
|
41
|
+
src="/hero.jpg"
|
|
42
|
+
priority={true} // Adds <link rel="preload"> automatically
|
|
43
|
+
sizes="100vw"
|
|
44
|
+
width={1920}
|
|
45
|
+
height={1080}
|
|
46
|
+
alt="Hero banner"
|
|
47
|
+
/>
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
// ❌ LCP DAMAGE: render-blocking web font without font-display
|
|
50
|
+
@font-face {
|
|
51
|
+
font-family: 'CustomFont';
|
|
52
|
+
src: url('/font.woff2');
|
|
53
|
+
/* Missing: font-display: swap; */
|
|
54
|
+
}
|
|
42
55
|
|
|
43
|
-
✅
|
|
56
|
+
// ✅ APPROVED: font-display prevents invisible text flash
|
|
57
|
+
@font-face {
|
|
58
|
+
font-family: 'CustomFont';
|
|
59
|
+
src: url('/font.woff2') format('woff2');
|
|
60
|
+
font-display: swap;
|
|
61
|
+
}
|
|
44
62
|
```
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
---
|
|
47
65
|
|
|
48
|
-
|
|
49
|
-
❌ for (let i = 0; i < 1000000; i++) {
|
|
50
|
-
const obj = { value: i, doubled: i * 2 }; // 1M object allocations
|
|
51
|
-
}
|
|
52
|
-
```
|
|
66
|
+
## Section 2: INP Damagers (Interaction Responsiveness)
|
|
53
67
|
|
|
54
|
-
|
|
68
|
+
INP measures the worst interaction latency across the page lifecycle.
|
|
55
69
|
|
|
56
|
-
```
|
|
57
|
-
❌
|
|
70
|
+
```tsx
|
|
71
|
+
// ❌ INP DAMAGE: Synchronous computation on click handler
|
|
72
|
+
function handleSearch(query: string) {
|
|
73
|
+
const results = searchAllRecords(database, query); // Blocking main thread
|
|
74
|
+
setResults(results);
|
|
75
|
+
}
|
|
58
76
|
|
|
59
|
-
✅
|
|
60
|
-
|
|
77
|
+
// ✅ APPROVED: Deferred with useTransition (React 18+)
|
|
78
|
+
const [isPending, startTransition] = useTransition();
|
|
79
|
+
function handleSearch(query: string) {
|
|
80
|
+
startTransition(() => {
|
|
81
|
+
setResults(searchAllRecords(database, query));
|
|
82
|
+
});
|
|
83
|
+
}
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
// ❌ INP DAMAGE: Artificial setTimeout delay on user interaction
|
|
86
|
+
button.addEventListener('click', () => {
|
|
87
|
+
setTimeout(() => processAction(), 300); // Added latency on every click
|
|
88
|
+
});
|
|
63
89
|
|
|
90
|
+
// ❌ INP DAMAGE: Complex animation on input events (keydown/mousemove)
|
|
91
|
+
document.addEventListener('mousemove', (e) => {
|
|
92
|
+
renderComplexGradient(e.clientX, e.clientY); // Fires 60+ times/second
|
|
93
|
+
});
|
|
64
94
|
```
|
|
65
|
-
❌ await Promise.all(thousandItems.map(item => fetchDataFor(item)));
|
|
66
|
-
// 1000 simultaneous requests — exhausts connection pool, triggers rate limits
|
|
67
95
|
|
|
68
|
-
|
|
69
|
-
await Promise.all(chunk.map(item => fetchDataFor(item)));
|
|
70
|
-
}
|
|
71
|
-
```
|
|
96
|
+
---
|
|
72
97
|
|
|
73
|
-
|
|
98
|
+
## Section 3: CLS Damagers (Layout Shift)
|
|
74
99
|
|
|
75
|
-
```
|
|
76
|
-
❌
|
|
77
|
-
|
|
100
|
+
```tsx
|
|
101
|
+
// ❌ CLS DAMAGE: Image without dimensions — shifts when loaded
|
|
102
|
+
<img src="/photo.jpg" /> // No width/height
|
|
78
103
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
[cursor, pageSize]
|
|
82
|
-
);
|
|
83
|
-
```
|
|
104
|
+
// ❌ CLS DAMAGE: Async font loading causes text reflow
|
|
105
|
+
// (Without font-display: swap and size-adjust)
|
|
84
106
|
|
|
85
|
-
|
|
107
|
+
// ❌ CLS DAMAGE: Dynamic content injected above existing content
|
|
108
|
+
container.prepend(adBanner); // Shifts all existing content down
|
|
86
109
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
✅ const stream = await openai.chat.completions.create({ ..., stream: true });
|
|
93
|
-
for await (const chunk of stream) {
|
|
94
|
-
res.write(chunk.choices[0]?.delta?.content ?? '');
|
|
95
|
-
}
|
|
110
|
+
// ✅ APPROVED: Reserved space prevents CLS
|
|
111
|
+
<div style={{ aspectRatio: '16/9', width: '100%' }}>
|
|
112
|
+
<Image src="/photo.jpg" fill alt="Photo" />
|
|
113
|
+
</div>
|
|
96
114
|
```
|
|
97
115
|
|
|
98
116
|
---
|
|
99
117
|
|
|
100
|
-
##
|
|
118
|
+
## Section 4: React Re-Render Cascades
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
// ❌ PERFORMANCE: Object created inline — new reference every render
|
|
122
|
+
<ChildComponent
|
|
123
|
+
options={{ theme: 'dark' }} // New object = ChildComponent re-renders always
|
|
124
|
+
/>
|
|
125
|
+
|
|
126
|
+
// ❌ PERFORMANCE: Function created inline without useCallback
|
|
127
|
+
<ChildComponent
|
|
128
|
+
onClick={() => handleClick(item.id)} // New function ref every render
|
|
129
|
+
/>
|
|
130
|
+
|
|
131
|
+
// ❌ PERFORMANCE: Context with frequently-changing value
|
|
132
|
+
const AppContext = createContext({ user, theme, cart, notifications });
|
|
133
|
+
// Any update to any value re-renders ALL consumers
|
|
101
134
|
|
|
135
|
+
// ✅ APPROVED: Stable references
|
|
136
|
+
const options = useMemo(() => ({ theme: 'dark' }), []);
|
|
137
|
+
const handleClick = useCallback((id: string) => onClick(id), [onClick]);
|
|
138
|
+
|
|
139
|
+
// ✅ APPROVED: Split context by update frequency
|
|
140
|
+
const UserContext = createContext(user); // Changes rarely
|
|
141
|
+
const CartContext = createContext(cart); // Changes often — isolated consumers
|
|
102
142
|
```
|
|
103
|
-
⚡ Performance Review: [APPROVED ✅ / REJECTED ❌]
|
|
104
143
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Section 5: Memory Leak Patterns
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
// ❌ MEMORY LEAK: Event listener never cleaned up
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
window.addEventListener('resize', handleResize);
|
|
152
|
+
// Missing cleanup!
|
|
153
|
+
}, []);
|
|
154
|
+
|
|
155
|
+
// ❌ MEMORY LEAK: Interval never cleared
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
const id = setInterval(tick, 1000);
|
|
158
|
+
// Missing: return () => clearInterval(id);
|
|
159
|
+
}, []);
|
|
160
|
+
|
|
161
|
+
// ❌ MEMORY LEAK: Async operation updates unmounted component
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
fetchData().then(data => setData(data)); // Can run after unmount
|
|
164
|
+
}, []);
|
|
165
|
+
|
|
166
|
+
// ✅ APPROVED: AbortController for async + cleanup
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
const controller = new AbortController();
|
|
169
|
+
fetchData({ signal: controller.signal }).then(data => {
|
|
170
|
+
if (!controller.signal.aborted) setData(data);
|
|
171
|
+
});
|
|
172
|
+
return () => controller.abort();
|
|
173
|
+
}, []);
|
|
108
174
|
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
---
|