Dynamic Routes in Next.js

File‑system routing in Next.js is appealing because it is direct. Static pages map cleanly to files. That works well until the application needs many pages that share the same template but differ by data.
Articles are the obvious example.
If a blog has hundreds of posts, we do not want:
pages/articles/post-one.tsx
pages/articles/post-two.tsx
pages/articles/post-three.tsxand so on forever.
That is where dynamic routes come in.
Dynamic Routes let One File Represent Many Paths
In the pages directory model used here, a bracketed file name lets one page handle a changing path segment:
pages/articles/[slug].tsxThat tells Next.js the path segment is dynamic.
So routes such as:
/articles/accessibility-basics/articles/seo-tips/articles/react-performance
can all be handled by the same page file.
Why This Matters
Without dynamic routing, content‑driven sites and applications become tedious to maintain quickly.
A single reusable page template is almost always what we want for:
- blog posts
- product detail pages
- category pages
- author pages
- user profiles
The route value changes, but the page structure often stays broadly the same.
Dynamic routes make that pattern feel native to the framework rather than bolted on afterwards.
Accessing the Route Parameter
A page in the pages directory can read the segment through useRouter from next/router:
import { useRouter } from 'next/router';
const ArticlePage = (): JSX.Element => {
const router = useRouter();
const { slug } = router.query;
return <h1>{slug}</h1>;
};
export default ArticlePage;For /articles/accessibility-basics, router.query.slug becomes accessibility-basics once the router has the query information. During automatic static prerendering, router.query can be empty; Next.js then updates it after hydration.
Before starting a client‑side request, check that slug has the expected string value. If the page needs request‑time data through getInitialProps, use the query passed in that context rather than assuming the browser router is ready during the initial render.
The File Name Becomes Part of the API
This is one of the elegant things about the system.
The file:
pages/articles/[slug].tsxis not just a storage location. It is also a declaration about the shape of the URLs that file can represent.
That keeps the route structure visible in the project tree, which is one of Next.js's nicer architectural traits.
Dynamic Routing is Especially Useful for CMS‑Driven Work
In headless CMS projects, content entries often have slugs already:
how-to-write-better-cssfront-end-performance-basicsunderstanding-react-hooks
Dynamic routes map naturally to that sort of data. One page file can receive a slug and then fetch the right content for that page.
That fit is one of the reasons Next.js became so attractive for content‑heavy React projects.
Nested Dynamic Routes are Possible Too
The pattern does not stop at one level.
For example:
pages/shop/[category]/[product].tsxcould represent URLs like:
/shop/books/clean-code/shop/gadgets/noise-cancelling-headphones
This gives the route tree a lot of expressive power without needing a separate central routing configuration.
Dynamic Routes are Still Page Routes, Not Arbitrary Filesystem Tricks
This point is worth holding on to.
The brackets are not a templating gimmick. They are how Next.js models route parameters in the file system. The page still behaves like an ordinary route entry point. It simply receives part of its URL as data.
That is a very clean way to express dynamic page structures.
Route Design Still Matters
The existence of dynamic routing does not make every URL scheme a good one.
Developers still need to think about:
- whether a slug is stable
- whether the path structure is meaningful
- whether IDs or slugs are more appropriate
- how readable the URL should be
Next.js makes dynamic routes easy to implement. It does not choose a good URL strategy for us.
One Route File Does Not Mean One Source of Data
It is also worth noting that a dynamic route page can decide how it finds its content.
The slug might be used to:
- query a CMS
- look up a local markdown file
- fetch an API result
- index into static JSON
The routing model stays the same regardless. That separation between URL shape and data source is a healthy one.
Dynamic Routes Reduce Duplication, but Not Responsibility
One page file can serve many URLs, which is great for reuse. Even so, the page still needs to handle real concerns such as:
- loading states
- missing content
- error cases
- SEO metadata
The route becomes more scalable because the template is reused. The rest of the page design still needs to be robust.
This is One of Next.js's Best Examples of Convention Paying Off
Creating a dynamic route in many systems would mean:
- define a path pattern
- register it with a router
- wire parameters into the page logic
In Next.js, the route pattern is expressed by naming the file correctly.
That is a very strong example of the framework letting structure stand in for configuration.
One Pattern Can Serve Many Pages
Dynamic routes in Next.js let one page file represent a whole family of related URLs, which makes content‑driven applications far more manageable. The bracket syntax is easy to read, easy to map to real site structures, and a natural fit for slug‑based content.
Once you have used it a few times, it becomes hard to imagine wanting more routing ceremony than that.
Postscript
May 2023: Next.js 13.4 made the App Router stable. The pages directory approach above is now called the Pages Router. For an App Router project, follow its dynamic route documentation; next/router belongs to the Pages Router.
September 2026: The Nando’s replatform is a later project example, rather than part of this July 2019 account. Its restaurant pages, recipes, products, and editorial content illustrate why a consistent family of route patterns matters. I have moved that retrospective reference here to keep the original article's chronology clear.