codingwithagent 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/bin/init.js +257 -0
- package/package.json +56 -0
- package/templates/accessibility/.cursorrules +342 -0
- package/templates/accessibility/README.md +47 -0
- package/templates/antigravity/accessibility/.agent/rules/accessibility.md +501 -0
- package/templates/antigravity/accessibility/.agent/rules/aria-patterns.md +568 -0
- package/templates/antigravity/accessibility/.agent/rules/wcag-standard.md +225 -0
- package/templates/antigravity/accessibility/README.md +42 -0
- package/templates/antigravity/minimal/.agent/rules/accessibility.md +53 -0
- package/templates/antigravity/minimal/.agent/rules/code-quality.md +86 -0
- package/templates/antigravity/minimal/.agent/rules/react-components.md +164 -0
- package/templates/antigravity/minimal/README.md +34 -0
- package/templates/antigravity/standard/.agent/rules/accessibility.md +98 -0
- package/templates/antigravity/standard/.agent/rules/code-quality.md +166 -0
- package/templates/antigravity/standard/.agent/rules/pull-request-review.md +192 -0
- package/templates/antigravity/standard/.agent/rules/react-components.md +204 -0
- package/templates/antigravity/standard/.agent/rules/testing.md +197 -0
- package/templates/antigravity/standard/README.md +39 -0
- package/templates/antigravity/strict/.agent/README.md +46 -0
- package/templates/antigravity/strict/.agent/rules/accessibility.md +199 -0
- package/templates/antigravity/strict/.agent/rules/code-quality.md +268 -0
- package/templates/antigravity/strict/.agent/rules/pull-request-review.md +114 -0
- package/templates/antigravity/strict/.agent/rules/react-components.md +423 -0
- package/templates/antigravity/strict/.agent/rules/security.md +483 -0
- package/templates/antigravity/strict/.agent/rules/testing.md +280 -0
- package/templates/minimal/.cursorrules +48 -0
- package/templates/minimal/README.md +40 -0
- package/templates/standard/.cursorrules +184 -0
- package/templates/standard/README.md +43 -0
- package/templates/strict/.cursorrules +227 -0
- package/templates/strict/README.md +47 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: always_on
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# React Component Standards - STRICT (Maximum Quality)
|
|
6
|
+
|
|
7
|
+
## Component Architecture - MANDATORY
|
|
8
|
+
|
|
9
|
+
### Separation of Concerns - STRICT
|
|
10
|
+
|
|
11
|
+
- **Containers**: Redux connection ONLY (no JSX, max 50 lines)
|
|
12
|
+
- **Components**: Pure presentational ONLY (no business logic)
|
|
13
|
+
- **Utils**: Pure functions ONLY (no side effects, fully testable)
|
|
14
|
+
- **Selectors**: Data transformation ONLY (no side effects, memoized)
|
|
15
|
+
- **Sagas**: Side effects ONLY (no direct state mutations)
|
|
16
|
+
|
|
17
|
+
### Component Design - ZERO TOLERANCE
|
|
18
|
+
|
|
19
|
+
- Components MUST be stateless when possible
|
|
20
|
+
- Single Responsibility Principle (ONE purpose ONLY)
|
|
21
|
+
- Maximum component size: 150 lines (not 200)
|
|
22
|
+
- NO dependencies outside props (complete isolation)
|
|
23
|
+
- NO side effects in render
|
|
24
|
+
|
|
25
|
+
## Functional Components - MANDATORY
|
|
26
|
+
|
|
27
|
+
### Requirements - ALL ENFORCED
|
|
28
|
+
|
|
29
|
+
- Functional components with hooks ONLY
|
|
30
|
+
- Class components = automatic PR rejection
|
|
31
|
+
- TypeScript REQUIRED with explicit types
|
|
32
|
+
- PropTypes AND TypeScript interfaces (both required)
|
|
33
|
+
- JSDoc comments REQUIRED
|
|
34
|
+
|
|
35
|
+
### Component Structure - STRICT ORDER
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
/**
|
|
39
|
+
* ComponentName description
|
|
40
|
+
* @param {Props} props - Component props
|
|
41
|
+
* @returns {JSX.Element} Rendered component
|
|
42
|
+
*/
|
|
43
|
+
const ComponentName: React.FC<Props> = ({ prop1, prop2 }) => {
|
|
44
|
+
// 1. Hooks (in order: useState, useEffect, useCallback, useMemo, useRef)
|
|
45
|
+
const [state, setState] = useState<Type>(initialValue);
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
// side effects
|
|
49
|
+
return () => cleanup();
|
|
50
|
+
}, [dependencies]); // dependencies MUST be complete
|
|
51
|
+
|
|
52
|
+
const handleEvent = useCallback(() => {
|
|
53
|
+
// handler logic
|
|
54
|
+
}, [dependencies]);
|
|
55
|
+
|
|
56
|
+
const computedValue = useMemo(() => {
|
|
57
|
+
return expensiveCalculation();
|
|
58
|
+
}, [dependencies]);
|
|
59
|
+
|
|
60
|
+
// 2. Early returns
|
|
61
|
+
if (!prop1) return null;
|
|
62
|
+
if (error) return <ErrorMessage />;
|
|
63
|
+
|
|
64
|
+
// 3. Render
|
|
65
|
+
return <div>{/* JSX */}</div>;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
ComponentName.propTypes = {
|
|
69
|
+
prop1: PropTypes.string.isRequired,
|
|
70
|
+
prop2: PropTypes.number,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
ComponentName.defaultProps = {
|
|
74
|
+
prop2: 0,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default ComponentName;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Hooks - STRICT ENFORCEMENT
|
|
81
|
+
|
|
82
|
+
### useState - STRICT RULES
|
|
83
|
+
|
|
84
|
+
- UI-only state (modals, toggles, focus)
|
|
85
|
+
- NO business logic in state
|
|
86
|
+
- NO API data in state (use Redux)
|
|
87
|
+
- Explicit types REQUIRED
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// CORRECT
|
|
91
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
92
|
+
|
|
93
|
+
// INCORRECT
|
|
94
|
+
const [isOpen, setIsOpen] = useState(false); // missing type
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### useEffect - ZERO TOLERANCE
|
|
98
|
+
|
|
99
|
+
- Dependencies array REQUIRED (no empty array without justification)
|
|
100
|
+
- Cleanup function REQUIRED for subscriptions
|
|
101
|
+
- NO async functions directly (use async inside)
|
|
102
|
+
- exhaustive-deps ESLint rule MUST pass
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// CORRECT
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const subscription = subscribe();
|
|
108
|
+
return () => subscription.unsubscribe();
|
|
109
|
+
}, [dependency1, dependency2]);
|
|
110
|
+
|
|
111
|
+
// INCORRECT - missing cleanup
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
subscribe();
|
|
114
|
+
}, [dependency]);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### useCallback - REQUIRED FOR ALL CALLBACKS
|
|
118
|
+
|
|
119
|
+
- ALL callback props MUST use useCallback
|
|
120
|
+
- ALL event handlers passed as props MUST use useCallback
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// CORRECT
|
|
124
|
+
const handleClick = useCallback(() => {
|
|
125
|
+
doSomething(value);
|
|
126
|
+
}, [value]);
|
|
127
|
+
|
|
128
|
+
// INCORRECT - will cause re-renders
|
|
129
|
+
const handleClick = () => {
|
|
130
|
+
doSomething(value);
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### useMemo - REQUIRED FOR OBJECTS/ARRAYS AS PROPS
|
|
135
|
+
|
|
136
|
+
- ALL objects passed as props MUST use useMemo
|
|
137
|
+
- ALL arrays passed as props MUST use useMemo
|
|
138
|
+
- Expensive calculations MUST use useMemo
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// CORRECT
|
|
142
|
+
const user = useMemo(
|
|
143
|
+
() => ({
|
|
144
|
+
name,
|
|
145
|
+
email,
|
|
146
|
+
}),
|
|
147
|
+
[name, email]
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// INCORRECT - new object on every render
|
|
151
|
+
const user = { name, email };
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### useRef - STRICT USAGE
|
|
155
|
+
|
|
156
|
+
- DOM access ONLY (no alternative state storage)
|
|
157
|
+
- Access in useEffect or event handlers ONLY (not in render)
|
|
158
|
+
- Cleanup in useEffect return REQUIRED
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// CORRECT
|
|
162
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
163
|
+
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
inputRef.current?.focus();
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
// INCORRECT - accessing in render
|
|
169
|
+
const value = inputRef.current?.value; // NO!
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Custom Hooks - MANDATORY PATTERNS
|
|
173
|
+
|
|
174
|
+
- Prefix with "use" (REQUIRED)
|
|
175
|
+
- Return array or object (consistent pattern)
|
|
176
|
+
- Document with JSDoc
|
|
177
|
+
- Test in isolation
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
/**
|
|
181
|
+
* Custom hook for form validation
|
|
182
|
+
* @param {string} value - Value to validate
|
|
183
|
+
* @returns {Object} Validation result
|
|
184
|
+
*/
|
|
185
|
+
const useFormValidation = (value: string): ValidationResult => {
|
|
186
|
+
const [isValid, setIsValid] = useState<boolean>(false);
|
|
187
|
+
const [error, setError] = useState<string>("");
|
|
188
|
+
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
// validation logic
|
|
191
|
+
}, [value]);
|
|
192
|
+
|
|
193
|
+
return { isValid, error };
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Props - MAXIMUM ENFORCEMENT
|
|
198
|
+
|
|
199
|
+
### Props Requirements - ALL MANDATORY
|
|
200
|
+
|
|
201
|
+
- Destructure at function signature (REQUIRED)
|
|
202
|
+
- TypeScript interface REQUIRED
|
|
203
|
+
- PropTypes REQUIRED (in addition to TypeScript)
|
|
204
|
+
- Mark required props with .isRequired
|
|
205
|
+
- defaultProps for ALL optional props
|
|
206
|
+
- NO prop drilling beyond 2 levels (stricter than standard)
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// CORRECT - Full typing
|
|
210
|
+
interface Props {
|
|
211
|
+
title: string;
|
|
212
|
+
count?: number;
|
|
213
|
+
onSubmit: () => void;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const Component: React.FC<Props> = ({ title, count = 0, onSubmit }) => {
|
|
217
|
+
return (
|
|
218
|
+
<div>
|
|
219
|
+
{title}: {count}
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
Component.propTypes = {
|
|
225
|
+
title: PropTypes.string.isRequired,
|
|
226
|
+
count: PropTypes.number,
|
|
227
|
+
onSubmit: PropTypes.func.isRequired,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// INCORRECT - Missing types or destructuring
|
|
231
|
+
const Component = (props) => {
|
|
232
|
+
// NO!
|
|
233
|
+
return <div>{props.title}</div>;
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Props Validation - STRICT
|
|
238
|
+
|
|
239
|
+
- Validate ALL props (PropTypes + TypeScript)
|
|
240
|
+
- NO any type for props
|
|
241
|
+
- NO optional props without defaults
|
|
242
|
+
- Complex objects MUST have shape definitions
|
|
243
|
+
|
|
244
|
+
## JSX - ZERO TOLERANCE
|
|
245
|
+
|
|
246
|
+
### MANDATORY Rules - ALL ENFORCED
|
|
247
|
+
|
|
248
|
+
- NO anonymous functions (declare all handlers)
|
|
249
|
+
- NO inline styles (styled-components ONLY)
|
|
250
|
+
- NO array index as key
|
|
251
|
+
- NO non-boolean conditional rendering
|
|
252
|
+
- NO nested ternaries (max depth: 1)
|
|
253
|
+
- NO complex logic (extract to functions)
|
|
254
|
+
- Semantic HTML REQUIRED
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// CORRECT
|
|
258
|
+
const handleClick = useCallback(() => {
|
|
259
|
+
doSomething();
|
|
260
|
+
}, []);
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<button onClick={handleClick}>{isLoading ? <Spinner /> : "Submit"}</button>
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
// INCORRECT - multiple violations
|
|
267
|
+
return (
|
|
268
|
+
<div onClick={() => doSomething()}>
|
|
269
|
+
{" "}
|
|
270
|
+
{/* anonymous function */}
|
|
271
|
+
{count && <Display />} {/* non-boolean */}
|
|
272
|
+
{a ? (b ? c : d) : e} {/* nested ternary */}
|
|
273
|
+
</div>
|
|
274
|
+
);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Conditional Rendering - STRICT
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// CORRECT - Boolean condition
|
|
281
|
+
{
|
|
282
|
+
isLoggedIn && <Dashboard />;
|
|
283
|
+
}
|
|
284
|
+
{
|
|
285
|
+
isLoading ? <Spinner /> : <Content />;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// INCORRECT - Can render "0"
|
|
289
|
+
{
|
|
290
|
+
count && <Display />;
|
|
291
|
+
} // NO! Use count > 0
|
|
292
|
+
|
|
293
|
+
// INCORRECT - Nested ternary
|
|
294
|
+
{
|
|
295
|
+
a ? (b ? c : d) : e;
|
|
296
|
+
} // NO! Extract to function
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Lists - STRICT REQUIREMENTS
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
// CORRECT - Key from data
|
|
303
|
+
{
|
|
304
|
+
users.map((user) => <UserCard key={user.id} {...user} />);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// INCORRECT - Index as key
|
|
308
|
+
{
|
|
309
|
+
users.map((user, index) => (
|
|
310
|
+
<UserCard key={index} {...user} /> // REJECTED!
|
|
311
|
+
));
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Component Complexity - STRICT LIMITS
|
|
316
|
+
|
|
317
|
+
### When to Refactor - MANDATORY
|
|
318
|
+
|
|
319
|
+
- Component exceeds 150 lines (HARD LIMIT)
|
|
320
|
+
- More than 8 props (HARD LIMIT)
|
|
321
|
+
- More than 5 hooks (HARD LIMIT)
|
|
322
|
+
- Cyclomatic complexity > 10
|
|
323
|
+
- Any nested ternaries
|
|
324
|
+
- Duplicate logic
|
|
325
|
+
|
|
326
|
+
### Refactoring - REQUIRED
|
|
327
|
+
|
|
328
|
+
- Extract child components immediately
|
|
329
|
+
- Create custom hooks for complex logic
|
|
330
|
+
- Move business logic to selectors
|
|
331
|
+
- Use composition pattern
|
|
332
|
+
- Split container and component
|
|
333
|
+
|
|
334
|
+
## DOM Access - SEVERELY RESTRICTED
|
|
335
|
+
|
|
336
|
+
### Prohibited - AUTOMATIC REJECTION
|
|
337
|
+
|
|
338
|
+
- NO document.querySelector
|
|
339
|
+
- NO document.getElementById
|
|
340
|
+
- NO direct DOM manipulation
|
|
341
|
+
- NO window object access
|
|
342
|
+
- NO document object access
|
|
343
|
+
|
|
344
|
+
### Allowed - ONLY WITH JUSTIFICATION
|
|
345
|
+
|
|
346
|
+
- useRef for focus management
|
|
347
|
+
- useRef for third-party library integration
|
|
348
|
+
- useRef for measuring (with cleanup)
|
|
349
|
+
|
|
350
|
+
## Performance - STRICT REQUIREMENTS
|
|
351
|
+
|
|
352
|
+
### Optimization - ALL REQUIRED
|
|
353
|
+
|
|
354
|
+
- React.memo for ALL pure components
|
|
355
|
+
- useCallback for ALL callback props
|
|
356
|
+
- useMemo for ALL object/array props
|
|
357
|
+
- useMemo for expensive calculations (>10ms)
|
|
358
|
+
- List virtualization for >50 items
|
|
359
|
+
- Code splitting for >100KB components
|
|
360
|
+
|
|
361
|
+
### Performance Monitoring - MANDATORY
|
|
362
|
+
|
|
363
|
+
- React DevTools Profiler analysis REQUIRED
|
|
364
|
+
- Performance budget: <100ms render time
|
|
365
|
+
- Re-render count < 3 per user action
|
|
366
|
+
- Bundle size per component: <50KB
|
|
367
|
+
|
|
368
|
+
## Testing - STRICT REQUIREMENTS
|
|
369
|
+
|
|
370
|
+
### Test Coverage - MANDATORY
|
|
371
|
+
|
|
372
|
+
- 100% coverage for components (not 90%)
|
|
373
|
+
- ALL props combinations tested
|
|
374
|
+
- ALL event handlers tested
|
|
375
|
+
- ALL conditional renders tested
|
|
376
|
+
- ALL hooks tested
|
|
377
|
+
- ALL error states tested
|
|
378
|
+
|
|
379
|
+
### Test Quality - ZERO TOLERANCE
|
|
380
|
+
|
|
381
|
+
- NO snapshot tests (explicit assertions ONLY)
|
|
382
|
+
- Descriptive test names REQUIRED
|
|
383
|
+
- Test user behavior, not implementation
|
|
384
|
+
- Mock ALL external dependencies
|
|
385
|
+
- Clean up ALL mocks
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// CORRECT
|
|
389
|
+
describe("UserProfile", () => {
|
|
390
|
+
it("should display user name when provided", () => {
|
|
391
|
+
const { getByText } = render(<UserProfile name="John" />);
|
|
392
|
+
expect(getByText("John")).toBeInTheDocument();
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it("should call onEdit when edit button clicked", () => {
|
|
396
|
+
const onEdit = jest.fn();
|
|
397
|
+
const { getByRole } = render(<UserProfile onEdit={onEdit} />);
|
|
398
|
+
fireEvent.click(getByRole("button", { name: /edit/i }));
|
|
399
|
+
expect(onEdit).toHaveBeenCalledTimes(1);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// INCORRECT
|
|
404
|
+
it("works", () => {
|
|
405
|
+
// NO! Not descriptive
|
|
406
|
+
expect(wrapper).toMatchSnapshot(); // NO! No snapshots
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## Enforcement - AUTOMATIC REJECTION
|
|
411
|
+
|
|
412
|
+
### These Cause Immediate PR Rejection
|
|
413
|
+
|
|
414
|
+
- Class components
|
|
415
|
+
- Anonymous functions in JSX
|
|
416
|
+
- Array index as key
|
|
417
|
+
- Missing TypeScript types
|
|
418
|
+
- Missing PropTypes
|
|
419
|
+
- Props drilling > 2 levels
|
|
420
|
+
- Components > 150 lines
|
|
421
|
+
- Missing tests
|
|
422
|
+
- Coverage < 100% for components
|
|
423
|
+
- Performance budget exceeded
|