Hello! If you're exploring Next.js 15 and want to understand how different rendering mechanisms like SSR, SSG, ISR, CSR, and Server Components work within the App Router, this article will help you grasp them through practical examples. We'll walk through each mechanism using the app folder structure

In Next.js 15, the App Router (the app directory) is the primary way to build applications, replacing the older pages directory. It offers a flexible structure, defaults to Server Components, and integrates seamlessly with various rendering mechanisms. Each page.js file in the app directory represents a route.
Think of the App Router as a modern restaurant where you can order food in different ways:
Letโs dive into each mechanism with examples in the App Router.
SSG generates static HTML pages at build time, stored on the server or CDN for lightning-fast delivery.
Simple Example
Imagine a blog with posts like โHow to Make Bread.โ The content rarely changes, so you want pre-rendered HTML for speed and SEO.
Implementing SSG in App Router
In the App Router, create a page.js file and use fetch with default caching to generate static pages.
1// app/blog/page.js
2async function getPosts() {
3 const res = await fetch('https://api.example.com/posts', {
4 cache: 'force-cache', // Static generation, like getStaticProps
5 });
6 return res.json();
7}
8
9export default async function Blog() {
10 const posts = await getPosts();
11 return (
12 <ul>
13 {posts.map((post) => (
14 <li key={post.id}>{post.title}</li>
15 ))}
16 </ul>
17 );
18}1// app/blog/[id]/page.js
2async function getPost(id) {
3 const res = await fetch(`https://api.example.com/posts/${id}`, {
4 cache: 'force-cache',
5 });
6 return res.json();
7}
8
9export async function generateStaticParams() {
10 const res = await fetch('https://api.example.com/posts');
11 const posts = await res.json();
12 return posts.map((post) => ({ id: post.id.toString() }));
13}
14
15export default async function BlogPost({ params }) {
16 const post = await getPost(params.id);
17 return (
18 <div>
19 <h1>{post.title}</h1>
20 <p>{post.content}</p>
21 </div>
22 );
23}When to Use :
What is SSR?
SSR generates HTML on the server for each request, ensuring fresh content every time.
Simple Example
Picture a news website showing the latest articles. Each visit fetches new data and renders HTML on the server.
Implementing SSR in App Router
Use fetch with cache: 'no-store' to fetch fresh data per request.
1// app/news/page.js
2async function getNews() {
3 const res = await fetch('https://api.example.com/news', {
4 cache: 'no-store', // Like getServerSideProps
5 });
6 return res.json();
7}
8
9export default async function News() {
10 const articles = await getNews();
11 return (
12 <ul>
13 {articles.map((article) => (
14 <li key={article.id}>{article.title}</li>
15 ))}
16 </ul>
17 );
18}When to Use :
What is ISR?
ISR generates static pages at build time (like SSG) but allows periodic updates without rebuilding the entire app.
Simple Example
Consider an e-commerce product list where prices update hourly. ISR creates a static page but refreshes it every hour.
Implementing ISR in App Router
Use fetch with next: { revalidate } to specify the refresh interval.
1// app/products/page.js
2async function getProducts() {
3 const res = await fetch('https://api.example.com/products', {
4 next: { revalidate: 3600 }, // Refresh every 1 hour
5 });
6 return res.json();
7}
8
9export default async function Products() {
10 const products = await getProducts();
11 return (
12 <ul>
13 {products.map((product) => (
14 <li key={product.id}>{product.name}</li>
15 ))}
16 </ul>
17 );
18}When to Use :
What is CSR?
CSR loads minimal HTML, then uses JavaScript to fetch data and render content in the browser.
Simple Example
Imagine a dashboard showing orders after login. Data is fetched via JavaScript in the browser.
Implementing CSR in App Router
Use "use client" to mark a component as client-side, paired with useEffect for data fetching.
1// app/dashboard/page.js
2'use client';
3
4import { useState, useEffect } from 'react';
5
6export default function Dashboard() {
7 const [orders, setOrders] = useState([]);
8
9 useEffect(() => {
10 async function fetchOrders() {
11 const res = await fetch('https://api.example.com/orders');
12 const data = await res.json();
13 setOrders(data);
14 }
15 fetchOrders();
16 }, []);
17
18 return (
19 <ul>
20 {orders.map((order) => (
21 <li key={order.id}>{order.name}</li>
22 ))}
23 </ul>
24 );
25}When to Use :
What are Server Components?
Server Components, the default in App Router, render logic and HTML on the server, minimizing JavaScript sent to the client.
Simple Example
A product page fetches data from an API and renders HTML on the server, sending only the final result to the browser.
Implementing Server Components
All components in the app directory are Server Components unless marked "use client".
1// app/products/[id]/page.js
2async function getProduct(id) {
3 const res = await fetch(`https://api.example.com/products/${id}`);
4 return res.json();
5}
6
7export default async function ProductPage({ params }) {
8 const product = await getProduct(params.id);
9 return (
10 <div>
11 <h1>{product.name}</h1>
12 <p>{product.description}</p>
13 </div>
14 );
15}When to Use :
| Mechanism | Render Time | Speed | SEO | Use Case |
| SSG | Build time | Very fast | Great | Blogs, documentation |
| SSR | Request time | Slower | Good | News, dashboards |
| ISR | Build + Revalidate | Fast | Great | Products, periodic updates |
| CSR | Client-side | Slow | Poor | Interactive apps, no SEO |
| Server Components | Server-side | Fast | Great | Most pages |
With App Router in Next.js 15, you can flexibly choose the right rendering mechanism:
I hope these examples clarify how to implement rendering in the App Router.