> **TL;DR.** Next.js 16 ships with the App Router as the only supported model, React 19 as the baseline, and first-class Partial Prerendering that eliminates most SSR vs. static tradeoffs. If you're starting a new project in 2026, this is the stack. If you're on Pages Router, the migration path is well-documented and worth doing.
---
What Actually Changed in Next.js 16
The headline feature is **Partial Prerendering (PPR) going stable**. PPR lets a single route serve a static shell instantly from the CDN while streaming dynamic slots in the same HTTP response — no per-route `export const dynamic = 'force-dynamic'` juggling.
Key changes from Next.js 14/15:
- **Pages Router is deprecated** — still works but receives no new features
- **React 19 required** — `use()`, `useOptimistic()`, and the Actions model are first-class
- **Turbopack is the default bundler** — `next dev` uses Turbopack; `next build` does too (stable since 15.3)
- **`after()` API stable** — run work after a response has flushed (logging, analytics, cache invalidation) without blocking the user
- **`forbidden()` and `unauthorized()` APIs** — throw these from Server Components to render dedicated error boundaries instead of generic 500s
- **Node.js 20+ required** — drop Node 18 from your CI/CD
---
App Router Mental Model
The App Router uses the file system to declare rendering behavior, not runtime configuration.
**Directory conventions you must know:**
**Server vs. Client Components:**
- Everything is a Server Component by default. They run on the server, access databases directly, and never ship their source to the browser.
- Add `"use client"` at the top of a file when you need browser APIs, event handlers, or React state.
- The rule: push `"use client"` as far down the tree as possible. A page can be a Server Component while a single button inside it is a Client Component.
---
Data Fetching in 2026
Forget `getServerSideProps` and `getStaticProps` — those are Pages Router concepts.
**Fetch in Server Components:**
```ts
// app/products/page.tsx
async function ProductsPage() {
const products = await fetch('https://api.example.com/products', {
next: { revalidate: 3600 } // ISR: revalidate every hour
}).then(r => r.json())
return <ProductList products={products} />
}
```
**On-demand revalidation with Server Actions:**
```ts
'use server'
import { revalidatePath } from 'next/cache'
export async function publishPost(id: string) {
await db.posts.update(id, { published: true })
revalidatePath('/blog')
}
```
**When to use what:**
- Static data with periodic refresh → `fetch` + `next.revalidate`
- Data specific to the current user → `fetch` with `cache: 'no-store'` or `noStore()`
- Mutations → Server Actions with `revalidatePath` or `revalidateTag`
- Real-time → route handler + SSE, or a client-side WebSocket
---
Server Actions Replace Most API Routes
Server Actions let client components call server-side functions directly without writing a separate API endpoint.
```ts
// app/actions.ts
'use server'
export async function createComment(formData: FormData) {
const text = formData.get('text') as string
await db.comments.insert({ text, userId: await getAuthUser() })
revalidatePath('/posts')
}
```
```tsx
// Client component
<form action={createComment}>
<input name="text" />
<button type="submit">Post</button>
</form>
```
With React 19's `useActionState`, you get pending state and error handling with minimal boilerplate. API routes (`app/api/`) are still useful when you need an endpoint consumed by external clients, mobile apps, or third-party webhooks.
---
Partial Prerendering: The Architecture Shift
PPR is the biggest architectural change in Next.js 16 complete picture. It lets one route combine:
1. A **static shell** prerendered at build time and served from CDN edge
2. **Dynamic holes** that stream in after the shell is delivered
Enable it:
```ts
// next.config.ts
export default {
experimental: {
ppr: true,
},
}
```
Mark dynamic parts with `Suspense`:
```tsx
import { Suspense } from 'react'
import { UserCart } from './user-cart' // reads cookies → dynamic
export default function ShopPage() {
return (
<main>
<StaticHero /> {/* static, prerendered */}
<Suspense fallback={<CartSkeleton />}>
<UserCart /> {/* dynamic, streams in */}
</Suspense>
</main>
)
}
```
Without PPR, reading a cookie in any component on the page forces the entire route to be dynamic. PPR eliminates that penalty.
---
TypeScript and Config Setup
Next.js 16 ships with a typed config file by default:
```ts
// next.config.ts (not .js)
import type { NextConfig } from 'next'
const config: NextConfig = {
images: {
remotePatterns: [{ hostname: 'cdn.example.com' }],
},
experimental: {
ppr: true,
},
}
export default config
```
**Strict TypeScript setup worth enabling:**
```json
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"paths": {
"@/*": ["./src/*"]
}
}
}
```
`noUncheckedIndexedAccess` catches array index bugs that strict mode misses. Enable it on new projects; retrofit carefully on existing ones.
---
Performance Checklist
Before deploying to production, verify:
- `next build` output table shows no route unexpectedly large (>200KB first load JS)
- Dynamic imports (`next/dynamic`) used for heavy client components
- `next/image` wrapping every `<img>` — automatic WebP/AVIF conversion, lazy loading, CLS prevention
- `next/font` for all fonts — self-hosted, zero layout shift
- `Suspense` boundaries placed above any component that fetches data
- `generateStaticParams` used for dynamic routes with known IDs (PDPs, blog posts)
Run `npx @next/bundle-analyzer` to visualize what's in your bundles. The common offender: a charting library imported in a Server Component that should be client-only.
---
Deploying Next.js 16
**Vercel (zero config):**
```bash
vercel --prod
```
Vercel natively supports PPR, ISR, edge middleware, and Server Actions with no additional configuration.
**Self-hosted (Node.js server):**
```bash
next build
outputs .next/ folder
node server.js # or: next start
```
Self-hosting loses automatic edge cache invalidation — you need a CDN in front and manual purge calls. Vercel, Netlify, and Cloudflare Workers all support Next.js to varying degrees; check PPR support specifically if you use it.
**Docker:**
```dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
CMD ["node", "server.js"]
```
Enable `output: 'standalone'` in `next.config.ts` to get a minimal production bundle.
---
When to Use Next.js vs. Alternatives
Next.js 16 is the right choice when:
- You need a mix of static, ISR, and dynamic routes in one project
- Your team already knows React
- You're deploying to Vercel and want zero infra management
- You're building an AI-powered app where server-side API calls should never expose keys to the browser — relevant if you're following patterns from the [AI for Backend Developers guide](/en/rehberler/ai-backend-developers-2026)
Consider alternatives when:
- **Pure static site** — Astro is simpler and ships less JS
- **Full-stack Python/Go backend** — Next.js as a thin frontend calling your existing API is fine, but a dedicated Next.js full-stack might be overkill
- **Offline-first mobile** — React Native or a PWA wrapper
For [vibe coding e-commerce](/en/rehberler/vibe-coding-ecommerce-2026) projects, Next.js + Vercel is the dominant stack because PPR handles the static catalog / dynamic cart split out of the box.
---
Next Steps
The nextjs 16 complete stack pairs well with a few adjacent decisions:
- **AI integration:** Server Components make it trivial to call AI APIs server-side without exposing keys. See the [How to Start AI SaaS guide](/en/rehberler/how-to-start-ai-saas-2026) for patterns.
- **Internal tooling:** If you're building dashboards and admin panels, the [Vibe Coding for Internal Tools guide](/en/rehberler/vibe-coding-internal-tools-2026) covers auth, role-based access, and data table patterns.
- **Agent UIs:** Streaming Server Components pair naturally with LLM streaming responses. The [Vibe Coding for AI Agents guide](/en/rehberler/vibe-coding-ai-agents-2026) covers frontend patterns for agent applications.
Migrate from Pages Router incrementally: both routers coexist in one project, so you can move route by route rather than rewriting everything at once. Start with the routes that need PPR or Server Actions first — those see the most immediate benefit.