1+ ---
2+ alwaysApply: true
3+ ---
4+
5+ Next-GDrive-Index
6+ Applies to: Node 18+, TypeScript 5, Next.js 15 (App Router), React 19, Tailwind 4, Shadcn/Radix.
7+
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
14+
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
163+
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
174+
175+ One named export per file.
176+
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
184+
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)
194+
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
203+
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
209+
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)
214+
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)
219+
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
226+
227+ ────────────────────────────────────────
228+ 10. Quality Gates (CI)
229+ npm run validate = type-check + lint + prettier --check + vitest
230+ All checks must pass before merging.
231+
232+ ────────────────────────────────────────
233+ 11. Skeleton Examples
234+ components/file-card/file-card.tsx
235+ ----------------------------------
236+ 'use client'
237+
238+ import { type FC } from 'react'
239+ import Image from 'next/image'
240+ import { cn } from '@/src/lib/cn'
241+
242+ interface FileCardProps {
243+ name: string
244+ thumbnailUrl: string
245+ isSelected?: boolean
246+ }
247+
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+ }
266+
267+ lib/cn.ts
268+ ---------
269+ export function cn (...classes: (string | undefined | false)[]) {
270+ return classes.filter(Boolean).join(' ')
271+ }
272+
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+ }
292+
293+ .prettierrc
294+ {
295+ "singleQuote": true,
296+ "semi": false,
297+ "trailingComma": "all",
298+ "printWidth": 100,
299+ "tabWidth": 2
300+ }
301+
302+ ────────────────────────────────────────
303+ Keep the guide living, concise, and contributor-friendly.
0 commit comments