Next.js adds the pieces React alone doesn't ship with — routing, server-side rendering, and a build system — as an opinionated, batteries-included layer.
With the App Router, the folder structure under app/ is the routing table — no separate route config file to maintain.
app/
page.js → /
about/page.js → /about
blog/[slug]/page.js → /blog/:slug
Square brackets mark a dynamic segment, accessible inside the page as a prop:
export default function BlogPost({ params }) {
return <h1>Post: {params.slug}</h1>
}
In the App Router, every component is a Server Component unless you say otherwise — it renders on the server, ships zero JavaScript for that component to the browser, and can talk directly to a database or file system without an API layer in between.
export default async function Page() {
const posts = await db.posts.findMany()
return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>
}
Add 'use client' at the top of a file only when you need interactivity — state, event handlers, browser APIs — since that opts the component into shipping JS to the browser.
Because Server Components run on the server, fetch() or a direct database call inside the component itself replaces most of what a client-side data-fetching library would otherwise be doing — there's less client-side plumbing to write than in a plain React SPA.
Comments