Next.js 15 represents the most significant architectural shift in the framework's history. The App Router is now stable and production-ready, bringing React Server Components, a new caching model, and Partial Prerendering to the mainstream.
React Server Components by Default
In the App Router, every component is a Server Component by default. Server Components render on the server and send HTML to the client — no JavaScript bundle shipped for them. This dramatically reduces client-side JavaScript and improves Time to First Byte.
Add 'use client' at the top of a file to opt into client-side rendering for components that need interactivity, browser APIs, or React hooks.
The New File Conventions
- page.tsx — The UI for a route segment. Makes the route publicly accessible.
- layout.tsx — Shared UI that wraps child segments. Persists across navigations.
- loading.tsx — Instant loading UI shown while a segment loads (uses React Suspense).
- error.tsx — Error boundary UI for a segment.
- not-found.tsx — UI rendered when notFound() is called.
- route.ts — API endpoint (replaces pages/api).
The New Caching Model
Next.js 15 overhauled its caching behavior. The key change: fetch requests are no longer cached by default. In Next.js 13-14, all fetches were cached automatically — a source of much confusion. Now you opt into caching explicitly:
// Cached indefinitely (static)
fetch(url, { cache: 'force-cache' });
// Never cached (dynamic)
fetch(url, { cache: 'no-store' });
// Revalidated every 60 seconds (ISR)
fetch(url, { next: { revalidate: 60 } });
Partial Prerendering (PPR)
PPR is the most exciting new feature in Next.js 15. It allows a single page to combine static and dynamic content. The static shell is served instantly from the CDN; dynamic sections stream in as they resolve on the server. You get the performance of static sites with the freshness of server rendering — simultaneously.
Server Actions
Server Actions let you call server-side functions directly from client components — no API route required. They are ideal for form submissions and mutations:
'use server';
export async function submitForm(formData: FormData) {
const name = formData.get('name');
await db.insert({ name });
revalidatePath('/');
}
Migration from Pages Router
The Pages Router and App Router can coexist in the same project. Migrate incrementally: move one route at a time. Start with static pages, then tackle dynamic routes, then authenticated sections. The two routers are fully compatible during migration.
Conclusion
The Next.js 15 App Router is a fundamental rethinking of how web applications are built — not just a new folder structure. Invest time understanding Server Components and the caching model; they are the concepts that unlock the full performance potential of the new architecture.