Routing and navigation

Build dynamic routes

Represent resource identifiers with dynamic segments and read the resolved parameters in an App Router page.

8 minute lesson

~~~

You do not create one file for every note. A dynamic segment such as [slug] captures that part of the URL and lets one page render many resources.

Create app/notes/[slug]/page.tsx. In current Next.js, params is asynchronous, so await it before reading the value. Validate the slug before using it in a query; a value coming from the URL is untrusted input.

Dynamic does not necessarily mean request-only. If the set of slugs is known at build time, generateStaticParams can return them for prerendering. Other values may still be rendered on demand unless the route configuration deliberately rejects them. Choose that behavior from the data lifecycle, not from the bracket syntax alone.

export default async function NotePage({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params
  return <p>Reading {slug}</p>
}

Open /notes/first-note and /notes/another-note. Decode and validate the slug before it reaches the data layer, return notFound() for a valid-looking slug with no record, and use generateStaticParams for two known notes. Compare the production build output with the on-demand case.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →