# Next.js Core Concepts

## App Router vs Pages Router

**App Router (Default)** - Recommended for new projects
- React Server Components (default)
- Nested layouts with state preservation
- Server Actions for mutations
- Streaming and Suspense
- File-based routing in `app/`

**Pages Router (Legacy)** - Use for existing apps
- Traditional file-based routing in `pages/`
- API routes in `pages/api`
- Team familiarity with Pages conventions

**Decision:** New project? → App Router | Existing Pages app? → Continue with Pages

## Server vs Client Components

### Server Components (Default)
**Use when:**
- Fetching data from DB/API
- Accessing backend resources
- Sensitive information (API keys)
- Heavy dependencies (exclude from client bundle)

**Characteristics:**
- Run on server
- Can be async
- No React hooks
- Not in client bundle

### Client Components
**Use when:**
- Interactivity (onClick, onChange)
- Browser APIs (window, localStorage)
- React hooks (useState, useEffect)
- Event listeners

**Characteristics:**
- Run in browser
- Requires 'use client'
- Can use all React features

```typescript
// Server Component (default)
export default async function Page() {
  const data = await fetch('https://api.example.com/posts');
  const posts = await data.json();
  return <div>{JSON.stringify(posts)}</div>;
}

// Client Component
'use client';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState<number>(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
```

## Data Fetching Strategies

### 1. ⚡ Static Generation (SSG) - Fastest
**When:** Content doesn't change often
**Performance:** Cached at build time, served from CDN edge

```typescript
export const revalidate = false; // Infinite cache

export default async function Page() {
  const data = await fetch('https://api.example.com/posts');
  return <div>{await data.json()}</div>;
}
```

### 2. ⚡ Incremental Static Regeneration (ISR) - Great Performance
**When:** Content changes but doesn't need to be real-time
**Performance:** Cached with periodic revalidation, mostly edge-served

```typescript
export const revalidate = 60; // Revalidate every 60s

export default async function Page() {
  const data = await fetch('https://api.example.com/posts');
  return <div>{await data.json()}</div>;
}
```

### 3. ⚠️ Server-Side Rendering (SSR) - Slower
**When:** User-specific or frequently changing content
**Performance:** Generated on every request, no caching

```typescript
export const dynamic = 'force-dynamic';

export default async function Page() {
  const data = await fetch('https://api.example.com/posts', {
    cache: 'no-store'
  });
  return <div>{await data.json()}</div>;
}
```

### 4. 🔄 Client-Side Data Fetching - Additional Request
**When:** User interactions trigger data fetching
**Performance:** Requires separate network request, adds latency

```typescript
'use client';
import { useEffect, useState } from 'react';

interface SearchResult {
  id: string;
  title: string;
}

export default function Search() {
  const [results, setResults] = useState<SearchResult[]>([]);

  useEffect(() => {
    fetch('/api/search')
      .then(res => res.json())
      .then((data: SearchResult[]) => setResults(data));
  }, []);

  return <div>{results.map(r => r.title).join(', ')}</div>;
}
```

### 5. 🔄 Streaming with Suspense - Progressive Rendering
**When:** Want to show parts of page while others load
**Performance:** Reduces Time to First Byte, improves perceived performance

```typescript
import { Suspense } from 'react';

export default function Page() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <SlowComponent />
      </Suspense>
    </div>
  );
}
```

## Caching Strategies

### Request Deduplication
Automatic - multiple identical requests are deduplicated

### Time-Based Revalidation
```typescript
const res = await fetch('https://api.example.com/data', {
  next: { revalidate: 3600 } // 1 hour
});
```

### Tag-Based Revalidation
```typescript
// Fetch with tag
const posts = await fetch('https://api.example.com/posts', {
  next: { tags: ['posts'] }
});

// Revalidate by tag
import { revalidateTag } from 'next/cache';
revalidateTag('posts');
```

### On-Demand Revalidation
```typescript
import { revalidatePath } from 'next/cache';
revalidatePath('/posts');
```

## Route File Conventions

```
app/
  page.tsx          → /
  about/page.tsx    → /about
  blog/[slug]/page.tsx → /blog/[slug]
  (marketing)/about/page.tsx → /about (route group)
```

### Dynamic Segments
```
[id]           → Single dynamic segment
[...slug]       → Catch-all
[[...slug]]    → Optional catch-all
```

### Route Groups
```
(marketing)/about/page.tsx  → /about (parentheses not in URL)
```

### Parallel Routes
```
app/
  layout.tsx
  @analytics/
    page.tsx    → Analytics slot
```

## Navigation Patterns

### Client-Side
```typescript
'use client';
import { useRouter, usePathname } from 'next/navigation';

const router = useRouter();
router.push('/about');
```

### Server-Side
```typescript
import { redirect } from 'next/navigation';

export default async function Page() {
  const user = await getUser();
  if (!user) redirect('/login');
  return <div>Content</div>;
}
```

## Error Handling

```typescript
// app/error.tsx
'use client';
export default function Error({
  error,
  reset
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>Error: {error.message}</h2>
      <button onClick={reset}>Try again</button>
    </div>
  );
}

// app/not-found.tsx
import { notFound } from 'next/navigation';

export default async function Post({
  params
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params;
  const post = await getPost(id);
  if (!post) notFound();
  return <article>{post.content}</article>;
}
```

## Metadata & SEO

```typescript
import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Page Title',
  description: 'Description',
  openGraph: {
    title: 'OG Title',
    images: ['/og-image.jpg'],
  },
};

// Dynamic
export async function generateMetadata({
  params
}: {
  params: Promise<{ id: string }>
}): Promise<Metadata> {
  const { id } = await params;
  const post = await getPost(id);
  return { title: post.title };
}
```

## Performance Optimization

### Image
```typescript
import Image from 'next/image';

<Image src="/photo.jpg" alt="Photo" width={800} height={600} priority />
```

### Font
```typescript
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';

const inter = Inter({ subsets: ['latin'], variable: '--font-inter' });

export default function Layout({ children }: { children: ReactNode }) {
  return <html className={inter.variable}><body>{children}</body></html>;
}
```

### Script
```typescript
import Script from 'next/script';

<Script src="https://example.com/script.js" strategy="afterInteractive" />
```

## Middleware

```typescript
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token');
  
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

export const config = { matcher: '/dashboard/:path*' };
```

## Key Decisions

1. **App Router or Pages?** → App Router for new projects
2. **Server or Client?** → Server by default, Client when needed
3. **Static or Dynamic?** → Static for performance, Dynamic for fresh data
4. **Time or Tag revalidation?** → Time for predictable, Tag for user-generated
5. **Link or router.push?** → Link for navigation, router.push for programmatic
