Skip to content

Commit fff52dc

Browse files
committed
docs(nextjs.mdc): condense and reorganize Next.js project guidelines
Streamline the Next.js project guidelines by removing redundant sections and focusing on key practices. This change aims to make the document more concise and easier to follow, ensuring that contributors can quickly understand and apply the guidelines. The reorganization also emphasizes important conventions and best practices, enhancing the overall readability and utility of the document.
1 parent 87f1065 commit fff52dc

File tree

1 file changed

+52
-279
lines changed

1 file changed

+52
-279
lines changed

.cursor/rules/nextjs.mdc

Lines changed: 52 additions & 279 deletions
Original file line numberDiff line numberDiff line change
@@ -1,303 +1,76 @@
11
---
22
alwaysApply: true
33
---
4+
## 2. Project Layout
45

5-
Next-GDrive-Index
6-
Applies to: Node 18+, TypeScript 5, Next.js 15 (App Router), React 19, Tailwind 4, Shadcn/Radix.
6+
```
7+
src/
8+
app/ – Next.js routes (RSC by default)
9+
components/feature-x/ – React UI (kebab-case dirs)
10+
hooks/ – custom hooks
11+
lib/ – helpers, adapters, utilities
12+
types/ – shared TypeScript interfaces
13+
tests/ – co-located *.test.ts(x)
14+
scripts/ – build/CLI helpers
15+
```
716

8-
────────────────────────────────────────
9-
1. Development Philosophy
10-
• Readability, maintainability, testability > premature optimisation
11-
• Functional & declarative code; follow SOLID and Composition-over-Inheritance
12-
• Server Components first; add 'use client' only when you need the browser
13-
• Small, single-purpose functions, components, files, and folders
17+
- One named export per file.
1418

15-
────────────────────────────────────────
16-
2. Project Layout
17-
src/
18-
app/ – Next.js routes (RSC by default)
19-
components/feature-x/ – React UI (kebab-case dirs)
20-
hooks/ – custom hooks
21-
lib/ – helpers, adapters, utilities
22-
types/ – shared TypeScript interfaces
23-
tests/ – co-located *.test.ts(x)
24-
scripts/ – build/CLI helpers
25-
26-
One named export per file.
27-
28-
────────────────────────────────────────
29-
3. Naming Conventions
30-
Directories & files kebab-case
31-
React components / types PascalCase
32-
Variables, functions, hooks camelCase (hooks start with use)
33-
Booleans verbNoun (isLoading, canSubmit)
34-
Env vars & constants UPPER_SNAKE_CASE
35-
36-
────────────────────────────────────────
37-
4. Code Style (ESLint + Prettier)
38-
• TypeScript strict mode; never any (use unknown or generics)
39-
• Prefer interfaces over type when extending; avoid enums → const maps
40-
• Declare with function keyword; arrow funcs only for tiny callbacks
41-
• 2-space indent, single quotes, no semicolons (unless required), ≤100 cols
42-
• Early return; no deep nesting; ≤20 LOC per function
43-
• Iterate with map/filter/reduce; avoid for unless necessary
44-
• Dead code & unused imports forbidden (eslint-plugin-unused-imports)
45-
46-
────────────────────────────────────────
47-
5. React & Next.js
48-
• Data fetching ⇒ RSC (cache()/revalidate)
49-
• Client components isolated to UI state, event listeners, browser-only libs
50-
• Code-split: next/dynamic + <Suspense fallback />
51-
• Images: next/image, WebP/AVIF, explicit width/height, loading='lazy'
52-
• URL state ⇒ nuqs (search params)
53-
• Optimise Web Vitals (LCP, CLS, FID) with proper loading order & layout shifts prevention
54-
55-
────────────────────────────────────────
56-
6. Styling & UI
57-
• Tailwind utility-first; class-variance-authority or tailwind-merge for variants
58-
• Shadcn UI (Radix primitives) for accessible components
59-
• Mobile-first breakpoints; dark mode via next-themes + Tailwind dark: class
60-
61-
────────────────────────────────────────
62-
7. Data Validation
63-
• Zod for runtime schema validation (forms, API payloads)
64-
• Always validate external data at boundaries (fetch responses, env vars)
65-
66-
────────────────────────────────────────
67-
8. Error Handling
68-
• Throw typed errors; catch only to add context or show user feedback
69-
• UI errors captured with React error boundaries; log to Sentry (server & client)
70-
71-
────────────────────────────────────────
72-
9. Testing
73-
Tooling: Vitest or Jest, React Testing Library, Playwright for E2E
74-
Unit (Arrange-Act-Assert): one *.test.tsx per module, mock I/O
75-
Integration: call real fetch handlers when feasible
76-
E2E: Playwright flows against built app
77-
78-
────────────────────────────────────────
79-
10. Quality Gates (CI)
80-
npm run validate = type-check + lint + prettier --check + vitest
81-
All checks must pass before merging.
82-
83-
────────────────────────────────────────
84-
11. Skeleton Examples
85-
components/file-card/file-card.tsx
86-
----------------------------------
87-
'use client'
88-
89-
import { type FC } from 'react'
90-
import Image from 'next/image'
91-
import { cn } from '@/src/lib/cn'
92-
93-
interface FileCardProps {
94-
name: string
95-
thumbnailUrl: string
96-
isSelected?: boolean
97-
}
98-
99-
export function FileCard ({ name, thumbnailUrl, isSelected = false }: FileCardProps) {
100-
return (
101-
<div className={cn(
102-
'flex flex-col gap-2 p-2 rounded-lg cursor-pointer',
103-
isSelected && 'ring-2 ring-primary'
104-
)}>
105-
<Image
106-
src={thumbnailUrl}
107-
alt={`${name} thumbnail`}
108-
width={180}
109-
height={120}
110-
className='rounded-md object-cover'
111-
loading='lazy'
112-
/>
113-
<span className='truncate text-sm'>{name}</span>
114-
</div>
115-
)
116-
}
117-
118-
lib/cn.ts
119-
---------
120-
export function cn (...classes: (string | undefined | false)[]) {
121-
return classes.filter(Boolean).join(' ')
122-
}
123-
124-
────────────────────────────────────────
125-
12. ESLint / Prettier Quick-Start
126-
.eslintrc.json
127-
{
128-
"extends": [
129-
"next/core-web-vitals",
130-
"eslint:recommended",
131-
"plugin:@typescript-eslint/recommended",
132-
"plugin:react-hooks/recommended",
133-
"plugin:jsx-a11y/recommended",
134-
"plugin:prettier/recommended"
135-
],
136-
"plugins": ["unused-imports"],
137-
"rules": {
138-
"curly": ["error", "multi-line"],
139-
"unused-imports/no-unused-imports": "error",
140-
"@typescript-eslint/consistent-type-imports": "error"
141-
}
142-
}
143-
144-
.prettierrc
145-
{
146-
"singleQuote": true,
147-
"semi": false,
148-
"trailingComma": "all",
149-
"printWidth": 100,
150-
"tabWidth": 2
151-
}
152-
153-
────────────────────────────────────────
154-
Keep the guide living, concise, and contributor-friendly.Next-GDrive-Index – Engineering Guide (Backend-less Edition)
155-
Applies to: Node 18+, TypeScript 5, Next.js 15 (App Router), React 19, Tailwind 4, Shadcn/Radix.
156-
157-
────────────────────────────────────────
158-
1. Development Philosophy
159-
• Readability, maintainability, testability > premature optimisation
160-
• Functional & declarative code; follow SOLID and Composition-over-Inheritance
161-
• Server Components first; add 'use client' only when you need the browser
162-
• Small, single-purpose functions, components, files, and folders
19+
---
16320

164-
────────────────────────────────────────
165-
2. Project Layout
166-
src/
167-
app/ – Next.js routes (RSC by default)
168-
components/feature-x/ – React UI (kebab-case dirs)
169-
hooks/ – custom hooks
170-
lib/ – helpers, adapters, utilities
171-
types/ – shared TypeScript interfaces
172-
tests/ – co-located *.test.ts(x)
173-
scripts/ – build/CLI helpers
21+
## 3. Naming Conventions
17422

175-
One named export per file.
23+
- Directories & files: **kebab-case**
24+
- React components / types: **PascalCase**
25+
- Variables, functions, hooks: **camelCase** (hooks start with `use`)
26+
- Booleans: **verbNoun** (`isLoading`, `canSubmit`)
27+
- Env vars & constants: **UPPER_SNAKE_CASE**
17628

177-
────────────────────────────────────────
178-
3. Naming Conventions
179-
Directories & files kebab-case
180-
React components / types PascalCase
181-
Variables, functions, hooks camelCase (hooks start with use)
182-
Booleans verbNoun (isLoading, canSubmit)
183-
Env vars & constants UPPER_SNAKE_CASE
29+
---
18430

185-
────────────────────────────────────────
186-
4. Code Style (ESLint + Prettier)
187-
• TypeScript strict mode; never any (use unknown or generics)
188-
• Prefer interfaces over type when extending; avoid enums → const maps
189-
• Declare with function keyword; arrow funcs only for tiny callbacks
190-
• 2-space indent, single quotes, no semicolons (unless required), ≤100 cols
191-
• Early return; no deep nesting; ≤20 LOC per function
192-
• Iterate with map/filter/reduce; avoid for unless necessary
193-
• Dead code & unused imports forbidden (eslint-plugin-unused-imports)
31+
## 4. Code Style (ESLint + Prettier)
19432

195-
────────────────────────────────────────
196-
5. React & Next.js
197-
• Data fetching ⇒ RSC (cache()/revalidate)
198-
• Client components isolated to UI state, event listeners, browser-only libs
199-
• Code-split: next/dynamic + <Suspense fallback />
200-
• Images: next/image, WebP/AVIF, explicit width/height, loading='lazy'
201-
• URL state ⇒ nuqs (search params)
202-
• Optimise Web Vitals (LCP, CLS, FID) with proper loading order & layout shifts prevention
33+
- TypeScript strict mode; never `any` (use `unknown` or generics)
34+
- Prefer `interface` over `type` for extending; avoid enums—I> use const maps
35+
- Declare with `function` keyword; arrows only for tiny callbacks
36+
- 2-space indent, single quotes, no semicolons (unless required), ≤100 cols
37+
- Early return; avoid deep nesting; ≤20 LOC per function
38+
- Use `map`/`filter`/`reduce` for iteration; avoid `for` unless necessary
39+
- Dead code & unused imports forbidden (`eslint-plugin-unused-imports`)
20340

204-
────────────────────────────────────────
205-
6. Styling & UI
206-
• Tailwind utility-first; class-variance-authority or tailwind-merge for variants
207-
• Shadcn UI (Radix primitives) for accessible components
208-
• Mobile-first breakpoints; dark mode via next-themes + Tailwind dark: class
41+
---
20942

210-
────────────────────────────────────────
211-
7. Data Validation
212-
• Zod for runtime schema validation (forms, API payloads)
213-
• Always validate external data at boundaries (fetch responses, env vars)
43+
## 5. React & Next.js
21444

215-
────────────────────────────────────────
216-
8. Error Handling
217-
• Throw typed errors; catch only to add context or show user feedback
218-
• UI errors captured with React error boundaries; log to Sentry (server & client)
45+
- Fetch data in RSC (`cache()`, `revalidate`)
46+
- Client components: only for UI state, events, browser-only libs
47+
- Code-split: `next/dynamic` + `<Suspense fallback />`
48+
- Images: `next/image`, WebP/AVIF, explicit width/height, `loading='lazy'`
49+
- URL state: **nuqs** (search params)
50+
- Optimise Web Vitals (LCP, CLS, FID): control loading order, prevent layout shifts
21951

220-
────────────────────────────────────────
221-
9. Testing
222-
Tooling: Vitest or Jest, React Testing Library, Playwright for E2E
223-
Unit (Arrange-Act-Assert): one *.test.tsx per module, mock I/O
224-
Integration: call real fetch handlers when feasible
225-
E2E: Playwright flows against built app
52+
---
22653

227-
────────────────────────────────────────
228-
10. Quality Gates (CI)
229-
npm run validate = type-check + lint + prettier --check + vitest
230-
All checks must pass before merging.
54+
## 6. Styling & UI
23155

232-
────────────────────────────────────────
233-
11. Skeleton Examples
234-
components/file-card/file-card.tsx
235-
----------------------------------
236-
'use client'
56+
- Tailwind utility-first; use **class-variance-authority** or **tailwind-merge** for variants
57+
- Use **Shadcn UI** (Radix primitives) for accessible components
58+
- Mobile-first breakpoints; dark mode via **next-themes** + Tailwind `dark:` class
23759

238-
import { type FC } from 'react'
239-
import Image from 'next/image'
240-
import { cn } from '@/src/lib/cn'
60+
---
24161

242-
interface FileCardProps {
243-
name: string
244-
thumbnailUrl: string
245-
isSelected?: boolean
246-
}
62+
## 7. Data Validation
24763

248-
export function FileCard ({ name, thumbnailUrl, isSelected = false }: FileCardProps) {
249-
return (
250-
<div className={cn(
251-
'flex flex-col gap-2 p-2 rounded-lg cursor-pointer',
252-
isSelected && 'ring-2 ring-primary'
253-
)}>
254-
<Image
255-
src={thumbnailUrl}
256-
alt={`${name} thumbnail`}
257-
width={180}
258-
height={120}
259-
className='rounded-md object-cover'
260-
loading='lazy'
261-
/>
262-
<span className='truncate text-sm'>{name}</span>
263-
</div>
264-
)
265-
}
64+
- Use **Zod** for runtime schema validation (forms, API payloads)
65+
- Always validate external data at boundaries (fetch responses, env vars)
26666

267-
lib/cn.ts
268-
---------
269-
export function cn (...classes: (string | undefined | false)[]) {
270-
return classes.filter(Boolean).join(' ')
271-
}
67+
---
27268

273-
────────────────────────────────────────
274-
12. ESLint / Prettier Quick-Start
275-
.eslintrc.json
276-
{
277-
"extends": [
278-
"next/core-web-vitals",
279-
"eslint:recommended",
280-
"plugin:@typescript-eslint/recommended",
281-
"plugin:react-hooks/recommended",
282-
"plugin:jsx-a11y/recommended",
283-
"plugin:prettier/recommended"
284-
],
285-
"plugins": ["unused-imports"],
286-
"rules": {
287-
"curly": ["error", "multi-line"],
288-
"unused-imports/no-unused-imports": "error",
289-
"@typescript-eslint/consistent-type-imports": "error"
290-
}
291-
}
69+
## 8. Error Handling
29270

293-
.prettierrc
294-
{
295-
"singleQuote": true,
296-
"semi": false,
297-
"trailingComma": "all",
298-
"printWidth": 100,
299-
"tabWidth": 2
300-
}
71+
- Throw **typed errors**; catch only to add context or show user feedback
72+
- UI errors: React error boundaries; log to **Sentry** (server & client)
73+
-
74+
---
30175

302-
────────────────────────────────────────
303-
Keep the guide living, concise, and contributor-friendly.
76+
**Keep this guide living, concise, and contributor-friendly.**

0 commit comments

Comments
 (0)