Skip to content
Kamal Benaouija

Search Kamal Benaouija's site

All articles
ProgrammingNext.jsReactWeb Development

Next.js 15 App Router: The Notes I Wish I Had on Day One

A practical, opinionated tour of Server Components, data fetching and rendering modes in the App Router.

KB

Kamal Benaouija

June 10, 2026

2 min read

I rebuilt my own site on Next.js 15's App Router while writing this, so these notes are fresh — not theoretical.

Server Components Are the Default, and That's the Point

Every component in app/ is a Server Component unless you opt into "use client". That single default changes how you should think about data fetching entirely.

// app/projects/page.tsx — this runs on the server, no client JS shipped for this logic
import { getAllProjects } from "@/lib/projects";
 
export default function ProjectsPage() {
  const projects = getAllProjects();
  return <ProjectGrid projects={projects} />;
}

No useEffect, no loading spinner, no client-side waterfall. The data is just... there, before the HTML ever reaches the browser.

When You Actually Need "use client"

Reach for a Client Component only when you need:

  • Interactivity (onClick, onChange, state)
  • Browser-only APIs (window, localStorage)
  • React hooks like useState or useEffect

Everything else — layout, data fetching, static content — should stay a Server Component. Push "use client" as far down the tree as possible.

Rendering Modes, Simplified

ModeWhen it runsUse for
Static (default)Build timePages with no per-request data
DynamicPer requestPages using cookies, headers, or no-store fetches
StreamingPer request, incrementallyPages with slow, non-critical data

Next.js infers the mode automatically based on what your code does — no explicit config needed for most cases.

Metadata Without the Boilerplate

The built-in Metadata API replaces manual <head> management entirely:

export async function generateMetadata({ params }) {
  const post = await getPostBySlug(params.slug);
  return {
    title: post.title,
    description: post.description,
  };
}

Combined with app/sitemap.ts-style generation and JSON-LD, this alone removes the need for most third-party SEO libraries in the App Router.

My One Piece of Advice

Resist the urge to make everything a Client Component "just in case." Every unnecessary "use client" boundary is JavaScript your visitors have to download and execute for no reason. Default to the server; earn your way to the client.

Share