11---
22alwaysApply: 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