Modern Frontend with Next.js App Router
Next.js 13+ introduced the App Router, fundamentally changing how we think about routing and rendering in React applications. Server Components, streaming, and nested layouts are now first-class citizens.
Server Components by Default
In the App Router, every component is a Server Component unless you explicitly opt into client-side rendering with the 'use client' directive. This means your components run on the server, reducing the JavaScript bundle sent to the browser.
// This runs on the server - no JS sent to client
async function BlogList() {
const posts = await db.post.findMany();
return posts.map(post => <PostCard key={post.id} {...post} />);
}Streaming with Suspense
One of the most powerful features is streaming. You can show content progressively as it becomes available, rather than waiting for the entire page to load.
import { Suspense } from 'react';
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<StatsSkeleton />}>
<Stats />
</Suspense>
<Suspense fallback={<ChartSkeleton />}>
<RevenueChart />
</Suspense>
</div>
);
}Layouts and Templates
The App Router introduces shared layouts that persist across navigations. This means your sidebar or header doesn't re-render when navigating between pages.
When to Use Client Components
Not everything should be a Server Component. Use Client Components when you need interactivity (useState, useEffect, event handlers), browser APIs (localStorage, geolocation), or certain third-party libraries.
Key Takeaways
- Default to Server Components — they're faster and lighter
- Use Suspense boundaries for better UX
- Layouts persist — design your component tree accordingly
- The 'use client' boundary is your tool for interactivity