Next.js App Router represents a fundamental paradigm shift in how React applications handle data and rendering. This guide covers production-proven patterns.
Server Components: The Default
In the App Router, components are Server Components by default. They run on the server and ship zero JavaScript to the client. The implications are profound:
- Database queries happen directly in the component — no API routes needed.
- Sensitive operations (reading env vars, accessing private data) are naturally secure.
- The client bundle is dramatically smaller.
// app/dashboard/page.tsx — This runs ONLY on the server
import { db } from '@/lib/db';
export default async function DashboardPage() {
// Direct DB query, zero exposure to client
const metrics = await db.getMetrics();
return <Dashboard data={metrics} />;
}Streaming with Suspense
Streaming allows you to progressively render the page, showing a loading skeleton for expensive data fetches while faster content renders immediately:
import { Suspense } from 'react';
import { MetricsSkeleton } from './skeletons';
import Metrics from './Metrics'; // Async Server Component
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<MetricsSkeleton />}>
<Metrics />
</Suspense>
</div>
);
}Parallel Routes for Complex Dashboards
Parallel Routes allow you to render multiple pages in the same layout simultaneously:
app/
dashboard/
@analytics/ page.tsx
@sales/ page.tsx
layout.tsx (receives @analytics and @sales as props)The Data Mutation Pattern: Server Actions
Server Actions replace API routes for data mutations:
'use server';
export async function updateUserProfile(formData: FormData) {
const name = formData.get('name');
await db.users.update({ name }); // Direct DB call
revalidatePath('/profile');
}Conclusion: The App Router's Server Components, Streaming, and Server Actions form a cohesive model that significantly reduces client bundle size and improves performance.

