Skip to content

Commit 45ff28a

Browse files
committed
information for robots
1 parent 2d7b9fb commit 45ff28a

15 files changed

Lines changed: 5126 additions & 0 deletions

.cursorrules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
design-docs/assistants/cursor-instructions.md
Lines changed: 395 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,395 @@
1+
# Cursor IDE Configuration for Draft Builder
2+
3+
## Project-Specific Instructions
4+
5+
This document provides Cursor IDE with project-specific coding standards, patterns, and conventions for the Draft Builder fantasy sports application. These instructions should be used in conjunction with Cursor's AI assistance to maintain consistency and follow established patterns.
6+
7+
## Documentation and Design Resources
8+
9+
**For AI Programming Assistants**: Before beginning work on this project, consult the following directories for comprehensive project context:
10+
11+
### Design Documentation Structure
12+
```
13+
design-docs/
14+
├── assistants/ # AI-specific guidance and instructions
15+
│ ├── cursor-instructions.md # This file - coding standards and patterns
16+
│ └── ... # Additional AI assistant resources
17+
├── architecture/ # System design and technical architecture
18+
├── features/ # Feature specifications and requirements
19+
├── api/ # API design and integration patterns
20+
└── ... # Additional high-level design documents
21+
```
22+
23+
### Key Information Sources
24+
25+
**High-Level Project Information**:
26+
- `design-docs/` - Contains architectural decisions, feature specifications, and design rationale
27+
- Review architecture documents before making structural changes
28+
- Check feature documentation to understand user requirements and acceptance criteria
29+
30+
**AI Assistant Resources**:
31+
- `design-docs/assistants/` - Specialized guidance for AI programming tools
32+
- Contains prompt templates, coding patterns, and assistant-specific instructions
33+
- Reference these documents when unclear about project conventions or patterns
34+
35+
**Before Starting Development**:
36+
1. **Read** relevant design documents in `design-docs/` for project context
37+
2. **Check** `design-docs/assistants/` for AI-specific guidance and examples
38+
3. **Follow** the established patterns documented in this file
39+
4. **Consult** existing code examples that follow these conventions
40+
41+
This approach ensures consistency with project vision and maintains alignment with established architectural decisions.
42+
43+
## Technology Stack Context
44+
45+
**Framework**: Next.js 15.3.3 with App Router
46+
**Language**: TypeScript with strict mode enabled
47+
**UI**: React 19.1.0 with Tailwind CSS 3.4.1
48+
**Testing**: Jest 29.7.0 with React Testing Library
49+
**State Management**: React hooks and local storage
50+
**API Integration**: Custom platform adapters for ESPN and Sleeper
51+
**Caching**: Redis with ioredis client
52+
**Deployment**: Vercel
53+
54+
## File Organization Standards
55+
56+
### Directory Structure
57+
```
58+
src/
59+
├── app/ # Next.js App Router pages and API routes
60+
│ ├── api/ # Server-side API endpoints
61+
│ ├── league/[leagueID]/ # Dynamic league-specific routes
62+
│ └── storage/ # Client-side data persistence
63+
├── platforms/ # External platform integrations
64+
│ ├── espn/ # ESPN API wrapper
65+
│ ├── sleeper/ # Sleeper API wrapper
66+
│ └── common.ts # Shared platform types
67+
├── rankings/ # Player ranking systems
68+
├── redis/ # Redis caching utilities
69+
└── ui/ # Reusable UI components
70+
```
71+
72+
### Naming Conventions
73+
74+
**Files**:
75+
- Use PascalCase for React components: `MockDraft.tsx`
76+
- Use camelCase for utilities and APIs: `sleeperApi.ts`
77+
- Use kebab-case for page routes: `[league-id]/page.tsx`
78+
- Test files: `ComponentName.test.tsx`
79+
80+
**Variables and Functions**:
81+
- camelCase for variables and functions: `calculateBudget()`
82+
- PascalCase for React components: `<LoadingScreen />`
83+
- UPPER_SNAKE_CASE for constants: `IN_PROGRESS_SELECTIONS_KEY`
84+
85+
**Types and Interfaces**:
86+
- PascalCase with descriptive names: `LeagueInfo`, `MockPlayer`
87+
- Suffix with 'State' for state objects: `SearchSettingsState`
88+
- Use union types for platform distinctions: `Platform = 'sleeper' | 'espn'`
89+
90+
## Code Style Guidelines
91+
92+
### TypeScript Patterns
93+
94+
**Type Safety**:
95+
```typescript
96+
// Always use strict typing
97+
interface Player {
98+
id: string; // Use string IDs for consistency
99+
name: string;
100+
defaultPosition: string;
101+
positions: string[];
102+
suggestedCost?: number; // Optional properties with ?
103+
}
104+
105+
// Use type guards for runtime checking
106+
function isValidPlayer(obj: any): obj is Player {
107+
return obj &&
108+
typeof obj.id === 'string' &&
109+
typeof obj.name === 'string';
110+
}
111+
```
112+
113+
**Error Handling**:
114+
```typescript
115+
// Platform APIs return data or HTTP error codes
116+
async function fetchData(): Promise<PlayerData | number> {
117+
try {
118+
const response = await api.call();
119+
return response.data;
120+
} catch (error) {
121+
logRequestError("Failed to fetch player data", error);
122+
return 500; // Return HTTP status code
123+
}
124+
}
125+
```
126+
127+
**Async Patterns**:
128+
```typescript
129+
// Use proper loading states with useCallback
130+
const handleSubmit = useCallback(async (data: FormData) => {
131+
if (isSubmitting) return;
132+
133+
try {
134+
setIsSubmitting(true);
135+
await submitData(data);
136+
} finally {
137+
setIsSubmitting(false);
138+
}
139+
}, [isSubmitting]);
140+
```
141+
142+
### React Component Patterns
143+
144+
**Component Structure**:
145+
```typescript
146+
// Props interface first
147+
interface ComponentProps {
148+
required: string;
149+
optional?: boolean;
150+
children?: React.ReactNode;
151+
}
152+
153+
// Component with proper typing
154+
export default function Component({ required, optional = false }: ComponentProps) {
155+
// Hooks at the top
156+
const [state, setState] = useState<StateType>(initialValue);
157+
const memoizedValue = useMemo(() => expensiveCalculation(), [deps]);
158+
159+
// Event handlers with useCallback
160+
const handleEvent = useCallback((e: React.MouseEvent) => {
161+
e.preventDefault();
162+
// Handle event
163+
}, [dependencies]);
164+
165+
// Render
166+
return (
167+
<div className="tailwind-classes">
168+
{/* JSX content */}
169+
</div>
170+
);
171+
}
172+
```
173+
174+
**Loading States**:
175+
```typescript
176+
// Use LoadingTask pattern for complex loading
177+
const tasks = useMemo(() => new Set([
178+
new LoadingTask(dataPromise, "Loading player data..."),
179+
new LoadingTask(() => isReady, "Preparing interface...")
180+
]), [dataPromise, isReady]);
181+
182+
return (
183+
<LoadingScreen tasks={tasks}>
184+
<MainContent />
185+
</LoadingScreen>
186+
);
187+
```
188+
189+
### API Integration Patterns
190+
191+
**Platform API Structure**:
192+
```typescript
193+
// Extend PlatformApi base class
194+
export class SleeperApi extends PlatformApi {
195+
async fetchLeague(season?: SeasonId): Promise<LeagueInfo | number> {
196+
try {
197+
const response = await fetchLeagueInfo(this.league.id);
198+
return importSleeperLeagueInfo(response);
199+
} catch (error) {
200+
return this.handleError(error);
201+
}
202+
}
203+
}
204+
205+
// Use factory pattern for API selection
206+
export function apiFor(league: PlatformLeague): PlatformApi {
207+
switch (league.platform) {
208+
case 'sleeper': return new SleeperApi(league);
209+
case 'espn': return new EspnApi(league);
210+
default: throw new Error(`Unsupported platform: ${league.platform}`);
211+
}
212+
}
213+
```
214+
215+
### Testing Standards
216+
217+
**Test File Structure**:
218+
```typescript
219+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
220+
import userEvent from '@testing-library/user-event';
221+
import ComponentName from './ComponentName';
222+
223+
describe('ComponentName', () => {
224+
// Setup/teardown if needed
225+
beforeEach(() => {
226+
// Reset mocks
227+
});
228+
229+
it('should render with required props', () => {
230+
render(<ComponentName required="value" />);
231+
expect(screen.getByText('expected')).toBeInTheDocument();
232+
});
233+
234+
it('should handle user interactions', async () => {
235+
const user = userEvent.setup();
236+
const mockCallback = jest.fn();
237+
238+
render(<ComponentName onAction={mockCallback} />);
239+
240+
await user.click(screen.getByRole('button'));
241+
242+
expect(mockCallback).toHaveBeenCalledWith(expectedArgs);
243+
});
244+
});
245+
```
246+
247+
**Mock Patterns**:
248+
```typescript
249+
// Mock external dependencies
250+
jest.mock('./api', () => ({
251+
fetchData: jest.fn(),
252+
}));
253+
254+
// Type-safe mocks
255+
const mockFetchData = fetchData as jest.MockedFunction<typeof fetchData>;
256+
257+
beforeEach(() => {
258+
mockFetchData.mockReset();
259+
});
260+
```
261+
262+
## Common Anti-Patterns to Avoid
263+
264+
**Don't**:
265+
- Use `any` type except in very specific cases
266+
- Mutate props or state directly
267+
- Create components inside render functions
268+
- Use string refs (use useRef hook)
269+
- Ignore error boundaries
270+
- Use index as key in dynamic lists
271+
- Mix platform-specific logic in shared components
272+
273+
**Do**:
274+
- Use strict TypeScript typing
275+
- Implement proper error boundaries
276+
- Use React.memo for expensive pure components
277+
- Implement proper loading and error states
278+
- Use useCallback for event handlers in optimized components
279+
- Follow the established platform abstraction patterns
280+
281+
## Performance Guidelines
282+
283+
**Optimization Patterns**:
284+
```typescript
285+
// Memoize expensive calculations
286+
const expensiveValue = useMemo(() => {
287+
return complexCalculation(data);
288+
}, [data]);
289+
290+
// Memoize components that receive complex props
291+
const MemoizedComponent = React.memo(Component, (prevProps, nextProps) => {
292+
return prevProps.complexProp.id === nextProps.complexProp.id;
293+
});
294+
295+
// Use dynamic imports for code splitting
296+
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
297+
loading: () => <LoadingSpinner />,
298+
});
299+
```
300+
301+
## Error Handling Standards
302+
303+
**Client-Side Errors**:
304+
```typescript
305+
// Use error boundaries for component errors
306+
<ErrorBoundary fallback={<ErrorScreen />}>
307+
<RiskyComponent />
308+
</ErrorBoundary>
309+
310+
// Handle async errors gracefully
311+
const [error, setError] = useState<string | null>(null);
312+
313+
try {
314+
await riskyOperation();
315+
} catch (err) {
316+
setError(err instanceof Error ? err.message : 'Unknown error');
317+
}
318+
```
319+
320+
**API Error Handling**:
321+
```typescript
322+
// Consistent error logging
323+
export function logRequestError(message: string, error: any): void {
324+
console.error("Error with", message);
325+
console.error("Error type:", typeof error);
326+
console.error("Error details:", JSON.stringify(error).substring(0, 500));
327+
}
328+
```
329+
330+
## State Management Patterns
331+
332+
**Local Storage Integration**:
333+
```typescript
334+
// Use type-safe local storage hooks
335+
const [storedData, setStoredData] = useLocalStorage<DataType>('key', defaultValue);
336+
337+
// Handle storage migrations
338+
const migratedData = migrate(rawStorageData);
339+
```
340+
341+
**Form State Management**:
342+
```typescript
343+
// Use controlled components with proper validation
344+
const [formData, setFormData] = useState<FormType>(initialForm);
345+
346+
const handleInputChange = (field: keyof FormType) => (value: any) => {
347+
setFormData(prev => ({ ...prev, [field]: value }));
348+
};
349+
```
350+
351+
## Accessibility Requirements
352+
353+
**Always Include**:
354+
- Proper ARIA labels: `aria-label`, `aria-describedby`
355+
- Semantic HTML roles: `role="button"`, `role="tooltip"`
356+
- Keyboard navigation support
357+
- Screen reader compatible text
358+
- Color contrast compliance
359+
- Focus management for dynamic content
360+
361+
## Code Review Checklist
362+
363+
Before submitting code, ensure:
364+
- [ ] All TypeScript errors resolved
365+
- [ ] Tests pass and have adequate coverage
366+
- [ ] Error handling implemented
367+
- [ ] Loading states provided
368+
- [ ] Accessibility attributes included
369+
- [ ] Performance considerations addressed
370+
- [ ] Follows established patterns
371+
- [ ] No console.log statements in production code
372+
- [ ] Proper error logging used
373+
374+
## Import Organization
375+
376+
**Order**:
377+
1. React and Next.js imports
378+
2. Third-party libraries
379+
3. Internal utilities and types
380+
4. Relative imports
381+
5. Type-only imports at the end
382+
383+
```typescript
384+
import React, { useState, useCallback } from 'react';
385+
import { useRouter } from 'next/navigation';
386+
import axios from 'axios';
387+
388+
import { apiFor } from '@/platforms/ApiClient';
389+
import { LoadingScreen } from '@/ui/LoadingScreen';
390+
import { logRequestError } from '@/utils/errors';
391+
392+
import './Component.module.css';
393+
394+
import type { PlatformLeague } from '@/platforms/common';
395+
```

0 commit comments

Comments
 (0)