claudify-agent 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.claude/QUICK-REFERENCE.md +213 -213
  2. package/.claude/cost-dashboard.md +162 -162
  3. package/.claude/docs/COST-OPTIMIZATION.md +402 -403
  4. package/.claude/docs/MCP-INTEGRATION-GUIDE.md +348 -348
  5. package/.claude/docs/PLAN-MODE-OPTIMIZATION.md +835 -836
  6. package/.claude/hooks/auto-learning-review.ts +200 -195
  7. package/.claude/hooks/auto-lint-fix.ts +60 -104
  8. package/.claude/hooks/auto-security-review.ts +314 -354
  9. package/.claude/hooks/auto-validate.ts +249 -348
  10. package/.claude/hooks/lib/claude-hook.ts +168 -0
  11. package/.claude/hooks/plan-quality-tracker.ts +598 -719
  12. package/.claude/rules/anti-patterns.md +22 -22
  13. package/.claude/rules/context-tier-1.md +41 -41
  14. package/.claude/rules/context-tier-2.md +285 -285
  15. package/.claude/rules/general.md +25 -25
  16. package/.claude/rules/mcp-auto-use.md +46 -46
  17. package/.claude/rules/parallel-exploration-auto.md +30 -31
  18. package/.claude/rules/plan-mode-execution.md +289 -289
  19. package/.claude/rules/plan-mode-research.md +34 -34
  20. package/.claude/rules/plan-mode-structure.md +166 -166
  21. package/.claude/rules/plan-mode-validation.md +129 -130
  22. package/.claude/rules/security-critical.md +19 -19
  23. package/.claude/rules/tool-auto-selection.md +45 -45
  24. package/.claude/rules/tool-strategy.md +22 -22
  25. package/.claude/scripts/security-scan.js +1 -1
  26. package/.claude/security-dashboard.md +142 -142
  27. package/.claude/settings.json +50 -0
  28. package/.claude/skills/debug-optimizer/SKILL.md +420 -399
  29. package/.claude/skills/learning-loop/SKILL.md +313 -308
  30. package/.claude/skills/mcp-mastery/SKILL.md +218 -214
  31. package/.claude/skills/nextjs-guide/SKILL.md +687 -687
  32. package/.claude/skills/parallel-exploration/SKILL.md +197 -193
  33. package/.claude/skills/plan-mode-mastery/SKILL.md +268 -263
  34. package/.claude/skills/python-guide/SKILL.md +822 -822
  35. package/.claude/skills/react-guide/SKILL.md +762 -762
  36. package/.claude/skills/{security.md → security-guide/SKILL.md} +10 -0
  37. package/.claude/skills/solidity-guide/SKILL.md +5 -0
  38. package/.claude/skills/tool-selection/SKILL.md +433 -428
  39. package/.claude/skills/vite-guide/SKILL.md +445 -445
  40. package/CLAUDE.md +1 -0
  41. package/README.md +74 -35
  42. package/README.vi.md +106 -0
  43. package/bin/cli.js +13 -4
  44. package/package.json +9 -1
  45. package/.claude/skills/debug-optimizer.md +0 -12
  46. package/.claude/skills/nextjs.md +0 -13
  47. package/.claude/skills/react.md +0 -12
@@ -1,687 +1,687 @@
1
- ---
2
- name: nextjs-guide
3
- description: Apply Next.js 14-15 best practices including App Router, Server Components, data fetching, and project structure. Use when building, reviewing, or optimizing Next.js applications.
4
- ---
5
-
6
- # Next.js Best Practices
7
-
8
- ## Quick Start
9
-
10
- When working with Next.js 14-15:
11
-
12
- 1. **Server Components by default**: Only use `"use client"` when necessary
13
- 2. **App Router structure**: Use route groups, layouts, and proper file organization
14
- 3. **Data fetching**: Fetch directly in Server Components, use proper caching
15
- 4. **Component composition**: Keep client boundary small, compose Server Components inside Client Components
16
- 5. **Project structure**: Use `src/` directory with proper separation (components, lib, utils)
17
- 6. **Performance**: Leverage automatic optimizations (code-splitting, prefetching, caching)
18
-
19
- ## Server vs Client Components
20
-
21
- ### Server Components (Default)
22
-
23
- Use Server Components by default for data fetching and rendering:
24
-
25
- ```tsx
26
- // ✅ Good: Server Component (no "use client")
27
- async function ProductPage({ params }: { params: { id: string } }) {
28
- const product = await fetch(`https://api.example.com/products/${params.id}`, {
29
- next: { revalidate: 60 }
30
- }).then(res => res.json());
31
-
32
- return <div>{product.name}</div>;
33
- }
34
- ```
35
-
36
- **Use Server Components when**:
37
- - Fetching data from APIs or databases
38
- - Accessing environment variables
39
- - Rendering static or semi-static content
40
- - Keeping bundle size small
41
-
42
- ### Client Components
43
-
44
- Add `"use client"` only when genuinely needed:
45
-
46
- ```tsx
47
- // ✅ Good: Client Component with "use client"
48
- "use client";
49
-
50
- import { useState } from 'react';
51
-
52
- export function Counter() {
53
- const [count, setCount] = useState(0);
54
-
55
- return (
56
- <button onClick={() => setCount(count + 1)}>
57
- Count: {count}
58
- </button>
59
- );
60
- }
61
- ```
62
-
63
- **Use Client Components when**:
64
- - Event handlers (`onClick`, `onChange`, `onSubmit`)
65
- - Browser APIs (`window`, `localStorage`, `IntersectionObserver`)
66
- - React state and effects (`useState`, `useEffect`, `useRef`)
67
- - Third-party libraries that require client-side execution
68
-
69
- ### Composition Pattern
70
-
71
- Keep client boundary small by composing Server Components inside Client Components:
72
-
73
- ```tsx
74
- // ✅ Good: Client Component receiving Server Component as children
75
- // components/dashboard/DashboardLayout.tsx
76
- "use client";
77
-
78
- import { useState } from 'react';
79
-
80
- export function DashboardLayout({ children }: { children: React.ReactNode }) {
81
- const [sidebarOpen, setSidebarOpen] = useState(false);
82
-
83
- return (
84
- <div>
85
- <button onClick={() => setSidebarOpen(!sidebarOpen)}>Toggle</button>
86
- {children}
87
- </div>
88
- );
89
- }
90
- ```
91
-
92
- ```tsx
93
- // ✅ Good: Server Component passing content to Client Component
94
- // app/dashboard/page.tsx
95
- import { DashboardLayout } from '@/components/dashboard/DashboardLayout';
96
- import { StatsCard } from '@/components/dashboard/StatsCard'; // Server Component
97
-
98
- export default async function DashboardPage() {
99
- const stats = await fetchStats(); // Server-side data fetching
100
-
101
- return (
102
- <DashboardLayout>
103
- <StatsCard data={stats} />
104
- </DashboardLayout>
105
- );
106
- }
107
- ```
108
-
109
- ## Data Fetching
110
-
111
- ### Direct Fetching in Server Components
112
-
113
- Fetch data directly without `useEffect`:
114
-
115
- ```tsx
116
- // ✅ Good: Direct data fetching
117
- async function ProductList() {
118
- const products = await fetch('https://api.example.com/products', {
119
- next: { revalidate: 60 } // Revalidate every 60 seconds
120
- }).then(res => res.json());
121
-
122
- return (
123
- <ul>
124
- {products.map(product => (
125
- <li key={product.id}>{product.name}</li>
126
- ))}
127
- </ul>
128
- );
129
- }
130
- ```
131
-
132
- ### Parallel Fetching
133
-
134
- Use `Promise.all()` for multiple resources:
135
-
136
- ```tsx
137
- // ✅ Good: Parallel data fetching
138
- async function Dashboard() {
139
- const [users, products, orders] = await Promise.all([
140
- fetch('https://api.example.com/users').then(res => res.json()),
141
- fetch('https://api.example.com/products').then(res => res.json()),
142
- fetch('https://api.example.com/orders').then(res => res.json())
143
- ]);
144
-
145
- return (
146
- <div>
147
- <UsersSection users={users} />
148
- <ProductsSection products={products} />
149
- <OrdersSection orders={orders} />
150
- </div>
151
- );
152
- }
153
- ```
154
-
155
- ### Caching Strategies
156
-
157
- ```tsx
158
- // Time-based revalidation
159
- const data = await fetch(url, {
160
- next: { revalidate: 3600 } // Revalidate every hour
161
- });
162
-
163
- // No caching (always fresh)
164
- const data = await fetch(url, { cache: 'no-store' });
165
-
166
- // On-demand revalidation
167
- // In your route handler:
168
- import { revalidateTag } from 'next/cache';
169
-
170
- revalidateTag('products'); // Revalidate all data tagged with 'products'
171
-
172
- // In your fetch:
173
- const data = await fetch(url, {
174
- next: { tags: ['products'] }
175
- });
176
- ```
177
-
178
- ## Project Structure
179
-
180
- ### Core Directory Layout
181
-
182
- ```
183
- src/
184
- ├── app/ # App Router (routes)
185
- │ ├── (auth)/ # Route group (doesn't affect URL)
186
- │ │ ├── login/
187
- │ │ └── register/
188
- │ ├── (dashboard)/ # Another route group
189
- │ │ ├── layout.tsx # Shared layout for dashboard routes
190
- │ │ ├── page.tsx # /dashboard
191
- │ │ └── settings/
192
- │ ├── api/ # API routes
193
- │ │ └── users/
194
- │ │ └── route.ts
195
- │ ├── globals.css
196
- │ ├── layout.tsx # Root layout
197
- │ └── page.tsx # Home page
198
- ├── components/
199
- │ ├── ui/ # Reusable UI components (Button, Card, Modal)
200
- │ ├── layout/ # Layout components (Header, Footer, Sidebar)
201
- │ └── features/ # Feature-specific components
202
- │ ├── auth/
203
- │ ├── dashboard/
204
- │ └── products/
205
- ├── lib/ # Business logic, API clients, auth
206
- │ ├── api.ts
207
- │ ├── auth.ts
208
- │ └── db.ts
209
- ├── utils/ # Pure utility functions
210
- │ ├── cn.ts
211
- │ └── formatters.ts
212
- ├── types/ # TypeScript types
213
- │ └── index.ts
214
- └── styles/ # Additional styles
215
- └── variables.css
216
-
217
- public/ # Static assets
218
- ├── images/
219
- └── fonts/
220
- ```
221
-
222
- ### Route Organization
223
-
224
- Use route groups for organization without affecting URL structure:
225
-
226
- ```
227
- app/
228
- ├── (marketing)/ # Marketing pages: /, /about, /contact
229
- │ ├── page.tsx # /
230
- │ ├── about/
231
- │ │ └── page.tsx # /about
232
- │ └── contact/
233
- │ └── page.tsx # /contact
234
- ├── (auth)/ # Auth pages: /login, /register
235
- │ ├── login/
236
- │ │ └── page.tsx # /login
237
- │ └── register/
238
- │ └── page.tsx # /register
239
- └── (app)/ # App routes: /dashboard, /settings
240
- ├── dashboard/
241
- │ └── page.tsx # /dashboard
242
- └── settings/
243
- └── page.tsx # /settings
244
- ```
245
-
246
- ### Component Organization
247
-
248
- Each component in its own folder:
249
-
250
- ```
251
- components/ui/Button/
252
- ├── Button.tsx # Main component
253
- ├── Button.test.tsx # Tests
254
- ├── Button.stories.tsx # Storybook (optional)
255
- └── index.ts # Barrel export
256
- ```
257
-
258
- ```tsx
259
- // components/ui/Button/Button.tsx
260
- import { clsx } from 'clsx';
261
-
262
- interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
263
- variant?: 'primary' | 'secondary' | 'outline';
264
- size?: 'sm' | 'md' | 'lg';
265
- }
266
-
267
- export function Button({
268
- variant = 'primary',
269
- size = 'md',
270
- className,
271
- children,
272
- ...props
273
- }: ButtonProps) {
274
- return (
275
- <button
276
- className={clsx(
277
- 'font-medium rounded transition-colors',
278
- {
279
- 'bg-blue-600 text-white hover:bg-blue-700': variant === 'primary',
280
- 'bg-gray-200 text-gray-900 hover:bg-gray-300': variant === 'secondary',
281
- 'border border-gray-300 hover:bg-gray-100': variant === 'outline',
282
- 'px-3 py-1.5 text-sm': size === 'sm',
283
- 'px-4 py-2 text-base': size === 'md',
284
- 'px-6 py-3 text-lg': size === 'lg',
285
- },
286
- className
287
- )}
288
- {...props}
289
- >
290
- {children}
291
- </button>
292
- );
293
- }
294
- ```
295
-
296
- ## Utils vs Lib
297
-
298
- Distinguish between utils and lib:
299
-
300
- ```typescript
301
- // ✅ utils/formatters.ts - Pure functions, no side effects
302
- export function formatCurrency(amount: number): string {
303
- return new Intl.NumberFormat('en-US', {
304
- style: 'currency',
305
- currency: 'USD'
306
- }).format(amount);
307
- }
308
-
309
- // ✅ lib/api.ts - Business logic, external dependencies
310
- import { ENV } from './env';
311
-
312
- export async function fetchUser(id: string) {
313
- const response = await fetch(`${ENV.API_URL}/users/${id}`, {
314
- headers: {
315
- 'Authorization': `Bearer ${ENV.API_KEY}`
316
- }
317
- });
318
-
319
- if (!response.ok) {
320
- throw new Error('Failed to fetch user');
321
- }
322
-
323
- return response.json();
324
- }
325
- ```
326
-
327
- ## Performance Optimizations
328
-
329
- ### Automatic Optimizations (Built-in)
330
-
331
- Next.js provides by default:
332
- - **Code-splitting**: By route segments
333
- - **Link prefetching**: `<Link>` components prefetch in viewport
334
- - **Prerendering**: At build time
335
- - **Intelligent caching**: Data requests and rendered components
336
-
337
- ### Image Optimization
338
-
339
- ```tsx
340
- import Image from 'next/image';
341
-
342
- // ✅ Good: Optimized image
343
- <Image
344
- src="/hero.jpg"
345
- alt="Hero banner"
346
- width={1200}
347
- height={630}
348
- priority // For above-the-fold images
349
- quality={85}
350
- />
351
- ```
352
-
353
- ### Font Optimization
354
-
355
- ```tsx
356
- // ✅ Good: Optimized fonts
357
- import { Inter } from 'next/font/google';
358
-
359
- const inter = Inter({
360
- subsets: ['latin'],
361
- display: 'swap',
362
- variable: '--font-inter'
363
- });
364
-
365
- export default function RootLayout({ children }) {
366
- return (
367
- <html lang="en" className={inter.variable}>
368
- <body>{children}</body>
369
- </html>
370
- );
371
- }
372
- ```
373
-
374
- ## Error Handling
375
-
376
- ### Error Boundaries
377
-
378
- ```tsx
379
- // app/error.tsx
380
- "use client";
381
-
382
- import { useEffect } from 'react';
383
-
384
- export default function Error({
385
- error,
386
- reset,
387
- }: {
388
- error: Error & { digest?: string };
389
- reset: () => void;
390
- }) {
391
- useEffect(() => {
392
- console.error('Application error:', error);
393
- }, [error]);
394
-
395
- return (
396
- <div>
397
- <h2>Something went wrong!</h2>
398
- <button onClick={() => reset()}>Try again</button>
399
- </div>
400
- );
401
- }
402
- ```
403
-
404
- ### Not Found Handling
405
-
406
- ```tsx
407
- // app/not-found.tsx
408
- import Link from 'next/link';
409
-
410
- export default function NotFound() {
411
- return (
412
- <div>
413
- <h2>Page Not Found</h2>
414
- <p>Could not find requested resource</p>
415
- <Link href="/">Return Home</Link>
416
- </div>
417
- );
418
- }
419
- ```
420
-
421
- ### Loading States
422
-
423
- ```tsx
424
- // app/dashboard/loading.tsx
425
- export default function Loading() {
426
- return (
427
- <div className="flex items-center justify-center min-h-screen">
428
- <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600" />
429
- </div>
430
- );
431
- }
432
- ```
433
-
434
- ## API Routes
435
-
436
- ### RESTful API Structure
437
-
438
- ```typescript
439
- // app/api/users/route.ts
440
- import { NextRequest, NextResponse } from 'next/server';
441
- import { db } from '@/lib/db';
442
-
443
- export async function GET() {
444
- try {
445
- const users = await db.user.findMany();
446
- return NextResponse.json(users);
447
- } catch (error) {
448
- console.error('Failed to fetch users:', error);
449
- return NextResponse.json(
450
- { error: 'Failed to fetch users' },
451
- { status: 500 }
452
- );
453
- }
454
- }
455
-
456
- export async function POST(request: NextRequest) {
457
- try {
458
- const body = await request.json();
459
- const user = await db.user.create({ data: body });
460
- return NextResponse.json(user, { status: 201 });
461
- } catch (error) {
462
- return NextResponse.json(
463
- { error: 'Failed to create user' },
464
- { status: 400 }
465
- );
466
- }
467
- }
468
- ```
469
-
470
- ## Testing
471
-
472
- ### Component Testing with Vitest
473
-
474
- ```tsx
475
- // __tests__/Button.test.tsx
476
- import { render, screen } from '@testing-library/react';
477
- import { describe, it, expect } from 'vitest';
478
- import { Button } from '@/components/ui/Button';
479
-
480
- describe('Button', () => {
481
- it('renders with default props', () => {
482
- render(<Button>Click me</Button>);
483
- expect(screen.getByRole('button')).toHaveTextContent('Click me');
484
- });
485
-
486
- it('handles click events', () => {
487
- const handleClick = vi.fn();
488
- render(<Button onClick={handleClick}>Click me</Button>);
489
- screen.getByRole('button').click();
490
- expect(handleClick).toHaveBeenCalledTimes(1);
491
- });
492
-
493
- it('applies variant classes', () => {
494
- const { container } = render(<Button variant="primary">Test</Button>);
495
- expect(container.firstChild).toHaveClass('bg-blue-600');
496
- });
497
- });
498
- ```
499
-
500
- ## Commands
501
-
502
- ### Essential Next.js Commands
503
-
504
- ```bash
505
- npm run dev # Start development server
506
- npm run build # Build for production
507
- npm run start # Start production server
508
- npm run lint # Run ESLint
509
- npm run typecheck # Run TypeScript checker
510
- npm run test # Run test suite
511
- ```
512
-
513
- ## Anti-Patterns to Avoid
514
-
515
- ### ❌ Bad: Unnecessary Client Components
516
-
517
- ```tsx
518
- // ❌ Bad: Using Client Component when Server Component suffices
519
- "use client";
520
-
521
- export async function ProductPage({ params }) {
522
- const product = await fetchProduct(params.id);
523
- return <div>{product.name}</div>;
524
- }
525
- ```
526
-
527
- ```tsx
528
- // ✅ Good: Server Component
529
- export async function ProductPage({ params }) {
530
- const product = await fetchProduct(params.id);
531
- return <div>{product.name}</div>;
532
- }
533
- ```
534
-
535
- ### ❌ Bad: Large Client Components
536
-
537
- ```tsx
538
- // ❌ Bad: Everything in one Client Component
539
- "use client";
540
-
541
- export function Dashboard() {
542
- const [data, setData] = useState(null);
543
-
544
- useEffect(() => {
545
- fetchData().then(setData);
546
- }, []);
547
-
548
- return <div>...</div>;
549
- }
550
- ```
551
-
552
- ```tsx
553
- // ✅ Good: Split Server and Client
554
- async function Dashboard() {
555
- const data = await fetchData();
556
- return <DashboardClient initialData={data} />;
557
- }
558
-
559
- "use client";
560
-
561
- function DashboardClient({ initialData }) {
562
- const [data, setData] = useState(initialData);
563
- return <div>...</div>;
564
- }
565
- ```
566
-
567
- ### ❌ Bad: Waterfall Fetching
568
-
569
- ```tsx
570
- // ❌ Bad: Sequential fetching
571
- async function Page() {
572
- const user = await fetchUser();
573
- const posts = await fetchPosts(user.id);
574
- const comments = await fetchComments(posts[0].id);
575
- // ...
576
- }
577
- ```
578
-
579
- ```tsx
580
- // ✅ Good: Parallel fetching
581
- async function Page() {
582
- const [user, posts, comments] = await Promise.all([
583
- fetchUser(),
584
- fetchPosts(user.id),
585
- fetchComments(posts[0].id)
586
- ]);
587
- }
588
- ```
589
-
590
- ## Examples
591
-
592
- ### Example 1: E-commerce Product Page
593
-
594
- ```tsx
595
- // app/products/[id]/page.tsx
596
- import { notFound } from 'next/navigation';
597
- import { ProductImages } from './ProductImages';
598
- import { AddToCart } from './AddToCart';
599
-
600
- async function getProduct(id: string) {
601
- const res = await fetch(`https://api.example.com/products/${id}`, {
602
- next: { revalidate: 3600, tags: ['products'] }
603
- });
604
-
605
- if (!res.ok) return null;
606
- return res.json();
607
- }
608
-
609
- export default async function ProductPage({
610
- params
611
- }: {
612
- params: { id: string }
613
- }) {
614
- const product = await getProduct(params.id);
615
-
616
- if (!product) {
617
- notFound();
618
- }
619
-
620
- return (
621
- <div>
622
- <ProductImages images={product.images} />
623
- <div>
624
- <h1>{product.name}</h1>
625
- <p>{product.description}</p>
626
- <p>${product.price}</p>
627
- <AddToCart productId={product.id} />
628
- </div>
629
- </div>
630
- );
631
- }
632
- ```
633
-
634
- ```tsx
635
- // app/products/[id]/AddToCart.tsx
636
- "use client";
637
-
638
- import { useState } from 'react';
639
-
640
- export function AddToCart({ productId }: { productId: string }) {
641
- const [quantity, setQuantity] = useState(1);
642
-
643
- return (
644
- <div>
645
- <input
646
- type="number"
647
- value={quantity}
648
- onChange={(e) => setQuantity(Number(e.target.value))}
649
- min={1}
650
- />
651
- <button onClick={() => addToCart(productId, quantity)}>
652
- Add to Cart
653
- </button>
654
- </div>
655
- );
656
- }
657
- ```
658
-
659
- ### Example 2: Dashboard with Authentication
660
-
661
- ```tsx
662
- // app/(dashboard)/dashboard/page.tsx
663
- import { redirect } from 'next/navigation';
664
- import { getSession } from '@/lib/auth';
665
- import { DashboardLayout } from '@/components/layout/DashboardLayout';
666
- import { StatsCards } from './StatsCards';
667
-
668
- export default async function DashboardPage() {
669
- const session = await getSession();
670
-
671
- if (!session) {
672
- redirect('/login');
673
- }
674
-
675
- return (
676
- <DashboardLayout user={session.user}>
677
- <StatsCards userId={session.user.id} />
678
- </DashboardLayout>
679
- );
680
- }
681
- ```
682
-
683
- ## Additional Resources
684
-
685
- - For complete API details, see [Next.js Documentation](https://nextjs.org/docs)
686
- - For App Router patterns, see [Next.js App Router Guide](https://nextjs.org/docs/app)
687
- - For production checklist, see [Next.js Production Guide](https://nextjs.org/docs/app/guides/production-checklist)
1
+ ---
2
+ name: nextjs-guide
3
+ description: Apply Next.js 14-15 best practices including App Router, Server Components, data fetching, and project structure. Use when building, reviewing, or optimizing Next.js applications.
4
+ ---
5
+
6
+ # Next.js Best Practices
7
+
8
+ ## Quick Start
9
+
10
+ When working with Next.js 14-15:
11
+
12
+ 1. **Server Components by default**: Only use `"use client"` when necessary
13
+ 2. **App Router structure**: Use route groups, layouts, and proper file organization
14
+ 3. **Data fetching**: Fetch directly in Server Components, use proper caching
15
+ 4. **Component composition**: Keep client boundary small, compose Server Components inside Client Components
16
+ 5. **Project structure**: Use `src/` directory with proper separation (components, lib, utils)
17
+ 6. **Performance**: Leverage automatic optimizations (code-splitting, prefetching, caching)
18
+
19
+ ## Server vs Client Components
20
+
21
+ ### Server Components (Default)
22
+
23
+ Use Server Components by default for data fetching and rendering:
24
+
25
+ ```tsx
26
+ // ✅ Good: Server Component (no "use client")
27
+ async function ProductPage({ params }: { params: { id: string } }) {
28
+ const product = await fetch(`https://api.example.com/products/${params.id}`, {
29
+ next: { revalidate: 60 }
30
+ }).then(res => res.json());
31
+
32
+ return <div>{product.name}</div>;
33
+ }
34
+ ```
35
+
36
+ **Use Server Components when**:
37
+ - Fetching data from APIs or databases
38
+ - Accessing environment variables
39
+ - Rendering static or semi-static content
40
+ - Keeping bundle size small
41
+
42
+ ### Client Components
43
+
44
+ Add `"use client"` only when genuinely needed:
45
+
46
+ ```tsx
47
+ // ✅ Good: Client Component with "use client"
48
+ "use client";
49
+
50
+ import { useState } from 'react';
51
+
52
+ export function Counter() {
53
+ const [count, setCount] = useState(0);
54
+
55
+ return (
56
+ <button onClick={() => setCount(count + 1)}>
57
+ Count: {count}
58
+ </button>
59
+ );
60
+ }
61
+ ```
62
+
63
+ **Use Client Components when**:
64
+ - Event handlers (`onClick`, `onChange`, `onSubmit`)
65
+ - Browser APIs (`window`, `localStorage`, `IntersectionObserver`)
66
+ - React state and effects (`useState`, `useEffect`, `useRef`)
67
+ - Third-party libraries that require client-side execution
68
+
69
+ ### Composition Pattern
70
+
71
+ Keep client boundary small by composing Server Components inside Client Components:
72
+
73
+ ```tsx
74
+ // ✅ Good: Client Component receiving Server Component as children
75
+ // components/dashboard/DashboardLayout.tsx
76
+ "use client";
77
+
78
+ import { useState } from 'react';
79
+
80
+ export function DashboardLayout({ children }: { children: React.ReactNode }) {
81
+ const [sidebarOpen, setSidebarOpen] = useState(false);
82
+
83
+ return (
84
+ <div>
85
+ <button onClick={() => setSidebarOpen(!sidebarOpen)}>Toggle</button>
86
+ {children}
87
+ </div>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ```tsx
93
+ // ✅ Good: Server Component passing content to Client Component
94
+ // app/dashboard/page.tsx
95
+ import { DashboardLayout } from '@/components/dashboard/DashboardLayout';
96
+ import { StatsCard } from '@/components/dashboard/StatsCard'; // Server Component
97
+
98
+ export default async function DashboardPage() {
99
+ const stats = await fetchStats(); // Server-side data fetching
100
+
101
+ return (
102
+ <DashboardLayout>
103
+ <StatsCard data={stats} />
104
+ </DashboardLayout>
105
+ );
106
+ }
107
+ ```
108
+
109
+ ## Data Fetching
110
+
111
+ ### Direct Fetching in Server Components
112
+
113
+ Fetch data directly without `useEffect`:
114
+
115
+ ```tsx
116
+ // ✅ Good: Direct data fetching
117
+ async function ProductList() {
118
+ const products = await fetch('https://api.example.com/products', {
119
+ next: { revalidate: 60 } // Revalidate every 60 seconds
120
+ }).then(res => res.json());
121
+
122
+ return (
123
+ <ul>
124
+ {products.map(product => (
125
+ <li key={product.id}>{product.name}</li>
126
+ ))}
127
+ </ul>
128
+ );
129
+ }
130
+ ```
131
+
132
+ ### Parallel Fetching
133
+
134
+ Use `Promise.all()` for multiple resources:
135
+
136
+ ```tsx
137
+ // ✅ Good: Parallel data fetching
138
+ async function Dashboard() {
139
+ const [users, products, orders] = await Promise.all([
140
+ fetch('https://api.example.com/users').then(res => res.json()),
141
+ fetch('https://api.example.com/products').then(res => res.json()),
142
+ fetch('https://api.example.com/orders').then(res => res.json())
143
+ ]);
144
+
145
+ return (
146
+ <div>
147
+ <UsersSection users={users} />
148
+ <ProductsSection products={products} />
149
+ <OrdersSection orders={orders} />
150
+ </div>
151
+ );
152
+ }
153
+ ```
154
+
155
+ ### Caching Strategies
156
+
157
+ ```tsx
158
+ // Time-based revalidation
159
+ const data = await fetch(url, {
160
+ next: { revalidate: 3600 } // Revalidate every hour
161
+ });
162
+
163
+ // No caching (always fresh)
164
+ const data = await fetch(url, { cache: 'no-store' });
165
+
166
+ // On-demand revalidation
167
+ // In your route handler:
168
+ import { revalidateTag } from 'next/cache';
169
+
170
+ revalidateTag('products'); // Revalidate all data tagged with 'products'
171
+
172
+ // In your fetch:
173
+ const data = await fetch(url, {
174
+ next: { tags: ['products'] }
175
+ });
176
+ ```
177
+
178
+ ## Project Structure
179
+
180
+ ### Core Directory Layout
181
+
182
+ ```
183
+ src/
184
+ ├── app/ # App Router (routes)
185
+ │ ├── (auth)/ # Route group (doesn't affect URL)
186
+ │ │ ├── login/
187
+ │ │ └── register/
188
+ │ ├── (dashboard)/ # Another route group
189
+ │ │ ├── layout.tsx # Shared layout for dashboard routes
190
+ │ │ ├── page.tsx # /dashboard
191
+ │ │ └── settings/
192
+ │ ├── api/ # API routes
193
+ │ │ └── users/
194
+ │ │ └── route.ts
195
+ │ ├── globals.css
196
+ │ ├── layout.tsx # Root layout
197
+ │ └── page.tsx # Home page
198
+ ├── components/
199
+ │ ├── ui/ # Reusable UI components (Button, Card, Modal)
200
+ │ ├── layout/ # Layout components (Header, Footer, Sidebar)
201
+ │ └── features/ # Feature-specific components
202
+ │ ├── auth/
203
+ │ ├── dashboard/
204
+ │ └── products/
205
+ ├── lib/ # Business logic, API clients, auth
206
+ │ ├── api.ts
207
+ │ ├── auth.ts
208
+ │ └── db.ts
209
+ ├── utils/ # Pure utility functions
210
+ │ ├── cn.ts
211
+ │ └── formatters.ts
212
+ ├── types/ # TypeScript types
213
+ │ └── index.ts
214
+ └── styles/ # Additional styles
215
+ └── variables.css
216
+
217
+ public/ # Static assets
218
+ ├── images/
219
+ └── fonts/
220
+ ```
221
+
222
+ ### Route Organization
223
+
224
+ Use route groups for organization without affecting URL structure:
225
+
226
+ ```
227
+ app/
228
+ ├── (marketing)/ # Marketing pages: /, /about, /contact
229
+ │ ├── page.tsx # /
230
+ │ ├── about/
231
+ │ │ └── page.tsx # /about
232
+ │ └── contact/
233
+ │ └── page.tsx # /contact
234
+ ├── (auth)/ # Auth pages: /login, /register
235
+ │ ├── login/
236
+ │ │ └── page.tsx # /login
237
+ │ └── register/
238
+ │ └── page.tsx # /register
239
+ └── (app)/ # App routes: /dashboard, /settings
240
+ ├── dashboard/
241
+ │ └── page.tsx # /dashboard
242
+ └── settings/
243
+ └── page.tsx # /settings
244
+ ```
245
+
246
+ ### Component Organization
247
+
248
+ Each component in its own folder:
249
+
250
+ ```
251
+ components/ui/Button/
252
+ ├── Button.tsx # Main component
253
+ ├── Button.test.tsx # Tests
254
+ ├── Button.stories.tsx # Storybook (optional)
255
+ └── index.ts # Barrel export
256
+ ```
257
+
258
+ ```tsx
259
+ // components/ui/Button/Button.tsx
260
+ import { clsx } from 'clsx';
261
+
262
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
263
+ variant?: 'primary' | 'secondary' | 'outline';
264
+ size?: 'sm' | 'md' | 'lg';
265
+ }
266
+
267
+ export function Button({
268
+ variant = 'primary',
269
+ size = 'md',
270
+ className,
271
+ children,
272
+ ...props
273
+ }: ButtonProps) {
274
+ return (
275
+ <button
276
+ className={clsx(
277
+ 'font-medium rounded transition-colors',
278
+ {
279
+ 'bg-blue-600 text-white hover:bg-blue-700': variant === 'primary',
280
+ 'bg-gray-200 text-gray-900 hover:bg-gray-300': variant === 'secondary',
281
+ 'border border-gray-300 hover:bg-gray-100': variant === 'outline',
282
+ 'px-3 py-1.5 text-sm': size === 'sm',
283
+ 'px-4 py-2 text-base': size === 'md',
284
+ 'px-6 py-3 text-lg': size === 'lg',
285
+ },
286
+ className
287
+ )}
288
+ {...props}
289
+ >
290
+ {children}
291
+ </button>
292
+ );
293
+ }
294
+ ```
295
+
296
+ ## Utils vs Lib
297
+
298
+ Distinguish between utils and lib:
299
+
300
+ ```typescript
301
+ // ✅ utils/formatters.ts - Pure functions, no side effects
302
+ export function formatCurrency(amount: number): string {
303
+ return new Intl.NumberFormat('en-US', {
304
+ style: 'currency',
305
+ currency: 'USD'
306
+ }).format(amount);
307
+ }
308
+
309
+ // ✅ lib/api.ts - Business logic, external dependencies
310
+ import { ENV } from './env';
311
+
312
+ export async function fetchUser(id: string) {
313
+ const response = await fetch(`${ENV.API_URL}/users/${id}`, {
314
+ headers: {
315
+ 'Authorization': `Bearer ${ENV.API_KEY}`
316
+ }
317
+ });
318
+
319
+ if (!response.ok) {
320
+ throw new Error('Failed to fetch user');
321
+ }
322
+
323
+ return response.json();
324
+ }
325
+ ```
326
+
327
+ ## Performance Optimizations
328
+
329
+ ### Automatic Optimizations (Built-in)
330
+
331
+ Next.js provides by default:
332
+ - **Code-splitting**: By route segments
333
+ - **Link prefetching**: `<Link>` components prefetch in viewport
334
+ - **Prerendering**: At build time
335
+ - **Intelligent caching**: Data requests and rendered components
336
+
337
+ ### Image Optimization
338
+
339
+ ```tsx
340
+ import Image from 'next/image';
341
+
342
+ // ✅ Good: Optimized image
343
+ <Image
344
+ src="/hero.jpg"
345
+ alt="Hero banner"
346
+ width={1200}
347
+ height={630}
348
+ priority // For above-the-fold images
349
+ quality={85}
350
+ />
351
+ ```
352
+
353
+ ### Font Optimization
354
+
355
+ ```tsx
356
+ // ✅ Good: Optimized fonts
357
+ import { Inter } from 'next/font/google';
358
+
359
+ const inter = Inter({
360
+ subsets: ['latin'],
361
+ display: 'swap',
362
+ variable: '--font-inter'
363
+ });
364
+
365
+ export default function RootLayout({ children }) {
366
+ return (
367
+ <html lang="en" className={inter.variable}>
368
+ <body>{children}</body>
369
+ </html>
370
+ );
371
+ }
372
+ ```
373
+
374
+ ## Error Handling
375
+
376
+ ### Error Boundaries
377
+
378
+ ```tsx
379
+ // app/error.tsx
380
+ "use client";
381
+
382
+ import { useEffect } from 'react';
383
+
384
+ export default function Error({
385
+ error,
386
+ reset,
387
+ }: {
388
+ error: Error & { digest?: string };
389
+ reset: () => void;
390
+ }) {
391
+ useEffect(() => {
392
+ console.error('Application error:', error);
393
+ }, [error]);
394
+
395
+ return (
396
+ <div>
397
+ <h2>Something went wrong!</h2>
398
+ <button onClick={() => reset()}>Try again</button>
399
+ </div>
400
+ );
401
+ }
402
+ ```
403
+
404
+ ### Not Found Handling
405
+
406
+ ```tsx
407
+ // app/not-found.tsx
408
+ import Link from 'next/link';
409
+
410
+ export default function NotFound() {
411
+ return (
412
+ <div>
413
+ <h2>Page Not Found</h2>
414
+ <p>Could not find requested resource</p>
415
+ <Link href="/">Return Home</Link>
416
+ </div>
417
+ );
418
+ }
419
+ ```
420
+
421
+ ### Loading States
422
+
423
+ ```tsx
424
+ // app/dashboard/loading.tsx
425
+ export default function Loading() {
426
+ return (
427
+ <div className="flex items-center justify-center min-h-screen">
428
+ <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600" />
429
+ </div>
430
+ );
431
+ }
432
+ ```
433
+
434
+ ## API Routes
435
+
436
+ ### RESTful API Structure
437
+
438
+ ```typescript
439
+ // app/api/users/route.ts
440
+ import { NextRequest, NextResponse } from 'next/server';
441
+ import { db } from '@/lib/db';
442
+
443
+ export async function GET() {
444
+ try {
445
+ const users = await db.user.findMany();
446
+ return NextResponse.json(users);
447
+ } catch (error) {
448
+ console.error('Failed to fetch users:', error);
449
+ return NextResponse.json(
450
+ { error: 'Failed to fetch users' },
451
+ { status: 500 }
452
+ );
453
+ }
454
+ }
455
+
456
+ export async function POST(request: NextRequest) {
457
+ try {
458
+ const body = await request.json();
459
+ const user = await db.user.create({ data: body });
460
+ return NextResponse.json(user, { status: 201 });
461
+ } catch (error) {
462
+ return NextResponse.json(
463
+ { error: 'Failed to create user' },
464
+ { status: 400 }
465
+ );
466
+ }
467
+ }
468
+ ```
469
+
470
+ ## Testing
471
+
472
+ ### Component Testing with Vitest
473
+
474
+ ```tsx
475
+ // __tests__/Button.test.tsx
476
+ import { render, screen } from '@testing-library/react';
477
+ import { describe, it, expect } from 'vitest';
478
+ import { Button } from '@/components/ui/Button';
479
+
480
+ describe('Button', () => {
481
+ it('renders with default props', () => {
482
+ render(<Button>Click me</Button>);
483
+ expect(screen.getByRole('button')).toHaveTextContent('Click me');
484
+ });
485
+
486
+ it('handles click events', () => {
487
+ const handleClick = vi.fn();
488
+ render(<Button onClick={handleClick}>Click me</Button>);
489
+ screen.getByRole('button').click();
490
+ expect(handleClick).toHaveBeenCalledTimes(1);
491
+ });
492
+
493
+ it('applies variant classes', () => {
494
+ const { container } = render(<Button variant="primary">Test</Button>);
495
+ expect(container.firstChild).toHaveClass('bg-blue-600');
496
+ });
497
+ });
498
+ ```
499
+
500
+ ## Commands
501
+
502
+ ### Essential Next.js Commands
503
+
504
+ ```bash
505
+ npm run dev # Start development server
506
+ npm run build # Build for production
507
+ npm run start # Start production server
508
+ npm run lint # Run ESLint
509
+ npm run typecheck # Run TypeScript checker
510
+ npm run test # Run test suite
511
+ ```
512
+
513
+ ## Anti-Patterns to Avoid
514
+
515
+ ### ❌ Bad: Unnecessary Client Components
516
+
517
+ ```tsx
518
+ // ❌ Bad: Using Client Component when Server Component suffices
519
+ "use client";
520
+
521
+ export async function ProductPage({ params }) {
522
+ const product = await fetchProduct(params.id);
523
+ return <div>{product.name}</div>;
524
+ }
525
+ ```
526
+
527
+ ```tsx
528
+ // ✅ Good: Server Component
529
+ export async function ProductPage({ params }) {
530
+ const product = await fetchProduct(params.id);
531
+ return <div>{product.name}</div>;
532
+ }
533
+ ```
534
+
535
+ ### ❌ Bad: Large Client Components
536
+
537
+ ```tsx
538
+ // ❌ Bad: Everything in one Client Component
539
+ "use client";
540
+
541
+ export function Dashboard() {
542
+ const [data, setData] = useState(null);
543
+
544
+ useEffect(() => {
545
+ fetchData().then(setData);
546
+ }, []);
547
+
548
+ return <div>...</div>;
549
+ }
550
+ ```
551
+
552
+ ```tsx
553
+ // ✅ Good: Split Server and Client
554
+ async function Dashboard() {
555
+ const data = await fetchData();
556
+ return <DashboardClient initialData={data} />;
557
+ }
558
+
559
+ "use client";
560
+
561
+ function DashboardClient({ initialData }) {
562
+ const [data, setData] = useState(initialData);
563
+ return <div>...</div>;
564
+ }
565
+ ```
566
+
567
+ ### ❌ Bad: Waterfall Fetching
568
+
569
+ ```tsx
570
+ // ❌ Bad: Sequential fetching
571
+ async function Page() {
572
+ const user = await fetchUser();
573
+ const posts = await fetchPosts(user.id);
574
+ const comments = await fetchComments(posts[0].id);
575
+ // ...
576
+ }
577
+ ```
578
+
579
+ ```tsx
580
+ // ✅ Good: Parallel fetching
581
+ async function Page() {
582
+ const [user, posts, comments] = await Promise.all([
583
+ fetchUser(),
584
+ fetchPosts(user.id),
585
+ fetchComments(posts[0].id)
586
+ ]);
587
+ }
588
+ ```
589
+
590
+ ## Examples
591
+
592
+ ### Example 1: E-commerce Product Page
593
+
594
+ ```tsx
595
+ // app/products/[id]/page.tsx
596
+ import { notFound } from 'next/navigation';
597
+ import { ProductImages } from './ProductImages';
598
+ import { AddToCart } from './AddToCart';
599
+
600
+ async function getProduct(id: string) {
601
+ const res = await fetch(`https://api.example.com/products/${id}`, {
602
+ next: { revalidate: 3600, tags: ['products'] }
603
+ });
604
+
605
+ if (!res.ok) return null;
606
+ return res.json();
607
+ }
608
+
609
+ export default async function ProductPage({
610
+ params
611
+ }: {
612
+ params: { id: string }
613
+ }) {
614
+ const product = await getProduct(params.id);
615
+
616
+ if (!product) {
617
+ notFound();
618
+ }
619
+
620
+ return (
621
+ <div>
622
+ <ProductImages images={product.images} />
623
+ <div>
624
+ <h1>{product.name}</h1>
625
+ <p>{product.description}</p>
626
+ <p>${product.price}</p>
627
+ <AddToCart productId={product.id} />
628
+ </div>
629
+ </div>
630
+ );
631
+ }
632
+ ```
633
+
634
+ ```tsx
635
+ // app/products/[id]/AddToCart.tsx
636
+ "use client";
637
+
638
+ import { useState } from 'react';
639
+
640
+ export function AddToCart({ productId }: { productId: string }) {
641
+ const [quantity, setQuantity] = useState(1);
642
+
643
+ return (
644
+ <div>
645
+ <input
646
+ type="number"
647
+ value={quantity}
648
+ onChange={(e) => setQuantity(Number(e.target.value))}
649
+ min={1}
650
+ />
651
+ <button onClick={() => addToCart(productId, quantity)}>
652
+ Add to Cart
653
+ </button>
654
+ </div>
655
+ );
656
+ }
657
+ ```
658
+
659
+ ### Example 2: Dashboard with Authentication
660
+
661
+ ```tsx
662
+ // app/(dashboard)/dashboard/page.tsx
663
+ import { redirect } from 'next/navigation';
664
+ import { getSession } from '@/lib/auth';
665
+ import { DashboardLayout } from '@/components/layout/DashboardLayout';
666
+ import { StatsCards } from './StatsCards';
667
+
668
+ export default async function DashboardPage() {
669
+ const session = await getSession();
670
+
671
+ if (!session) {
672
+ redirect('/login');
673
+ }
674
+
675
+ return (
676
+ <DashboardLayout user={session.user}>
677
+ <StatsCards userId={session.user.id} />
678
+ </DashboardLayout>
679
+ );
680
+ }
681
+ ```
682
+
683
+ ## Additional Resources
684
+
685
+ - For complete API details, see [Next.js Documentation](https://nextjs.org/docs)
686
+ - For App Router patterns, see [Next.js App Router Guide](https://nextjs.org/docs/app)
687
+ - For production checklist, see [Next.js Production Guide](https://nextjs.org/docs/app/guides/production-checklist)