Dynamic Route
One page template serving thousands of URLs by reading the changing part of the address as a variable.
See it
What it is
A dynamic route is one template that answers for an unlimited number of URLs by treating part of the path as a variable. 'app/products/[slug]/page.tsx' in Next.js, '/products/:slug' in React Router: the router hands the matched value to the page, the page looks up that record, and one file quietly serves ten thousand product pages.
Variants worth knowing: catch-all segments ('[...path]' or '*') match any remaining depth, which is how docs sites handle arbitrary nesting, and optional catch-alls also match the bare parent. In frameworks that pre-render, you list the known values at build time (generateStaticParams, getStaticPaths) and then you have to say what happens to everything you did not list. Depending on the setting (dynamicParams in the App Router, fallback in getStaticPaths, prerender options in SvelteKit) an unlisted value is either rendered on demand and cached, or it simply 404s.
Two things bite. First, the param is user input: anyone can type '/products/does-not-exist' or something worse, so validate it and return a real 404 (call notFound(), do not render an empty page, which reads as a soft 404 to search engines). Second, per-page metadata is easy to forget. Every one of those URLs needs its own title, description, and OG image, otherwise your whole catalog shares one link preview.
Ask AI for it
Add a dynamic route at app/products/[slug]/page.tsx in this Next.js App Router app: read the slug param, fetch that product, and call notFound() when it does not exist so the URL returns a real 404. Pre-render the known products with generateStaticParams and set dynamicParams explicitly, saying in a comment whether an unlisted slug should render on demand or return 404. Add generateMetadata for a per-product title, description, and OG image, and add a catch-all route at app/docs/[...path]/page.tsx for arbitrarily nested documentation paths. Add a static app/products/compare/page.tsx too, and rely on the router ranking that static segment above the dynamic one.