ma-agents 3.2.0 → 3.3.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/.opencode/skills/.ma-agents.json +99 -99
- package/.roo/rules/00-ma-agents.md +13 -0
- package/.roo/skills/.ma-agents.json +241 -0
- package/.roo/skills/MANIFEST.yaml +254 -0
- package/.roo/skills/ai-audit-trail/SKILL.md +23 -0
- package/.roo/skills/auto-bug-detection/SKILL.md +169 -0
- package/.roo/skills/cmake-best-practices/SKILL.md +64 -0
- package/.roo/skills/cmake-best-practices/examples/cmake.md +59 -0
- package/.roo/skills/code-documentation/SKILL.md +57 -0
- package/.roo/skills/code-documentation/examples/cpp.md +29 -0
- package/.roo/skills/code-documentation/examples/csharp.md +28 -0
- package/.roo/skills/code-documentation/examples/javascript_typescript.md +28 -0
- package/.roo/skills/code-documentation/examples/python.md +57 -0
- package/.roo/skills/code-review/SKILL.md +43 -0
- package/.roo/skills/commit-message/SKILL.md +79 -0
- package/.roo/skills/cpp-best-practices/SKILL.md +234 -0
- package/.roo/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
- package/.roo/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
- package/.roo/skills/cpp-concurrency-safety/SKILL.md +60 -0
- package/.roo/skills/cpp-concurrency-safety/examples/concurrency.md +73 -0
- package/.roo/skills/cpp-const-correctness/SKILL.md +63 -0
- package/.roo/skills/cpp-const-correctness/examples/const_correctness.md +54 -0
- package/.roo/skills/cpp-memory-handling/SKILL.md +42 -0
- package/.roo/skills/cpp-memory-handling/examples/modern-cpp.md +49 -0
- package/.roo/skills/cpp-memory-handling/examples/smart-pointers.md +46 -0
- package/.roo/skills/cpp-modern-composition/SKILL.md +64 -0
- package/.roo/skills/cpp-modern-composition/examples/composition.md +51 -0
- package/.roo/skills/cpp-robust-interfaces/SKILL.md +55 -0
- package/.roo/skills/cpp-robust-interfaces/examples/interfaces.md +56 -0
- package/.roo/skills/create-hardened-docker-skill/SKILL.md +637 -0
- package/.roo/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -0
- package/.roo/skills/csharp-best-practices/SKILL.md +278 -0
- package/.roo/skills/docker-hardening-verification/SKILL.md +28 -0
- package/.roo/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -0
- package/.roo/skills/docker-image-signing/SKILL.md +28 -0
- package/.roo/skills/docker-image-signing/scripts/sign-image.sh +33 -0
- package/.roo/skills/document-revision-history/SKILL.md +104 -0
- package/.roo/skills/git-workflow-skill/SKILL.md +194 -0
- package/.roo/skills/git-workflow-skill/hooks/commit-msg +61 -0
- package/.roo/skills/git-workflow-skill/hooks/pre-commit +38 -0
- package/.roo/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -0
- package/.roo/skills/git-workflow-skill/scripts/finish-feature.sh +192 -0
- package/.roo/skills/git-workflow-skill/scripts/install-hooks.sh +55 -0
- package/.roo/skills/git-workflow-skill/scripts/start-feature.sh +110 -0
- package/.roo/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -0
- package/.roo/skills/js-ts-dependency-mgmt/SKILL.md +49 -0
- package/.roo/skills/js-ts-dependency-mgmt/examples/dependency_mgmt.md +60 -0
- package/.roo/skills/js-ts-security-skill/SKILL.md +64 -0
- package/.roo/skills/js-ts-security-skill/scripts/verify-security.sh +136 -0
- package/.roo/skills/logging-best-practices/SKILL.md +50 -0
- package/.roo/skills/logging-best-practices/examples/cpp.md +36 -0
- package/.roo/skills/logging-best-practices/examples/csharp.md +49 -0
- package/.roo/skills/logging-best-practices/examples/javascript.md +77 -0
- package/.roo/skills/logging-best-practices/examples/python.md +57 -0
- package/.roo/skills/logging-best-practices/references/logging-standards.md +29 -0
- package/.roo/skills/open-presentation/SKILL.md +35 -0
- package/.roo/skills/opentelemetry-best-practices/SKILL.md +34 -0
- package/.roo/skills/opentelemetry-best-practices/examples/go.md +32 -0
- package/.roo/skills/opentelemetry-best-practices/examples/javascript.md +58 -0
- package/.roo/skills/opentelemetry-best-practices/examples/python.md +37 -0
- package/.roo/skills/opentelemetry-best-practices/references/otel-standards.md +37 -0
- package/.roo/skills/python-best-practices/SKILL.md +385 -0
- package/.roo/skills/python-dependency-mgmt/SKILL.md +42 -0
- package/.roo/skills/python-dependency-mgmt/examples/dependency_mgmt.md +67 -0
- package/.roo/skills/python-security-skill/SKILL.md +56 -0
- package/.roo/skills/python-security-skill/examples/security.md +56 -0
- package/.roo/skills/self-signed-cert/SKILL.md +42 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.ps1 +45 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.sh +43 -0
- package/.roo/skills/skill-creator/SKILL.md +196 -0
- package/.roo/skills/skill-creator/references/output-patterns.md +82 -0
- package/.roo/skills/skill-creator/references/workflows.md +28 -0
- package/.roo/skills/skill-creator/scripts/init_skill.py +208 -0
- package/.roo/skills/skill-creator/scripts/package_skill.py +99 -0
- package/.roo/skills/skill-creator/scripts/quick_validate.py +113 -0
- package/.roo/skills/story-status-lookup/SKILL.md +78 -0
- package/.roo/skills/test-accompanied-development/SKILL.md +50 -0
- package/.roo/skills/test-generator/SKILL.md +65 -0
- package/.roo/skills/vercel-react-best-practices/SKILL.md +109 -0
- package/.roo/skills/verify-hardened-docker-skill/SKILL.md +442 -0
- package/.roo/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -0
- package/README.md +2 -1
- package/lib/agents.js +23 -0
- package/package.json +4 -3
- package/test/roo-code-agent.test.js +166 -0
- package/test/roo-code-injection.test.js +172 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Quick validation script for skills - minimal version
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import yaml
|
|
11
|
+
except ImportError:
|
|
12
|
+
yaml = None
|
|
13
|
+
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def validate_skill(skill_path):
|
|
18
|
+
"""Basic validation of a skill"""
|
|
19
|
+
skill_path = Path(skill_path)
|
|
20
|
+
|
|
21
|
+
# Check SKILL.md exists
|
|
22
|
+
skill_md = skill_path / 'SKILL.md'
|
|
23
|
+
if not skill_md.exists():
|
|
24
|
+
return False, "SKILL.md not found"
|
|
25
|
+
|
|
26
|
+
# Read and validate frontmatter
|
|
27
|
+
content = skill_md.read_text()
|
|
28
|
+
if not content.startswith('---'):
|
|
29
|
+
return False, "No YAML frontmatter found"
|
|
30
|
+
|
|
31
|
+
# Extract frontmatter
|
|
32
|
+
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
|
|
33
|
+
if not match:
|
|
34
|
+
return False, "Invalid frontmatter format"
|
|
35
|
+
|
|
36
|
+
frontmatter_text = match.group(1)
|
|
37
|
+
|
|
38
|
+
# Parse YAML frontmatter
|
|
39
|
+
if yaml is None:
|
|
40
|
+
# Fallback: basic key-value parsing if PyYAML not installed
|
|
41
|
+
frontmatter = {}
|
|
42
|
+
for line in frontmatter_text.strip().split('\n'):
|
|
43
|
+
if ':' in line:
|
|
44
|
+
key, _, value = line.partition(':')
|
|
45
|
+
frontmatter[key.strip()] = value.strip()
|
|
46
|
+
else:
|
|
47
|
+
try:
|
|
48
|
+
frontmatter = yaml.safe_load(frontmatter_text)
|
|
49
|
+
if not isinstance(frontmatter, dict):
|
|
50
|
+
return False, "Frontmatter must be a YAML dictionary"
|
|
51
|
+
except yaml.YAMLError as e:
|
|
52
|
+
return False, f"Invalid YAML in frontmatter: {e}"
|
|
53
|
+
|
|
54
|
+
# Define allowed properties
|
|
55
|
+
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata', 'compatibility'}
|
|
56
|
+
|
|
57
|
+
# Check for unexpected properties
|
|
58
|
+
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
|
|
59
|
+
if unexpected_keys:
|
|
60
|
+
return False, (
|
|
61
|
+
f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
|
|
62
|
+
f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Check required fields
|
|
66
|
+
if 'name' not in frontmatter:
|
|
67
|
+
return False, "Missing 'name' in frontmatter"
|
|
68
|
+
if 'description' not in frontmatter:
|
|
69
|
+
return False, "Missing 'description' in frontmatter"
|
|
70
|
+
|
|
71
|
+
# Validate name
|
|
72
|
+
name = frontmatter.get('name', '')
|
|
73
|
+
if not isinstance(name, str):
|
|
74
|
+
return False, f"Name must be a string, got {type(name).__name__}"
|
|
75
|
+
name = name.strip()
|
|
76
|
+
if name:
|
|
77
|
+
if not re.match(r'^[a-z0-9-]+$', name):
|
|
78
|
+
return False, f"Name '{name}' should be kebab-case (lowercase letters, digits, and hyphens only)"
|
|
79
|
+
if name.startswith('-') or name.endswith('-') or '--' in name:
|
|
80
|
+
return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
|
|
81
|
+
if len(name) > 64:
|
|
82
|
+
return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
|
|
83
|
+
|
|
84
|
+
# Validate description
|
|
85
|
+
description = frontmatter.get('description', '')
|
|
86
|
+
if not isinstance(description, str):
|
|
87
|
+
return False, f"Description must be a string, got {type(description).__name__}"
|
|
88
|
+
description = description.strip()
|
|
89
|
+
if description:
|
|
90
|
+
if '<' in description or '>' in description:
|
|
91
|
+
return False, "Description cannot contain angle brackets (< or >)"
|
|
92
|
+
if len(description) > 1024:
|
|
93
|
+
return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
|
|
94
|
+
|
|
95
|
+
# Validate compatibility if present
|
|
96
|
+
compatibility = frontmatter.get('compatibility', '')
|
|
97
|
+
if compatibility:
|
|
98
|
+
if not isinstance(compatibility, str):
|
|
99
|
+
return False, f"Compatibility must be a string, got {type(compatibility).__name__}"
|
|
100
|
+
if len(compatibility) > 500:
|
|
101
|
+
return False, f"Compatibility is too long ({len(compatibility)} characters). Maximum is 500 characters."
|
|
102
|
+
|
|
103
|
+
return True, "Skill is valid!"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
if len(sys.argv) != 2:
|
|
108
|
+
print("Usage: python quick_validate.py <skill_directory>")
|
|
109
|
+
sys.exit(1)
|
|
110
|
+
|
|
111
|
+
valid, message = validate_skill(sys.argv[1])
|
|
112
|
+
print(message)
|
|
113
|
+
sys.exit(0 if valid else 1)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: story-status-lookup
|
|
3
|
+
description: Looks up the current status of a story to classify code as delivered or work-in-progress. Supports file-system backend now; Jira backend reserved for future configuration.
|
|
4
|
+
---
|
|
5
|
+
# Story Status Lookup
|
|
6
|
+
|
|
7
|
+
Look up the current status of a story to determine whether its code is **delivered** or **work-in-progress**.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Used by other skills (notably `auto-bug-detection`) to classify code before deciding whether to flag defects.
|
|
12
|
+
Do not flag bugs in WIP code. Do flag bugs in delivered code.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Backend Configuration
|
|
17
|
+
|
|
18
|
+
Before performing a lookup, check the project context for the configured sprint management backend.
|
|
19
|
+
|
|
20
|
+
**Where to look (in priority order):**
|
|
21
|
+
1. `project-context.md` in the project root — look for a `sprint_management` field
|
|
22
|
+
2. The root directives file (`CLAUDE.md`, `.cursor/rules`, or equivalent for the active agent)
|
|
23
|
+
3. If neither defines a backend, **default to `file-system`**
|
|
24
|
+
|
|
25
|
+
| `sprint_management` value | Backend |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `file-system` or not set | Read `sprint-status.yaml` (see below) |
|
|
28
|
+
| `jira` | *(Future — see Jira section below)* |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## File-System Backend
|
|
33
|
+
|
|
34
|
+
**Status file:** `_bmad-output/implementation-artifacts/sprint-status.yaml`
|
|
35
|
+
|
|
36
|
+
### Step 1 — Identify the story slug
|
|
37
|
+
|
|
38
|
+
Derive the story slug from the available context, in this order of preference:
|
|
39
|
+
|
|
40
|
+
1. The story file name currently in scope (e.g. `11-1-auto-bug-detection-skill.md` → slug is `11-1-auto-bug-detection-skill`)
|
|
41
|
+
2. The git branch name — strip prefixes (`feature/`, `fix/`, `chore/`) and normalize: lowercase, replace spaces and underscores with hyphens, remove non-alphanumeric characters except hyphens
|
|
42
|
+
3. Any explicit story reference in the current task description
|
|
43
|
+
|
|
44
|
+
### Step 2 — Look up the slug
|
|
45
|
+
|
|
46
|
+
Find the slug as a key under `development_status` in `sprint-status.yaml`.
|
|
47
|
+
|
|
48
|
+
### Step 3 — Map status to delivered / WIP
|
|
49
|
+
|
|
50
|
+
| Status value | Classification | Action |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `done` | **Delivered** | Flag bugs |
|
|
53
|
+
| `review` | **Delivered** | Flag bugs — dev work is complete, code is awaiting review |
|
|
54
|
+
| `in-progress` | WIP | Do not flag |
|
|
55
|
+
| `ready-for-dev` | WIP | Do not flag |
|
|
56
|
+
| `backlog` | WIP | Do not flag |
|
|
57
|
+
| `on-hold` | WIP | Do not flag |
|
|
58
|
+
|
|
59
|
+
### Fallback rule
|
|
60
|
+
|
|
61
|
+
If any of the following are true, **classify as WIP and do not flag**:
|
|
62
|
+
- The story slug cannot be determined from context
|
|
63
|
+
- The slug is not found in `sprint-status.yaml`
|
|
64
|
+
- The status file does not exist
|
|
65
|
+
|
|
66
|
+
Never guess or assume delivered status. When in doubt, WIP.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Future: Jira Backend
|
|
71
|
+
|
|
72
|
+
When `sprint_management: jira` is set in the project context, this extension point applies:
|
|
73
|
+
|
|
74
|
+
- Jira base URL, project key, and credentials will be defined in the project context or environment config
|
|
75
|
+
- Query the Jira issue status API for the relevant issue key
|
|
76
|
+
- Map the Jira workflow status to delivered/WIP using a status mapping defined in the project context
|
|
77
|
+
|
|
78
|
+
**This backend is not yet implemented.** When Jira support is added, update this skill with the lookup procedure and status mapping. The file-system backend remains the default fallback if Jira is unreachable.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Test-Accompanied Development
|
|
3
|
+
description: Enforces writing unit tests for every new public method created by the agent.
|
|
4
|
+
---
|
|
5
|
+
# Test-Accompanied Development (TAD)
|
|
6
|
+
|
|
7
|
+
Enforce a "Test-Alongside" policy where every public method is accompanied by a corresponding unit test.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
To ensure high code quality and maintainability by mandating that all public interfaces are verified by automated tests at the moment of creation.
|
|
12
|
+
|
|
13
|
+
## Policy
|
|
14
|
+
|
|
15
|
+
**Every new public method/function you write MUST be accompanied by at least one unit test.**
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
- Use this skill **every time** you are about to write a new public method or function.
|
|
20
|
+
- This skill should be active during the coding phase of any feature or bug fix.
|
|
21
|
+
|
|
22
|
+
## Instructions
|
|
23
|
+
|
|
24
|
+
1. **Identify Public Exports**: When preparing to write a new class, module, or function, identify which methods will be public/exported.
|
|
25
|
+
2. **Plan the Test**: Before or immediately after writing the method signature, plan the corresponding test cases (Happy Path, Edge Cases, Error Cases).
|
|
26
|
+
3. **Write the Method**: Implement the public method.
|
|
27
|
+
4. **Write the Tests**: Immediately write the unit tests for the method.
|
|
28
|
+
- Refer to the `test-generator` skill for best practices on how to structure these tests (AAA pattern, Mocking, etc.).
|
|
29
|
+
- Ensure tests are placed in the appropriate test directory of the project.
|
|
30
|
+
5. **Verify**: Run the tests to ensure they pass before considering the method "done".
|
|
31
|
+
|
|
32
|
+
## Rules
|
|
33
|
+
|
|
34
|
+
- **No Public Method without Tests**: Do not consider a public method complete until its corresponding test file exists and passes.
|
|
35
|
+
- **Refer to Test Generator**: Use the `test-generator` skill as the standard for test quality and structure.
|
|
36
|
+
- **Traceability**: Mention the test file location when adding the public method.
|
|
37
|
+
|
|
38
|
+
## Example Workflow
|
|
39
|
+
|
|
40
|
+
### TypeScript (Jest)
|
|
41
|
+
1. **Agent**: "I am adding a `calculateTotal` method to the `InvoiceService`. I will also create `InvoiceService.test.ts` to verify it."
|
|
42
|
+
2. **Agent**: [Writes `calculateTotal` in `InvoiceService.ts`]
|
|
43
|
+
3. **Agent**: [Writes tests in `InvoiceService.test.ts` using `test-generator` patterns]
|
|
44
|
+
4. **Agent**: "Method and tests are complete. Running tests now..."
|
|
45
|
+
|
|
46
|
+
### Python (Pytest)
|
|
47
|
+
1. **Agent**: "I am adding a `validate_user` function to `auth.py`. I will also create `tests/test_auth.py` to verify it."
|
|
48
|
+
2. **Agent**: [Writes `validate_user` in `auth.py`]
|
|
49
|
+
3. **Agent**: [Writes tests in `tests/test_auth.py` using `test-generator` patterns]
|
|
50
|
+
4. **Agent**: "Implementation and tests are ready. Running `pytest`."
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Test Generator
|
|
3
|
+
description: Generates comprehensive unit and integration tests
|
|
4
|
+
---
|
|
5
|
+
# Test Generator
|
|
6
|
+
|
|
7
|
+
Generate comprehensive unit and integration tests for code.
|
|
8
|
+
|
|
9
|
+
## Process
|
|
10
|
+
|
|
11
|
+
1. **Analyze**: Understand code purpose, paths, dependencies, edge cases
|
|
12
|
+
2. **Framework**: Determine or ask for testing framework
|
|
13
|
+
3. **Generate**: Create test cases covering:
|
|
14
|
+
- Happy path (normal behavior)
|
|
15
|
+
- Edge cases (boundaries, empty/null inputs)
|
|
16
|
+
- Error cases (invalid inputs, exceptions)
|
|
17
|
+
- Integration scenarios (if applicable)
|
|
18
|
+
|
|
19
|
+
## Test Structure (AAA Pattern)
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
- Arrange: Setup test data
|
|
23
|
+
- Act: Execute code
|
|
24
|
+
- Assert: Verify results
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Coverage Goals
|
|
28
|
+
|
|
29
|
+
- 80%+ code coverage
|
|
30
|
+
- All public methods
|
|
31
|
+
- All conditional branches
|
|
32
|
+
- Positive and negative cases
|
|
33
|
+
|
|
34
|
+
## Best Practices
|
|
35
|
+
|
|
36
|
+
- One assertion per test
|
|
37
|
+
- Independent tests
|
|
38
|
+
- Descriptive test names
|
|
39
|
+
- Mock external dependencies
|
|
40
|
+
- Clear assertion messages
|
|
41
|
+
|
|
42
|
+
## Example Output
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
describe('ComponentName', () => {
|
|
46
|
+
test('should [behavior] when [condition]', () => {
|
|
47
|
+
// Arrange
|
|
48
|
+
const input = setupTestData();
|
|
49
|
+
|
|
50
|
+
// Act
|
|
51
|
+
const result = functionUnderTest(input);
|
|
52
|
+
|
|
53
|
+
// Assert
|
|
54
|
+
expect(result).toEqual(expectedOutput);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('should handle edge case', () => {
|
|
58
|
+
// ...
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('should throw on invalid input', () => {
|
|
62
|
+
expect(() => fn(invalid)).toThrow();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Vercel React Best Practices
|
|
3
|
+
description: Performance optimization framework for React and Next.js projects with 57 actionable rules across 8 categories
|
|
4
|
+
---
|
|
5
|
+
# Vercel React Best Practices
|
|
6
|
+
|
|
7
|
+
A thorough performance optimization framework for React and Next.js projects. Contains 57 actionable rules organized into 8 categories, ranked by potential impact.
|
|
8
|
+
|
|
9
|
+
## When to Apply
|
|
10
|
+
|
|
11
|
+
Reference these guidelines when:
|
|
12
|
+
- Writing new React components
|
|
13
|
+
- Implementing data fetching
|
|
14
|
+
- Reviewing code for performance concerns
|
|
15
|
+
- Refactoring existing applications
|
|
16
|
+
- Reducing bundle sizes and load times
|
|
17
|
+
|
|
18
|
+
## Rule Categories (Priority-Ordered)
|
|
19
|
+
|
|
20
|
+
### 1. Eliminating Waterfalls (CRITICAL)
|
|
21
|
+
Prefix: `async-`
|
|
22
|
+
|
|
23
|
+
- Avoid sequential data fetching — use parallel requests (`Promise.all`, `Promise.allSettled`)
|
|
24
|
+
- Prefetch data at the layout/page level rather than in deeply nested components
|
|
25
|
+
- Use `loading.tsx` and `Suspense` boundaries to stream content progressively
|
|
26
|
+
- Avoid `await` chains where requests don't depend on each other
|
|
27
|
+
- Colocate data fetching with the component that uses the data, but fetch in parallel at the route level
|
|
28
|
+
- Use React Server Components to move data fetching to the server and eliminate client-server waterfalls
|
|
29
|
+
|
|
30
|
+
### 2. Bundle Size Optimization (CRITICAL)
|
|
31
|
+
Prefix: `bundle-`
|
|
32
|
+
|
|
33
|
+
- Prefer `next/dynamic` or `React.lazy` for heavy components not needed on initial load
|
|
34
|
+
- Audit dependencies with `@next/bundle-analyzer` — remove or replace bloated packages
|
|
35
|
+
- Use tree-shakeable libraries and import only what you need (`import { x } from 'lib'` not `import lib from 'lib'`)
|
|
36
|
+
- Mark client components with `'use client'` only at the lowest necessary level
|
|
37
|
+
- Avoid importing server-only code into client components
|
|
38
|
+
- Use `next/image` instead of raw `<img>` tags for automatic optimization
|
|
39
|
+
- Use `next/font` to self-host fonts and eliminate external font requests
|
|
40
|
+
|
|
41
|
+
### 3. Server-Side Performance (HIGH)
|
|
42
|
+
Prefix: `server-`
|
|
43
|
+
|
|
44
|
+
- Default to React Server Components — only add `'use client'` when interactivity is needed
|
|
45
|
+
- Use the `cache()` function to deduplicate identical requests within a single render
|
|
46
|
+
- Leverage `unstable_cache` or `fetch` cache options for cross-request caching
|
|
47
|
+
- Set proper `revalidate` values — avoid `revalidate: 0` unless data truly changes on every request
|
|
48
|
+
- Use `generateStaticParams` for static generation of dynamic routes
|
|
49
|
+
- Move database queries and API calls to Server Components or Route Handlers
|
|
50
|
+
- Use streaming (`loading.tsx`, `Suspense`) to avoid blocking the entire page on slow data
|
|
51
|
+
|
|
52
|
+
### 4. Client-Side Data Fetching (MEDIUM-HIGH)
|
|
53
|
+
Prefix: `client-`
|
|
54
|
+
|
|
55
|
+
- Use SWR or React Query for client-side data fetching with caching, revalidation, and deduplication
|
|
56
|
+
- Implement optimistic updates for mutations to improve perceived performance
|
|
57
|
+
- Set appropriate `staleTime` and `cacheTime` to avoid unnecessary refetches
|
|
58
|
+
- Use `prefetchQuery` or `preload` to start fetching before navigation
|
|
59
|
+
- Avoid `useEffect` + `fetch` patterns — prefer dedicated data fetching libraries
|
|
60
|
+
- Paginate or infinitely scroll large datasets instead of loading everything at once
|
|
61
|
+
|
|
62
|
+
### 5. Re-render Optimization (MEDIUM)
|
|
63
|
+
Prefix: `rerender-`
|
|
64
|
+
|
|
65
|
+
- Lift state up only as far as necessary — keep state close to where it's used
|
|
66
|
+
- Split contexts to avoid triggering unnecessary re-renders on unrelated state changes
|
|
67
|
+
- Use `useMemo` and `useCallback` only for expensive computations or stable references passed to memoized children
|
|
68
|
+
- Avoid creating new objects/arrays in render — extract them as constants or memoize them
|
|
69
|
+
- Use `React.memo` for pure components that re-render often with the same props
|
|
70
|
+
- Prefer `useRef` over `useState` for values that don't need to trigger re-renders
|
|
71
|
+
- Avoid prop drilling — use composition (`children` prop) instead of deep prop chains
|
|
72
|
+
|
|
73
|
+
### 6. Rendering Performance (MEDIUM)
|
|
74
|
+
Prefix: `rendering-`
|
|
75
|
+
|
|
76
|
+
- Virtualize long lists with `react-window` or `@tanstack/virtual`
|
|
77
|
+
- Debounce rapid user inputs (search, resize, scroll handlers)
|
|
78
|
+
- Use CSS for animations and transitions instead of JS-driven re-renders
|
|
79
|
+
- Use `content-visibility: auto` for off-screen content
|
|
80
|
+
- Avoid layout thrashing — batch DOM reads and writes
|
|
81
|
+
- Use `will-change` sparingly and only on elements that will actually animate
|
|
82
|
+
- Prefer `transform` and `opacity` for GPU-accelerated animations
|
|
83
|
+
|
|
84
|
+
### 7. JavaScript Performance (LOW-MEDIUM)
|
|
85
|
+
Prefix: `js-`
|
|
86
|
+
|
|
87
|
+
- Avoid blocking the main thread — use `requestIdleCallback` or Web Workers for heavy computation
|
|
88
|
+
- Use `Map` and `Set` for frequent lookups instead of arrays
|
|
89
|
+
- Minimize closures in hot paths
|
|
90
|
+
- Prefer `for...of` or `Array.prototype` methods over manual loops for readability, but use manual loops in performance-critical sections
|
|
91
|
+
- Avoid deep cloning — use structural sharing (Immer) or shallow copies where possible
|
|
92
|
+
- Use `AbortController` to cancel stale requests and avoid race conditions
|
|
93
|
+
|
|
94
|
+
### 8. Advanced Patterns (LOW)
|
|
95
|
+
Prefix: `advanced-`
|
|
96
|
+
|
|
97
|
+
- Use the `Offscreen` API (when stable) for pre-rendering hidden UI
|
|
98
|
+
- Implement route-level code splitting with parallel route segments
|
|
99
|
+
- Use Edge Runtime for latency-sensitive API routes
|
|
100
|
+
- Implement partial prerendering (PPR) for hybrid static/dynamic pages
|
|
101
|
+
- Use `Server Actions` for form mutations to avoid manual API routes
|
|
102
|
+
- Profile with React DevTools Profiler and Chrome Performance tab before optimizing
|
|
103
|
+
|
|
104
|
+
## General Principles
|
|
105
|
+
|
|
106
|
+
- **Measure before optimizing** — use Lighthouse, Web Vitals, and React DevTools
|
|
107
|
+
- **Higher-priority categories yield larger gains** — focus on waterfalls and bundle size first
|
|
108
|
+
- **Don't prematurely optimize** — only apply lower-priority rules after addressing critical ones
|
|
109
|
+
- **Test performance changes** — verify improvements with real metrics, not just intuition
|