App Router

File-based Routing

app/
├── page.js
├── about/
│   └── page.js
└── blog/
    ├── [slug]/
    │   └── page.js
    └── page.js
  • page.js: Define routes
  • Nested folders create nested routes
  • Dynamic segments with [paramName]

Layout and Templates

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
  • layout.js: Shared UI for multiple pages
  • template.js: Similar to layouts, but create a new instance on navigation

Server Components

async function getData() {
  const res = await fetch('https://api.example.com/data');
  return res.json();
}

export default async function Page() {
  const data = await getData();
  return <main>{/* Use data */}</main>;
}
  • Default in App Router
  • Can use async/await directly
  • No need for getServerSideProps or getStaticProps

Client Components

'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}
  • Add 'use client'; directive at the top
  • Use for interactive components

Data Fetching

// In Server Components
const res = await fetch('https://api.example.com/data', { cache: 'force-cache' });
const res = await fetch('https://api.example.com/data', { cache: 'no-store' });
const res = await fetch('https://api.example.com/data', { next: { revalidate: 3600 } });
  • force-cache: Static data (default)
  • no-store: Dynamic data
  • revalidate: ISR (Incremental Static Regeneration)

Route Handlers

export async function GET(request) {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();
  return Response.json({ data });
}
  • Define API routes
  • Support for various HTTP methods