# Next.js Implementation Patterns

Production-ready patterns for common use cases.

## Authentication

### Server-Side Auth Check
```typescript
// app/dashboard/page.tsx
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

export default async function Dashboard() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
  
  if (!token) redirect('/login');
  
  const user = await getUser(token.value);
  return <div>Welcome {user.name}</div>;
}
```

### Middleware Auth
```typescript
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

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

export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*'],
};
```

## Data Fetching

### Parallel Data Fetching
```typescript
export default async function Dashboard() {
  const [user, posts, analytics] = await Promise.all([
    getUser(),
    getPosts(),
    getAnalytics(),
  ]);
  
  return (
    <div>
      <UserProfile user={user} />
      <PostsList posts={posts} />
      <Analytics data={analytics} />
    </div>
  );
}
```

### Streaming with Suspense
```typescript
import { Suspense } from 'react';

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

## Form Handling

### Server Actions
```typescript
// app/actions.ts
'use server';
import { revalidatePath, redirect } from 'next/navigation';

export async function createPost(formData: FormData) {
  const title = formData.get('title');
  const post = await savePost({ title });
  
  revalidatePath('/posts');
  redirect(`/posts/${post.id}`);
}

// app/posts/create/page.tsx
import { createPost } from '../actions';

export default function CreatePost() {
  return (
    <form action={createPost}>
      <input name="title" />
      <button type="submit">Create</button>
    </form>
  );
}
```

### Optimistic Updates
```typescript
'use client';
import { useTransition, useState } from 'react';

export default function LikeButton({
  postId,
  initialCount
}: {
  postId: string;
  initialCount: number;
}) {
  const [isPending, startTransition] = useTransition();
  const [count, setCount] = useState<number>(initialCount);

  function handleLike() {
    startTransition(async () => {
      setCount(prev => prev + 1); // Optimistic
      await likePost(postId);
    });
  }

  return (
    <button onClick={handleLike} disabled={isPending}>
      Like ({count})
    </button>
  );
}
```

## Search & Filters

### URL Search Params
```typescript
'use client';
import { useRouter, useSearchParams } from 'next/navigation';

export default function SearchBar() {
  const router = useRouter();
  const searchParams = useSearchParams();
  
  function handleSearch(query: string) {
    const params = new URLSearchParams(searchParams.toString());
    params.set('q', query);
    router.push(`/search?${params.toString()}`);
  }
  
  return (
    <input
      onChange={(e) => handleSearch(e.target.value)}
      defaultValue={searchParams.get('q') || ''}
    />
  );
}
```

### Server-Side Search
```typescript
interface SearchResult {
  id: string;
  title: string;
}

export default async function SearchPage({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>;
}) {
  const { q } = await searchParams;
  const results: SearchResult[] = q ? await searchItems(q) : [];

  return <SearchResults results={results} />;
}
```

## Caching & Revalidation

### On-Demand Revalidation
```typescript
// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const { secret, path } = await request.json();
  
  if (secret !== process.env.REVALIDATE_SECRET) {
    return NextResponse.json({ error: 'Invalid' }, { status: 401 });
  }
  
  revalidatePath(path);
  return NextResponse.json({ revalidated: true });
}
```

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

// Revalidate in Server Action
'use server';
import { revalidateTag } from 'next/cache';

export async function updatePost(postId: string) {
  await savePost(postId);
  revalidateTag(`post-${postId}`);
}
```

## API Routes

### REST API
```typescript
// app/api/users/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  const user = await getUser(id);
  
  if (!user) {
    return NextResponse.json({ error: 'Not found' }, { status: 404 });
  }
  
  return NextResponse.json(user);
}

export async function PATCH(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  const body = await request.json();
  const user = await updateUser(id, body);
  return NextResponse.json(user);
}
```

## Image Patterns

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

<Image
  src="/photo.jpg"
  alt="Photo"
  width={800}
  height={600}
  sizes="(max-width: 768px) 100vw, 50vw"
  priority
/>
```

### Dynamic Images from API
```typescript
import Image from 'next/image';

export default async function PostImage({ imageUrl }: { imageUrl: string }) {
  return (
    <Image
      src={imageUrl}
      alt="Post image"
      width={800}
      height={600}
    />
  );
}
```

## Loading States

### Page-Level Loading
```typescript
// app/posts/loading.tsx
export default function Loading() {
  return <div className="animate-pulse">Loading...</div>;
}
```

### Skeleton Screens
```typescript
export default function PostSkeleton() {
  return (
    <div className="animate-pulse space-y-4">
      <div className="h-8 bg-gray-200 rounded w-3/4"></div>
      <div className="h-4 bg-gray-200 rounded w-full"></div>
    </div>
  );
}
```

## Error Boundaries

```typescript
// app/error.tsx
'use client';
import { useEffect } from 'react';

export default function Error({
  error,
  reset
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    console.error('Error:', error);
  }, [error]);

  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={reset}>Try again</button>
    </div>
  );
}
```
