Dynamic routes let a single file handle many URLs, such as every blog post or every product page, by capturing part of the URL as a parameter. This lesson covers creating, reading, and pre-rendering dynamic routes.
Creating a Dynamic Segment
Wrapping a folder name in square brackets, like [id], tells Next.js that segment of the URL is a variable rather than a fixed string. A single folder app/products/[id]/page.tsx then matches /products/1, /products/42, /products/anything — any value in that position.
Inside the page component, Next.js automatically provides the captured value through the params prop, keyed by whatever name you used inside the brackets.
[id] matches exactly one URL segment and delivers it as a string.
[...slug] matches one or more remaining segments and delivers them as a string array.
[[...slug]] behaves like [...slug] but also matches the parent path with zero segments.
Parameter names inside brackets become the exact key used on the params object.
Dynamic Routes Cheat Sheet
Segment types and what params looks like for each.
File Path
URL
params Value
app/posts/[id]/page.tsx
/posts/7
{ id: "7" }
app/shop/[...path]/page.tsx
/shop/shoes/nike
{ path: ["shoes", "nike"] }
app/docs/[[...path]]/page.tsx
/docs
{ path: undefined }
app/docs/[[...path]]/page.tsx
/docs/a/b
{ path: ["a", "b"] }
Pre-Rendering Dynamic Routes with generateStaticParams
By default, a dynamic route renders on demand for each request. Exporting an async generateStaticParams function tells Next.js which specific parameter values to pre-render into static HTML at build time, similar in spirit to getStaticPaths in the Pages Router.
Each object returned from generateStaticParams becomes one statically-generated page at build time.
Combining Multiple Dynamic Segments
A route can include more than one dynamic segment at different nesting levels. Each bracketed folder contributes its own key to the combined params object.
params delivers captured values into the page component automatically.
[...slug] captures multiple segments as an array; [[...slug]] makes that catch-all optional.
generateStaticParams pre-renders specific dynamic routes into static HTML at build time.
Route params always arrive as strings and may need explicit parsing (e.g. Number(params.id)).
Pro Tip
If a dynamic route's data rarely changes and the total number of possible values is small (like a fixed set of product categories), pre-render all of them with generateStaticParams — you get the performance of static HTML with none of the routing complexity of separate static files.
You can now build routes that respond to dynamic parameters. Next, learn how nested routes let you build multi-level URL structures with shared layouts.