@brookmind/ai-toolkit 1.0.5 → 1.1.2
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/README.md +60 -14
- package/agents/code-reviewer.md +6 -1
- package/agents/code-simplifier.md +52 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +257 -220
- package/dist/index.js.map +1 -1
- package/mcps/context7/.mcp.json +13 -0
- package/mcps/expo-mcp/.mcp.json +13 -0
- package/mcps/figma-mcp/.mcp.json +4 -6
- package/package.json +4 -4
- package/skills/pdf-processing-pro/FORMS.md +610 -0
- package/skills/pdf-processing-pro/OCR.md +137 -0
- package/skills/pdf-processing-pro/SKILL.md +296 -0
- package/skills/pdf-processing-pro/TABLES.md +626 -0
- package/skills/pdf-processing-pro/scripts/analyze_form.py +307 -0
- package/skills/react-best-practices/AGENTS.md +915 -0
- package/skills/react-best-practices/README.md +127 -0
- package/skills/react-best-practices/SKILL.md +110 -0
- package/skills/react-best-practices/metadata.json +14 -0
- package/skills/react-best-practices/rules/_sections.md +41 -0
- package/skills/react-best-practices/rules/_template.md +28 -0
- package/skills/react-best-practices/rules/advanced-event-handler-refs.md +80 -0
- package/skills/react-best-practices/rules/advanced-use-latest.md +76 -0
- package/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/react-best-practices/rules/async-suspense-boundaries.md +100 -0
- package/skills/react-best-practices/rules/bundle-barrel-imports.md +42 -0
- package/skills/react-best-practices/rules/bundle-conditional.md +106 -0
- package/skills/react-best-practices/rules/bundle-preload.md +44 -0
- package/skills/react-best-practices/rules/client-event-listeners.md +131 -0
- package/skills/react-best-practices/rules/client-swr-dedup.md +133 -0
- package/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/react-best-practices/rules/rendering-activity.md +90 -0
- package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/react-best-practices/rules/rendering-hoist-jsx.md +65 -0
- package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/react-best-practices/rules/rerender-memo.md +85 -0
- package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/themes/README.md +68 -0
- package/themes/claude-vivid.json +72 -0
- package/mcps/context7/.claude-plugin +0 -1
- package/mcps/context7/README.md +0 -1
- package/mcps/context7/server.json +0 -1
- package/mcps/expo-mcp/README.md +0 -33
- package/mcps/expo-mcp/package.json +0 -30
- package/mcps/figma-mcp/README.md +0 -554
- package/mcps/figma-mcp/server.json +0 -17
- package/mcps/figma-mcp/skills/code-connect-components +0 -1
- package/mcps/figma-mcp/skills/create-design-system-rules +0 -1
- package/mcps/figma-mcp/skills/implement-design +0 -1
- package/mcps/pg-aiguide/.claude-plugin +0 -1
- package/mcps/pg-aiguide/CLAUDE.md +0 -21
- package/mcps/pg-aiguide/README.md +0 -275
- package/mcps/pg-aiguide/skills/design-postgres-tables +0 -1
- package/mcps/pg-aiguide/skills/find-hypertable-candidates +0 -1
- package/mcps/pg-aiguide/skills/migrate-postgres-tables-to-hypertables +0 -1
- package/mcps/pg-aiguide/skills/setup-timescaledb-hypertables +0 -1
- package/mcps/pg-aiguide/skills.yaml +0 -4
- package/skills/cloudflare-cli/SKILL.md +0 -151
- package/skills/docx/LICENSE.txt +0 -30
- package/skills/docx/SKILL.md +0 -197
- package/skills/docx/docx-js.md +0 -350
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
- package/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/docx/ooxml/scripts/pack.py +0 -159
- package/skills/docx/ooxml/scripts/unpack.py +0 -29
- package/skills/docx/ooxml/scripts/validate.py +0 -69
- package/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
- package/skills/docx/ooxml/scripts/validation/base.py +0 -951
- package/skills/docx/ooxml/scripts/validation/docx.py +0 -274
- package/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
- package/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
- package/skills/docx/ooxml.md +0 -610
- package/skills/docx/scripts/__init__.py +0 -1
- package/skills/docx/scripts/document.py +0 -1276
- package/skills/docx/scripts/templates/comments.xml +0 -3
- package/skills/docx/scripts/templates/commentsExtended.xml +0 -3
- package/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
- package/skills/docx/scripts/templates/commentsIds.xml +0 -3
- package/skills/docx/scripts/templates/people.xml +0 -3
- package/skills/docx/scripts/utilities.py +0 -374
- package/skills/pdf/LICENSE.txt +0 -30
- package/skills/pdf/SKILL.md +0 -294
- package/skills/pdf/forms.md +0 -205
- package/skills/pdf/reference.md +0 -612
- package/skills/pdf/scripts/check_bounding_boxes.py +0 -70
- package/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
- package/skills/pdf/scripts/check_fillable_fields.py +0 -12
- package/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
- package/skills/pdf/scripts/create_validation_image.py +0 -41
- package/skills/pdf/scripts/extract_form_field_info.py +0 -152
- package/skills/pdf/scripts/fill_fillable_fields.py +0 -114
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
- package/skills/xlsx/LICENSE.txt +0 -30
- package/skills/xlsx/SKILL.md +0 -289
- package/skills/xlsx/recalc.py +0 -178
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# React Best Practices
|
|
2
|
+
|
|
3
|
+
A structured repository for creating and maintaining React Best Practices optimized for agents and LLMs.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
- `rules/` - Individual rule files (one per rule)
|
|
8
|
+
- `_sections.md` - Section metadata (titles, impacts, descriptions)
|
|
9
|
+
- `_template.md` - Template for creating new rules
|
|
10
|
+
- `area-description.md` - Individual rule files
|
|
11
|
+
- `src/` - Build scripts and utilities
|
|
12
|
+
- `metadata.json` - Document metadata (version, organization, abstract)
|
|
13
|
+
- **`AGENTS.md`** - Compiled output (generated)
|
|
14
|
+
- **`test-cases.json`** - Test cases for LLM evaluation (generated)
|
|
15
|
+
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
1. Install dependencies:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
2. Build AGENTS.md from rules:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm build
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
3. Validate rule files:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm validate
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
4. Extract test cases:
|
|
37
|
+
```bash
|
|
38
|
+
pnpm extract-tests
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Creating a New Rule
|
|
42
|
+
|
|
43
|
+
1. Copy `rules/_template.md` to `rules/area-description.md`
|
|
44
|
+
2. Choose the appropriate area prefix:
|
|
45
|
+
- `async-` for Eliminating Waterfalls (Section 1)
|
|
46
|
+
- `bundle-` for Bundle Size Optimization (Section 2)
|
|
47
|
+
- `server-` for Server-Side Performance (Section 3)
|
|
48
|
+
- `client-` for Client-Side Data Fetching (Section 4)
|
|
49
|
+
- `rerender-` for Re-render Optimization (Section 5)
|
|
50
|
+
- `rendering-` for Rendering Performance (Section 6)
|
|
51
|
+
- `js-` for JavaScript Performance (Section 7)
|
|
52
|
+
- `advanced-` for Advanced Patterns (Section 8)
|
|
53
|
+
3. Fill in the frontmatter and content
|
|
54
|
+
4. Ensure you have clear examples with explanations
|
|
55
|
+
5. Run `pnpm build` to regenerate AGENTS.md and test-cases.json
|
|
56
|
+
|
|
57
|
+
## Rule File Structure
|
|
58
|
+
|
|
59
|
+
Each rule file should follow this structure:
|
|
60
|
+
|
|
61
|
+
````markdown
|
|
62
|
+
---
|
|
63
|
+
title: Rule Title Here
|
|
64
|
+
impact: MEDIUM
|
|
65
|
+
impactDescription: Optional description
|
|
66
|
+
tags: tag1, tag2, tag3
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Rule Title Here
|
|
70
|
+
|
|
71
|
+
Brief explanation of the rule and why it matters.
|
|
72
|
+
|
|
73
|
+
**Incorrect (description of what's wrong):**
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Bad code example
|
|
77
|
+
```
|
|
78
|
+
````
|
|
79
|
+
|
|
80
|
+
**Correct (description of what's right):**
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Good code example
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Optional explanatory text after examples.
|
|
87
|
+
|
|
88
|
+
Reference: [Link](https://example.com)
|
|
89
|
+
|
|
90
|
+
## File Naming Convention
|
|
91
|
+
|
|
92
|
+
- Files starting with `_` are special (excluded from build)
|
|
93
|
+
- Rule files: `area-description.md` (e.g., `async-parallel.md`)
|
|
94
|
+
- Section is automatically inferred from filename prefix
|
|
95
|
+
- Rules are sorted alphabetically by title within each section
|
|
96
|
+
- IDs (e.g., 1.1, 1.2) are auto-generated during build
|
|
97
|
+
|
|
98
|
+
## Impact Levels
|
|
99
|
+
|
|
100
|
+
- `CRITICAL` - Highest priority, major performance gains
|
|
101
|
+
- `HIGH` - Significant performance improvements
|
|
102
|
+
- `MEDIUM-HIGH` - Moderate-high gains
|
|
103
|
+
- `MEDIUM` - Moderate performance improvements
|
|
104
|
+
- `LOW-MEDIUM` - Low-medium gains
|
|
105
|
+
- `LOW` - Incremental improvements
|
|
106
|
+
|
|
107
|
+
## Scripts
|
|
108
|
+
|
|
109
|
+
- `pnpm build` - Compile rules into AGENTS.md
|
|
110
|
+
- `pnpm validate` - Validate all rule files
|
|
111
|
+
- `pnpm extract-tests` - Extract test cases for LLM evaluation
|
|
112
|
+
- `pnpm dev` - Build and validate
|
|
113
|
+
|
|
114
|
+
## Contributing
|
|
115
|
+
|
|
116
|
+
When adding or modifying rules:
|
|
117
|
+
|
|
118
|
+
1. Use the correct filename prefix for your section
|
|
119
|
+
2. Follow the `_template.md` structure
|
|
120
|
+
3. Include clear bad/good examples with explanations
|
|
121
|
+
4. Add appropriate tags
|
|
122
|
+
5. Run `pnpm build` to regenerate AGENTS.md and test-cases.json
|
|
123
|
+
6. Rules are automatically sorted by title - no need to manage numbers!
|
|
124
|
+
|
|
125
|
+
## Acknowledgments
|
|
126
|
+
|
|
127
|
+
Originally created by [@shuding](https://x.com/shuding) at [Vercel](https://vercel.com).
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vercel-react-best-practices
|
|
3
|
+
description: React performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React code to ensure optimal performance patterns. Triggers on tasks involving React components, data fetching, bundle optimization, or performance improvements.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vercel React Best Practices
|
|
7
|
+
|
|
8
|
+
Comprehensive performance optimization guide for React applications, maintained by Vercel. Contains 35+ rules across 7 categories, prioritized by impact to guide automated refactoring and code generation.
|
|
9
|
+
|
|
10
|
+
## When to Apply
|
|
11
|
+
|
|
12
|
+
Reference these guidelines when:
|
|
13
|
+
|
|
14
|
+
- Writing new React components
|
|
15
|
+
- Implementing data fetching (client-side)
|
|
16
|
+
- Reviewing code for performance issues
|
|
17
|
+
- Refactoring existing React code
|
|
18
|
+
- Optimizing bundle size or load times
|
|
19
|
+
|
|
20
|
+
## Rule Categories by Priority
|
|
21
|
+
|
|
22
|
+
| Priority | Category | Impact | Prefix |
|
|
23
|
+
| -------- | ------------------------- | ----------- | ------------ |
|
|
24
|
+
| 1 | Eliminating Waterfalls | CRITICAL | `async-` |
|
|
25
|
+
| 2 | Bundle Size Optimization | CRITICAL | `bundle-` |
|
|
26
|
+
| 3 | Client-Side Data Fetching | MEDIUM-HIGH | `client-` |
|
|
27
|
+
| 4 | Re-render Optimization | MEDIUM | `rerender-` |
|
|
28
|
+
| 5 | Rendering Performance | MEDIUM | `rendering-` |
|
|
29
|
+
| 6 | JavaScript Performance | LOW-MEDIUM | `js-` |
|
|
30
|
+
| 7 | Advanced Patterns | LOW | `advanced-` |
|
|
31
|
+
|
|
32
|
+
## Quick Reference
|
|
33
|
+
|
|
34
|
+
### 1. Eliminating Waterfalls (CRITICAL)
|
|
35
|
+
|
|
36
|
+
- `async-defer-await` - Move await into branches where actually used
|
|
37
|
+
- `async-parallel` - Use Promise.all() for independent operations
|
|
38
|
+
- `async-dependencies` - Use better-all for partial dependencies
|
|
39
|
+
- `async-suspense-boundaries` - Use Suspense to stream content
|
|
40
|
+
|
|
41
|
+
### 2. Bundle Size Optimization (CRITICAL)
|
|
42
|
+
|
|
43
|
+
- `bundle-barrel-imports` - Import directly, avoid barrel files
|
|
44
|
+
- `bundle-conditional` - Load modules only when feature is activated
|
|
45
|
+
- `bundle-preload` - Preload on hover/focus for perceived speed
|
|
46
|
+
|
|
47
|
+
### 3. Client-Side Data Fetching (MEDIUM-HIGH)
|
|
48
|
+
|
|
49
|
+
- `client-swr-dedup` - Use React Query for automatic request deduplication
|
|
50
|
+
- `client-event-listeners` - Deduplicate global event listeners with useSyncExternalStore
|
|
51
|
+
|
|
52
|
+
### 4. Re-render Optimization (MEDIUM)
|
|
53
|
+
|
|
54
|
+
- `rerender-defer-reads` - Don't subscribe to state only used in callbacks
|
|
55
|
+
- `rerender-memo` - Extract expensive work into memoized components
|
|
56
|
+
- `rerender-dependencies` - Use primitive dependencies in effects
|
|
57
|
+
- `rerender-derived-state` - Subscribe to derived booleans, not raw values
|
|
58
|
+
- `rerender-functional-setstate` - Use functional setState for stable callbacks
|
|
59
|
+
- `rerender-lazy-state-init` - Pass function to useState for expensive values
|
|
60
|
+
- `rerender-transitions` - Use startTransition for non-urgent updates
|
|
61
|
+
|
|
62
|
+
### 4. Rendering Performance (MEDIUM)
|
|
63
|
+
|
|
64
|
+
- `rendering-animate-svg-wrapper` - Animate div wrapper, not SVG element
|
|
65
|
+
- `rendering-content-visibility` - Use content-visibility for long lists
|
|
66
|
+
- `rendering-hoist-jsx` - Extract static JSX outside components
|
|
67
|
+
- `rendering-svg-precision` - Reduce SVG coordinate precision
|
|
68
|
+
- `rendering-activity` - Use Activity component for show/hide
|
|
69
|
+
- `rendering-conditional-render` - Use ternary, not && for conditionals
|
|
70
|
+
|
|
71
|
+
### 5. JavaScript Performance (LOW-MEDIUM)
|
|
72
|
+
|
|
73
|
+
- `js-batch-dom-css` - Group CSS changes via classes or cssText
|
|
74
|
+
- `js-index-maps` - Build Map for repeated lookups
|
|
75
|
+
- `js-cache-property-access` - Cache object properties in loops
|
|
76
|
+
- `js-cache-function-results` - Cache function results in module-level Map
|
|
77
|
+
- `js-cache-storage` - Cache localStorage/sessionStorage reads
|
|
78
|
+
- `js-combine-iterations` - Combine multiple filter/map into one loop
|
|
79
|
+
- `js-length-check-first` - Check array length before expensive comparison
|
|
80
|
+
- `js-early-exit` - Return early from functions
|
|
81
|
+
- `js-hoist-regexp` - Hoist RegExp creation outside loops
|
|
82
|
+
- `js-min-max-loop` - Use loop for min/max instead of sort
|
|
83
|
+
- `js-set-map-lookups` - Use Set/Map for O(1) lookups
|
|
84
|
+
- `js-tosorted-immutable` - Use toSorted() for immutability
|
|
85
|
+
|
|
86
|
+
### 6. Advanced Patterns (LOW)
|
|
87
|
+
|
|
88
|
+
- `advanced-event-handler-refs` - Stable event handler references with useEffectEvent
|
|
89
|
+
- `advanced-use-latest` - Stable callbacks with useEffectEvent (React 19)
|
|
90
|
+
|
|
91
|
+
## How to Use
|
|
92
|
+
|
|
93
|
+
Read individual rule files for detailed explanations and code examples:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
rules/async-parallel.md
|
|
97
|
+
rules/bundle-barrel-imports.md
|
|
98
|
+
rules/_sections.md
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Each rule file contains:
|
|
102
|
+
|
|
103
|
+
- Brief explanation of why it matters
|
|
104
|
+
- Incorrect code example with explanation
|
|
105
|
+
- Correct code example with explanation
|
|
106
|
+
- Additional context and references
|
|
107
|
+
|
|
108
|
+
## Full Compiled Document
|
|
109
|
+
|
|
110
|
+
For the complete guide with all rules expanded: `AGENTS.md`
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.1.0",
|
|
3
|
+
"organization": "Vercel Engineering",
|
|
4
|
+
"date": "January 2026",
|
|
5
|
+
"abstract": "Comprehensive performance optimization guide for React applications, designed for AI agents and LLMs. Contains 40+ rules across 8 categories, prioritized by impact from critical (eliminating waterfalls, reducing bundle size) to incremental (advanced patterns). Each rule includes detailed explanations, real-world examples comparing incorrect vs. correct implementations, and specific impact metrics to guide automated refactoring and code generation.",
|
|
6
|
+
"references": [
|
|
7
|
+
"https://react.dev",
|
|
8
|
+
"https://swr.vercel.app",
|
|
9
|
+
"https://github.com/shuding/better-all",
|
|
10
|
+
"https://github.com/isaacs/node-lru-cache",
|
|
11
|
+
"https://vercel.com/blog/how-we-optimized-package-imports-in-next-js",
|
|
12
|
+
"https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Sections
|
|
2
|
+
|
|
3
|
+
This file defines all sections, their ordering, impact levels, and descriptions.
|
|
4
|
+
The section ID (in parentheses) is the filename prefix used to group rules.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Eliminating Waterfalls (async)
|
|
9
|
+
|
|
10
|
+
**Impact:** CRITICAL
|
|
11
|
+
**Description:** Waterfalls are the #1 performance killer. Each sequential await adds full network latency. Eliminating them yields the largest gains.
|
|
12
|
+
|
|
13
|
+
## 2. Bundle Size Optimization (bundle)
|
|
14
|
+
|
|
15
|
+
**Impact:** CRITICAL
|
|
16
|
+
**Description:** Reducing initial bundle size improves Time to Interactive and Largest Contentful Paint.
|
|
17
|
+
|
|
18
|
+
## 3. Client-Side Data Fetching (client)
|
|
19
|
+
|
|
20
|
+
**Impact:** MEDIUM-HIGH
|
|
21
|
+
**Description:** Automatic deduplication and efficient data fetching patterns reduce redundant network requests.
|
|
22
|
+
|
|
23
|
+
## 4. Re-render Optimization (rerender)
|
|
24
|
+
|
|
25
|
+
**Impact:** MEDIUM
|
|
26
|
+
**Description:** Reducing unnecessary re-renders minimizes wasted computation and improves UI responsiveness.
|
|
27
|
+
|
|
28
|
+
## 5. Rendering Performance (rendering)
|
|
29
|
+
|
|
30
|
+
**Impact:** MEDIUM
|
|
31
|
+
**Description:** Optimizing the rendering process reduces the work the browser needs to do.
|
|
32
|
+
|
|
33
|
+
## 6. JavaScript Performance (js)
|
|
34
|
+
|
|
35
|
+
**Impact:** LOW-MEDIUM
|
|
36
|
+
**Description:** Micro-optimizations for hot paths can add up to meaningful improvements.
|
|
37
|
+
|
|
38
|
+
## 7. Advanced Patterns (advanced)
|
|
39
|
+
|
|
40
|
+
**Impact:** LOW
|
|
41
|
+
**Description:** Advanced patterns for specific cases that require careful implementation.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Rule Title Here
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Optional description of impact (e.g., "20-50% improvement")
|
|
5
|
+
tags: tag1, tag2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Rule Title Here
|
|
9
|
+
|
|
10
|
+
**Impact: MEDIUM (optional impact description)**
|
|
11
|
+
|
|
12
|
+
Brief explanation of the rule and why it matters. This should be clear and concise, explaining the performance implications.
|
|
13
|
+
|
|
14
|
+
**Incorrect (description of what's wrong):**
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// Bad code example here
|
|
18
|
+
const bad = example()
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Correct (description of what's right):**
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// Good code example here
|
|
25
|
+
const good = example()
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Reference: [Link to documentation or resource](https://example.com)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Stable Event Handler References
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: stable subscriptions without re-subscribing
|
|
5
|
+
tags: advanced, hooks, useEffectEvent, refs, event-handlers, react-19
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Stable Event Handler References
|
|
9
|
+
|
|
10
|
+
Use `useEffectEvent` (React 19) for stable event handler references in effects. This prevents re-subscribing to events when callbacks change.
|
|
11
|
+
|
|
12
|
+
**React 19 with useEffectEvent (Recommended):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { useEffectEvent } from "react";
|
|
16
|
+
|
|
17
|
+
function useWindowEvent(event: string, handler: () => void) {
|
|
18
|
+
// useEffectEvent creates a stable reference that always calls latest handler
|
|
19
|
+
const onEvent = useEffectEvent(handler);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
window.addEventListener(event, onEvent);
|
|
23
|
+
return () => window.removeEventListener(event, onEvent);
|
|
24
|
+
}, [event]); // No need to include onEvent - it's always stable
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Usage
|
|
28
|
+
function Component({ onResize }: { onResize: () => void }) {
|
|
29
|
+
useWindowEvent("resize", onResize);
|
|
30
|
+
// Effect won't re-run when onResize changes!
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Why useEffectEvent?**
|
|
35
|
+
|
|
36
|
+
- Creates a stable function reference
|
|
37
|
+
- Always calls the latest version of the callback
|
|
38
|
+
- No stale closure issues
|
|
39
|
+
- Clean, official React API
|
|
40
|
+
|
|
41
|
+
**Incorrect (re-subscribes on every callback change):**
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
function useWindowEvent(event: string, handler: () => void) {
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
window.addEventListener(event, handler);
|
|
47
|
+
return () => window.removeEventListener(event, handler);
|
|
48
|
+
}, [event, handler]); // Re-subscribes when handler changes!
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Legacy fallback with refs (pre-React 19):**
|
|
53
|
+
|
|
54
|
+
If you're not on React 19, use the ref pattern:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
function useWindowEvent(event: string, handler: () => void) {
|
|
58
|
+
const handlerRef = useRef(handler);
|
|
59
|
+
|
|
60
|
+
// Keep ref updated with latest handler
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
handlerRef.current = handler;
|
|
63
|
+
}, [handler]);
|
|
64
|
+
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const listener = (e: Event) => handlerRef.current();
|
|
67
|
+
window.addEventListener(event, listener);
|
|
68
|
+
return () => window.removeEventListener(event, listener);
|
|
69
|
+
}, [event]);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Common use cases:**
|
|
74
|
+
|
|
75
|
+
- Window event listeners (resize, scroll, keydown)
|
|
76
|
+
- WebSocket message handlers
|
|
77
|
+
- Interval/timeout callbacks
|
|
78
|
+
- Any subscription that shouldn't re-subscribe on callback change
|
|
79
|
+
|
|
80
|
+
Reference: [useEffectEvent RFC](https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Stable Event Callbacks with useEffectEvent
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents effect re-runs and stale closures
|
|
5
|
+
tags: advanced, hooks, useEffectEvent, react-19, callbacks
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Stable Event Callbacks with useEffectEvent
|
|
9
|
+
|
|
10
|
+
Use `useEffectEvent` (React 19) to access latest values in effect callbacks without adding them to dependency arrays. This prevents effect re-runs while avoiding stale closures.
|
|
11
|
+
|
|
12
|
+
**Incorrect (effect re-runs on every callback change):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function SearchInput({ onSearch }: { onSearch: (q: string) => void }) {
|
|
16
|
+
const [query, setQuery] = useState("");
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const timeout = setTimeout(() => onSearch(query), 300);
|
|
20
|
+
return () => clearTimeout(timeout);
|
|
21
|
+
}, [query, onSearch]); // onSearch causes unnecessary re-runs
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (React 19 - useEffectEvent):**
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { useEffectEvent } from "react";
|
|
29
|
+
|
|
30
|
+
function SearchInput({ onSearch }: { onSearch: (q: string) => void }) {
|
|
31
|
+
const [query, setQuery] = useState("");
|
|
32
|
+
|
|
33
|
+
// useEffectEvent creates a stable reference that always calls the latest onSearch
|
|
34
|
+
const onSearchEvent = useEffectEvent((q: string) => {
|
|
35
|
+
onSearch(q);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const timeout = setTimeout(() => onSearchEvent(query), 300);
|
|
40
|
+
return () => clearTimeout(timeout);
|
|
41
|
+
}, [query]); // No need to include onSearchEvent - it's always stable
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Why useEffectEvent?**
|
|
46
|
+
|
|
47
|
+
- Always calls the latest version of the callback
|
|
48
|
+
- Stable reference - never triggers effect re-runs
|
|
49
|
+
- No stale closure bugs
|
|
50
|
+
- Official React 19 solution (replaces custom `useLatest` hooks)
|
|
51
|
+
|
|
52
|
+
**Legacy fallback (pre-React 19):**
|
|
53
|
+
|
|
54
|
+
If you're not on React 19 yet, use a ref-based pattern:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
function useLatest<T>(value: T) {
|
|
58
|
+
const ref = useRef(value);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
ref.current = value;
|
|
61
|
+
}, [value]);
|
|
62
|
+
return ref;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function SearchInput({ onSearch }: { onSearch: (q: string) => void }) {
|
|
66
|
+
const [query, setQuery] = useState("");
|
|
67
|
+
const onSearchRef = useLatest(onSearch);
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
const timeout = setTimeout(() => onSearchRef.current(query), 300);
|
|
71
|
+
return () => clearTimeout(timeout);
|
|
72
|
+
}, [query]);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Note:** Prefer `useEffectEvent` when available - it's the official React solution.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Defer Await Until Needed
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: avoids blocking unused code paths
|
|
5
|
+
tags: async, await, conditional, optimization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Defer Await Until Needed
|
|
9
|
+
|
|
10
|
+
Move `await` operations into the branches where they're actually used to avoid blocking code paths that don't need them.
|
|
11
|
+
|
|
12
|
+
**Incorrect (blocks both branches):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
async function handleRequest(userId: string, skipProcessing: boolean) {
|
|
16
|
+
const userData = await fetchUserData(userId)
|
|
17
|
+
|
|
18
|
+
if (skipProcessing) {
|
|
19
|
+
// Returns immediately but still waited for userData
|
|
20
|
+
return { skipped: true }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Only this branch uses userData
|
|
24
|
+
return processUserData(userData)
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Correct (only blocks when needed):**
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
async function handleRequest(userId: string, skipProcessing: boolean) {
|
|
32
|
+
if (skipProcessing) {
|
|
33
|
+
// Returns immediately without waiting
|
|
34
|
+
return { skipped: true }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Fetch only when needed
|
|
38
|
+
const userData = await fetchUserData(userId)
|
|
39
|
+
return processUserData(userData)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Another example (early return optimization):**
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Incorrect: always fetches permissions
|
|
47
|
+
async function updateResource(resourceId: string, userId: string) {
|
|
48
|
+
const permissions = await fetchPermissions(userId)
|
|
49
|
+
const resource = await getResource(resourceId)
|
|
50
|
+
|
|
51
|
+
if (!resource) {
|
|
52
|
+
return { error: 'Not found' }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!permissions.canEdit) {
|
|
56
|
+
return { error: 'Forbidden' }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return await updateResourceData(resource, permissions)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Correct: fetches only when needed
|
|
63
|
+
async function updateResource(resourceId: string, userId: string) {
|
|
64
|
+
const resource = await getResource(resourceId)
|
|
65
|
+
|
|
66
|
+
if (!resource) {
|
|
67
|
+
return { error: 'Not found' }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const permissions = await fetchPermissions(userId)
|
|
71
|
+
|
|
72
|
+
if (!permissions.canEdit) {
|
|
73
|
+
return { error: 'Forbidden' }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return await updateResourceData(resource, permissions)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This optimization is especially valuable when the skipped branch is frequently taken, or when the deferred operation is expensive.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Dependency-Based Parallelization
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: 2-10× improvement
|
|
5
|
+
tags: async, parallelization, dependencies, better-all
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Dependency-Based Parallelization
|
|
9
|
+
|
|
10
|
+
For operations with partial dependencies, use `better-all` to maximize parallelism. It automatically starts each task at the earliest possible moment.
|
|
11
|
+
|
|
12
|
+
**Incorrect (profile waits for config unnecessarily):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const [user, config] = await Promise.all([
|
|
16
|
+
fetchUser(),
|
|
17
|
+
fetchConfig()
|
|
18
|
+
])
|
|
19
|
+
const profile = await fetchProfile(user.id)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct (config and profile run in parallel):**
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { all } from 'better-all'
|
|
26
|
+
|
|
27
|
+
const { user, config, profile } = await all({
|
|
28
|
+
async user() { return fetchUser() },
|
|
29
|
+
async config() { return fetchConfig() },
|
|
30
|
+
async profile() {
|
|
31
|
+
return fetchProfile((await this.$.user).id)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Reference: [https://github.com/shuding/better-all](https://github.com/shuding/better-all)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Promise.all() for Independent Operations
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: 2-10× improvement
|
|
5
|
+
tags: async, parallelization, promises, waterfalls
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Promise.all() for Independent Operations
|
|
9
|
+
|
|
10
|
+
When async operations have no interdependencies, execute them concurrently using `Promise.all()`.
|
|
11
|
+
|
|
12
|
+
**Incorrect (sequential execution, 3 round trips):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const user = await fetchUser()
|
|
16
|
+
const posts = await fetchPosts()
|
|
17
|
+
const comments = await fetchComments()
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (parallel execution, 1 round trip):**
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
const [user, posts, comments] = await Promise.all([
|
|
24
|
+
fetchUser(),
|
|
25
|
+
fetchPosts(),
|
|
26
|
+
fetchComments()
|
|
27
|
+
])
|
|
28
|
+
```
|