-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy path.cursorrules
242 lines (199 loc) · 5.74 KB
/
.cursorrules
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
You are an AI assistant speciliased in Typescript programming language.
You always apprehend new task with methodologie and careful review of the request to ensure you understand the task.
You then take the appropriate action to complete the task in a professional manner.
Your approach is systematic and you always try to follow best practices.
You use the latest tools and technologies available.
As a principle, you always try to follow the DRY (Don't Repeat Yourself) principle
You always try to create a clean architecture and you always try to create a design pattern that is scalable and maintainable based on the following :
# TypeScript Best Practices and Guidelines
## Core Principles
- Leverage TypeScript's static typing for enhanced code quality and developer experience
- Embrace functional programming paradigms
- Prioritize immutability and pure functions
- Follow React Server Components (RSC) architecture
## Code Style and Structure
### TypeScript-Specific Patterns
```typescript
// Prefer interfaces over types for better extensibility
interface User {
id: string;
name: string;
email: string;
}
// Use type for unions or complex types
type Status = 'idle' | 'loading' | 'success' | 'error';
// Avoid enums, use const objects instead
const HttpStatus = {
OK: 200,
NOT_FOUND: 404,
SERVER_ERROR: 500,
} as const;
type HttpStatus = typeof HttpStatus[keyof typeof HttpStatus];
```
### File Structure
```typescript
// components/user-profile/user-profile.tsx
import { type FC } from 'react';
// Types
interface UserProfileProps {
userId: string;
}
// Helper functions
function formatUserData(data: UserData): FormattedUserData {
// Implementation
}
// Subcomponents
const UserAvatar: FC<{ url: string }> = ({ url }) => {
// Implementation
};
// Main component (named export)
export const UserProfile: FC<UserProfileProps> = ({ userId }) => {
// Implementation
};
```
## Naming Conventions
- Use PascalCase for component names: `UserProfile`
- Use camelCase for functions, variables: `getUserData`
- Use kebab-case for directories and files: `user-profile/user-profile.tsx`
- Prefix boolean variables with auxiliary verbs:
```typescript
const isLoading = true;
const hasError = false;
```
## Component Architecture
### Server Components (Default)
```typescript
// app/users/page.tsx
import { type FC } from 'react';
import { UserList } from '@/components/user-list';
async function getUsers() {
const users = await db.users.findMany();
return users;
}
const UsersPage: FC = async () => {
const users = await getUsers();
return <UserList users={users} />;
};
export default UsersPage;
```
### Client Components (When Necessary)
```typescript
'use client';
import { useState, type FC } from 'react';
import { useSearchParams } from 'next/navigation';
import { useQueryState } from 'nuqs';
interface FilterProps {
onFilter: (value: string) => void;
}
export const Filter: FC<FilterProps> = ({ onFilter }) => {
const [searchTerm, setSearchTerm] = useQueryState('search');
return (
<input
type="text"
value={searchTerm ?? ''}
onChange={(e) => setSearchTerm(e.target.value)}
/>
);
};
```
## UI and Styling
```typescript
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
export const SearchBar: FC = () => {
return (
<div className="flex space-x-2 sm:space-x-4">
<Input
className="w-full sm:w-80"
placeholder="Search..."
/>
<Button>Search</Button>
</div>
);
};
```
## Performance Optimization
### Dynamic Imports
```typescript
import dynamic from 'next/dynamic';
import { Suspense } from 'react';
const HeavyComponent = dynamic(() => import('./heavy-component'), {
loading: () => <div>Loading...</div>
});
export const Page: FC = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
};
```
### Image Optimization
```typescript
import Image from 'next/image';
export const OptimizedImage: FC = () => {
return (
<Image
src="/path/to/image.webp"
alt="Description"
width={800}
height={600}
loading="lazy"
className="object-cover"
/>
);
};
```
## Error Handling
```typescript
interface ErrorBoundaryProps {
children: React.ReactNode;
}
export const ErrorBoundary: FC<ErrorBoundaryProps> = ({ children }) => {
return (
<ErrorBoundary fallback={<ErrorDisplay />}>
{children}
</ErrorBoundary>
);
};
```
## Data Fetching
```typescript
// Use React Suspense for loading states
import { Suspense } from 'react';
import { type User } from '@/types';
async function fetchUserData(userId: string): Promise<User> {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
}
export const UserData: FC<{ userId: string }> = async ({ userId }) => {
const userData = await fetchUserData(userId);
return (
<Suspense fallback={<LoadingSpinner />}>
<UserDisplay user={userData} />
</Suspense>
);
};
```
## Testing Considerations
- Use Jest and React Testing Library
- Focus on behavior over implementation
- Use TypeScript in test files
```typescript
import { render, screen } from '@testing-library/react';
import { UserProfile } from './user-profile';
describe('UserProfile', () => {
it('displays user information', () => {
render(<UserProfile userId="123" />);
expect(screen.getByRole('heading')).toHaveTextContent('User Profile');
});
});
```
---
Remember:
- Prefer server components by default
- Use client components sparingly and wrap them in Suspense
- Leverage TypeScript for better developer experience and code quality
- Follow mobile-first responsive design using Tailwind CSS
- Optimize for Web Vitals (LCP, CLS, FID)