Skip to content

Commit f5b8c91

Browse files
committed
convert cursor rules to skills
1 parent 0ff5637 commit f5b8c91

7 files changed

Lines changed: 548 additions & 0 deletions

File tree

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
---
2+
name: e2e-testing
3+
description: Playwright E2E testing best practices for this project. Use when writing, modifying, or reviewing E2E tests.
4+
---
5+
6+
# E2E Testing Best Practices (Playwright)
7+
8+
## Setup
9+
10+
- Use Playwright helpers from `tests/e2e/helpers.ts`
11+
- Use `data-testid` attributes for stable selectors
12+
- Write descriptive test names that explain user behavior
13+
- Ensure tests are isolated and can run independently
14+
15+
## Never Use Hard-Coded Timeouts
16+
17+
```typescript
18+
// Bad
19+
await element.click();
20+
await page.waitForTimeout(200);
21+
22+
// Good
23+
await element.click();
24+
await expect(otherElement).toBeVisible();
25+
```
26+
27+
## Use Playwright's Auto-Waiting
28+
29+
```typescript
30+
// Bad
31+
if (await element.isVisible()) {
32+
await element.click();
33+
}
34+
35+
// Good
36+
await expect(element).toBeVisible();
37+
await element.click();
38+
```
39+
40+
## Never Use Non-Null Assertions
41+
42+
```typescript
43+
// Bad
44+
const box = await element.boundingBox();
45+
const x = box!.x;
46+
47+
// Good
48+
const box = await element.boundingBox();
49+
if (!box) {
50+
throw new Error("Unable to locate element bounding box");
51+
}
52+
const x = box.x;
53+
```
54+
55+
## Don't Await Locators (They're Lazy)
56+
57+
```typescript
58+
// Bad
59+
const button = await page.getByTestId("submit");
60+
61+
// Good
62+
const button = page.getByTestId("submit");
63+
await expect(button).toBeVisible();
64+
```
65+
66+
## Use Consistent Assertion Patterns
67+
68+
```typescript
69+
// Bad
70+
expect(await element).toHaveText("text");
71+
expect(await element.isVisible()).toBe(true);
72+
73+
// Good
74+
await expect(element).toHaveText("text");
75+
await expect(element).toBeVisible();
76+
```
77+
78+
## Prefer Semantic Selectors
79+
80+
Priority order:
81+
1. `getByRole()` - Best for accessibility
82+
2. `getByTestId()` - Best for test stability (preferred for this app)
83+
3. `getByText()` - Good for static content
84+
4. `locator()` with data attributes - When above don't work
85+
5. CSS selectors - Last resort
86+
87+
## Test Isolation
88+
89+
- Each test should set up its own state
90+
- Don't depend on test execution order (unless using serial mode intentionally)
91+
- Clean up after tests in `afterEach` or `afterAll`
92+
93+
## Helper Functions
94+
95+
- Leverage existing helpers from `tests/e2e/helpers.ts`
96+
- Create new helpers for repeated workflows
97+
- Keep helpers focused and reusable
98+
99+
## Add Meaningful Error Context
100+
101+
```typescript
102+
// Okay
103+
await expect(element).toBeVisible();
104+
105+
// Better
106+
await expect(element, "Component should appear after loading").toBeVisible();
107+
```
108+
109+
## Test User Behavior, Not Implementation
110+
111+
```typescript
112+
// Bad - implementation detail
113+
await expect(button).toHaveClass("bg-blue-500");
114+
115+
// Good - user-visible behavior
116+
await expect(button).toBeVisible();
117+
await expect(button).toBeEnabled();
118+
await expect(button).toHaveText("Submit");
119+
```
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
name: project-conventions
3+
description: Project conventions for Pipeline Studio App including file structure, imports, code quality, and general rules. Use when writing new code, creating files, or organizing imports.
4+
---
5+
6+
# Project Conventions
7+
8+
## Project Overview
9+
10+
React + TypeScript application for building and running ML pipelines using drag and drop. Uses Vite, TailwindCSS v4, ShadCN, Radix UI, React Flow, and Monaco Editor.
11+
12+
## File Structure & Imports
13+
14+
- Use absolute imports with `@/` prefix for src directory
15+
- Follow existing folder structure:
16+
- `src/components/` for all React components
17+
- `src/hooks/` for custom hooks
18+
- `src/types/` for TypeScript definitions
19+
- `src/utils/` for utility functions
20+
- `src/services/` for API and business logic
21+
- **Import order**: external packages -> internal modules -> relative imports
22+
- Use simple-import-sort rules (already configured in ESLint)
23+
- Do not use barrel exports
24+
25+
## Code Quality
26+
27+
- Follow ESLint rules (configured in eslint.config.js)
28+
- Use Prettier for formatting
29+
- Write tests using Vitest for unit tests, Playwright for E2E
30+
- Use descriptive variable and function names
31+
- Add JSDoc comments for complex functions
32+
- Prefer early returns to reduce nesting
33+
34+
## Comments & Documentation
35+
36+
- Use JSDoc for public APIs
37+
- Add comments for complex business logic
38+
- **Explain "why" not "what" in comments**
39+
- Keep comments up to date with code changes
40+
- Avoid writing redundant comments for functions and variables that are self-explanatory
41+
42+
## Error Handling
43+
44+
- Use proper error boundaries
45+
- Handle async errors with try/catch
46+
- Use toast notifications for user-facing errors
47+
- Log errors appropriately
48+
49+
## React Flow Specific
50+
51+
- Use `@xyflow/react` for flow diagrams
52+
- Follow existing node types and edge patterns
53+
- Keep flow state management consistent with existing patterns
54+
- Use proper node and edge typing
55+
56+
## Specific Project Patterns
57+
58+
- Use Monaco Editor for code editing features
59+
- Use localforage for client-side storage
60+
- Follow existing authentication patterns
61+
- Use proper task node and pipeline handling patterns
62+
- Follow the existing component library structure
63+
- **Do not modify componentSpec structure** without express permission
64+
65+
## Don't Do
66+
67+
- Don't use CSS-in-JS or styled-components
68+
- Don't use inline styling (`style={styles}`) except where strictly necessary
69+
- Don't use relative imports for `@/components/ui`
70+
- Don't create new global state without good reason
71+
- Don't bypass existing abstractions without discussion
72+
73+
## Planning & Documentation
74+
75+
When asked to create planning documents, architecture decisions, or investigation notes:
76+
- **Always save to `.local/`** - This directory is gitignored for local-only files
77+
- Use descriptive filenames: `.local/feature-name-planning.md`, `.local/bug-investigation.md`
78+
79+
## Optional "While We're Here" Cleanup
80+
81+
After completing a code generation task, scan the surrounding area for small, low-risk improvements. **Only offer** if ALL conditions are met:
82+
83+
1. **Small scope**: Affects < 30 lines of code
84+
2. **Low risk**: Purely cosmetic or minor refactoring (not logic changes)
85+
3. **Same file**: In a file you already modified
86+
4. **Clear benefit**: Improves readability, removes dead code, or fixes obvious issues
87+
88+
Don't be naggy — only offer once per task, and only if genuinely worthwhile.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
name: react-patterns
3+
description: React and React Compiler patterns for this project. Use when writing React components, hooks, providers, or working with React Compiler compatibility.
4+
---
5+
6+
# React Patterns
7+
8+
## Core Rules
9+
10+
- Use functional components with hooks exclusively (no class components)
11+
- Use proper dependency arrays in useEffect
12+
- Follow the existing component structure
13+
- Use React 19 features and patterns
14+
- **Import modules from React**: `import module from react`. Do not use inline `React.[module]`
15+
16+
## Component Structure
17+
18+
```typescript
19+
// ComponentName/index.ts
20+
export { ComponentName } from './ComponentName';
21+
22+
// ComponentName/ComponentName.tsx
23+
interface ComponentNameProps {
24+
// props
25+
}
26+
27+
export const ComponentName = ({ }: ComponentNameProps) => {
28+
// component logic
29+
return (
30+
// JSX
31+
);
32+
};
33+
```
34+
35+
## Custom Hooks
36+
37+
- Prefix with `use`
38+
- Return objects for multiple values, not arrays
39+
- Use proper TypeScript return types
40+
- Follow existing patterns in `src/hooks/`
41+
42+
## Provider Pattern
43+
44+
```typescript
45+
const Context = createContext<ContextType | null>(null);
46+
47+
export const Provider = ({ children }: { children: ReactNode }) => {
48+
// provider logic
49+
return <Context.Provider value={value}>{children}</Context.Provider>;
50+
};
51+
52+
export const useContext = () => {
53+
const context = useContext(Context);
54+
if (!context) throw new Error('useContext must be used within Provider');
55+
return context;
56+
};
57+
```
58+
59+
## State Management
60+
61+
- Use Tanstack Query for server state
62+
- Use Tanstack Router for routing
63+
- Use React hooks for local component state
64+
- Use Context providers for app-wide state (see existing providers in `src/providers/`)
65+
- **Use `useRequiredContext`** to simplify context usage and avoid null checks
66+
67+
## React Compiler
68+
69+
This project uses the React Compiler for automatic memoization. Files/directories are incrementally adopted in `react-compiler.config.js`.
70+
71+
### Writing React Compiler Compatible Code
72+
73+
**For new files**, ensure they follow React Compiler rules from the start:
74+
75+
1. **Don't mutate values during render**
76+
```typescript
77+
// Bad - mutating during render
78+
const items = props.items;
79+
items.push(newItem);
80+
81+
// Good - create new reference
82+
const items = [...props.items, newItem];
83+
```
84+
85+
2. **Don't read/write refs during render**
86+
```typescript
87+
// Bad - reading ref during render
88+
const value = myRef.current;
89+
return <div>{value}</div>;
90+
91+
// Good - read refs in effects or callbacks
92+
useEffect(() => {
93+
const value = myRef.current;
94+
}, []);
95+
```
96+
97+
3. **Follow Rules of Hooks strictly** - no conditional hooks, no hooks in loops, proper dependency arrays
98+
99+
4. **Avoid patterns the compiler can't optimize**
100+
- Don't spread props with `{...props}` unnecessarily
101+
- Avoid dynamic property access on objects when possible
102+
- Keep component logic predictable
103+
104+
### Adding Files to React Compiler
105+
106+
When a file is added to `react-compiler.config.js`:
107+
- Remove unnecessary `useCallback` and `useMemo` (compiler handles this)
108+
- Verify no compiler violations with `npm run validate`
109+
- Test the component still works correctly
110+
111+
### React Compiler Config Structure
112+
113+
Files are organized by cleanup effort in `react-compiler.config.js`:
114+
- Top section: Already enabled directories/files
115+
- Middle: Ready to enable (0 useCallback/useMemo)
116+
- Bottom (commented): Need cleanup before enabling
117+
118+
## Performance
119+
120+
- **Do not use `useMemo`, `useCallback`, or `memo` manually** — the React Compiler handles memoization automatically
121+
- If you encounter existing `useMemo`/`useCallback`/`memo` in a file, remove them when the file is enabled in `react-compiler.config.js`
122+
- Lazy load heavy components when possible
123+
- Follow existing patterns for optimization

0 commit comments

Comments
 (0)