Dynamic routes
A folder name in square brackets becomes a route parameter.
| Folder | Matches | params |
|---|---|---|
app/blog/[slug] | /blog/hello | { slug: 'hello' } |
app/docs/[...path] | /docs/a/b | { path: ['a', 'b'] } |
app/shop/[[...path]] | /shop and /shop/a | { path: undefined } or { path: ['a'] } |
params is a Promise
Since Next.js 15 params and searchParams are Promises and have to be awaited:
tsx
// app/blog/[slug]/page.tsx
export default async function Page({ params }: PageProps<'/blog/[slug]'>) {
const { slug } = await params;
const post = await getPost(slug);
if (!post) notFound();
return <Article post={post} />;
}generateStaticParams
It returns the list of params to prerender at build time, so these pages are served as static HTML:
tsx
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((p) => ({ slug: p.slug }));
}Params that are not in the list are rendered on the first request and can be cached after that. To return 404 for them instead, export dynamicParams = false.
PageProps<'/blog/[slug]'>is a globally available type helper generated by Next.js, soparamsis typed from the route itself.
updated
did you know it?