Mastering Dynamic Routes in Next.js: [id].js & App Router Guide (2025)

Himmat Regar Jul 14, 2025, 10:54 PM
nextjs
Views 128
Blog Thumbnail

Mastering Dynamic Routes in Next.js with [id].js (2025 Edition)

Dynamic routes let you map a single React page to many URLs that share the same “shape”—think /blog/first-post, /blog/second-post, or /users/alice. In Next .js, you create these flexible paths just by putting a segment in square brackets ([ ]) inside the file-system router. This guide walks through everything you need to know in 2025, covering both the classic Pages Router and the newer App Router introduced in v13+, with tips for pre-rendering, data fetching, SEO, and common gotchas.


1. Quick refresher: file-system routing

Next.js turns folders & files into URL segments automatically.
pages/about.js/about | pages/blog/first-post.js/blog/first-post
When you don’t know the segment name until runtime, you wrap it in brackets.


2. Dynamic routes in the Pages Router

What you do What it creates
pages/posts/[id].js Matches any /posts/{id} URL
 
// pages/posts/[id].js
import { useRouter } from 'next/router';

export default function Post() {
  const { query } = useRouter();          // { id: '123' }
  return <h1>Post {query.id}</h1>;
}

 

Pre-rendering with getStaticPaths + getStaticProps

  • If the list of paths is finite (e.g. blog posts), export getStaticPaths to tell Next-.js which IDs to pre-render at build time and use getStaticProps to fetch data for each. Next.js

  • fallback lets you choose what happens for paths not in that list (false, 'blocking', or true).

  • Because these are generated to plain HTML/JSON, they’re CDN-friendly and great for SEO.

Catch-all segments

  • [...slug].js captures /a/b/c as slug: ['a','b','c'].

  • [[...slug]].js does the same and matches the parent path (/). Next.js


3. Dynamic routes in the App Router (Next.js 13-15)

The App Router uses folders instead of files for segments:

app
└── blog
    └── [slug]          // folder = dynamic segment
        └── page.js
Inside page.js, the route params arrive as a params prop (server) or via useParams (client):
tsx
 
// app/blog/[slug]/page.tsx
export default async function Page({ params }: { params: { slug: string } }) {
  return <h1>Post {params.slug}</h1>;
}

 

Pre-rendering with generateStaticParams

generateStaticParams replaces getStaticPaths in the App Router. Return an array of param objects, and Next.js will statically build one page per item: Next.js

export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(r => r.json());
  return posts.map((p) => ({ slug: p.slug }));
}

 

  • For paths you don’t pre-generate, control runtime behavior with the dynamicParams route-segment option.

  • Catch-all ([...slug]) and optional catch-all ([[...slug]]) work the same here too. Next.js


4. Linking between dynamic pages

Whether you’re in pages/ or app/, use <Link> and provide the full href:

import Link from 'next/link';
<Link href={`/posts/${id}`}>Read more</Link>

 

Next.js automatically prefetches the code bundle for that route on hover/viewport, giving near-instant navigation.


5. API routes with dynamic parameters

Dynamic file names work in pages/api/ (Pages Router) and app/api/ (App Router route handlers):

// app/api/posts/[postId]/route.js   (App Router, Node.js context)
export async function GET(request, { params }) {
  return Response.json({ id: params.postId });
}

 

In the Pages Router you’d create pages/api/posts/[postId].js and export default functions for the HTTP verbs.


6. SEO & performance checklist

  1. Prefer static generation (getStaticPaths / generateStaticParams) whenever the data can be cached publicly.

  2. When data is user-specific or changes often, use Server-Side Rendering (getServerSideProps) or dynamic = 'force-dynamic'` in App Router.

  3. Don’t forget to set canonical URLs and meta tags—dynamic routes are still SSR pages, so you can compute SEO metadata on the server.


7. Common pitfalls & debugging tips

Issue Fix
Page shows as 404 during next build Make sure the [id].js file exports getStaticPaths when using SSG.
“Router query is empty on first render” Remember that on the very first client render during static generation, query params might be undefined—guard against it.
Dynamic param undefined in App Router Confirm that the folder is named [param], not (param) (parentheses create a route group).
ISR paths not updating Return empty array or set revalidate/dynamicParams so Next.js can rebuild paths at runtime.

8. Conclusion

With just a pair of square brackets, you unlock powerful, SEO-friendly routing that scales from ten pages to ten million. Use [id].js (Pages Router) or [id]/page.js (App Router) for the basic pattern, sprinkle in getStaticPaths or generateStaticParams to pre-render, and you’re production-ready. Happy routing! 🚀

FAQs: Dynamic Routes in Next .js ([id].js & App Router folders)

# Question Short Answer
1 What’s the difference between dynamic routes in the Pages Router and the App Router? In Pages, you create a file like pages/posts/[id].js; in App, you create a folder named [id] with page.js inside. Data-fetching helpers change from getStaticPaths/Props (Pages) to generateStaticParams & segment options (App).
2 Do I always need getStaticPaths() / generateStaticParams()? Only if you want static generation (SSG/ISR). If you prefer on-demand rendering (SSR) or the list of possible paths is huge/unknown, skip them and set the route to be dynamic at runtime (getServerSideProps in Pages; dynamic = 'force-dynamic' in App).
3 How do optional segments work—what’s [[...slug]] for? [[...slug]].js (Pages) or [[...slug]]/page.js (App) matches zero or more segments, so both /blog and /blog/a/b hit the same page. Without the double brackets, at least one segment is required.
4 Can I have multiple dynamic segments? Yes. Example: pages/users/[userId]/posts/[postId].js/users/42/posts/7. In App Router: app/users/[userId]/posts/[postId]/page.js.
5 How do I link to a dynamic page? Use <Link href={/posts/${id}}>…</Link> (both routers). You can pass objects ({ pathname:'/posts/[id]', query:{ id } }) if the route has search params too.
6 Why do I see an empty router.query on first render? In statically generated Pages routes, the initial HTML is rendered without JS, so router.query is undefined until hydration. Guard for it (if (!id) return null).
7 What does fallback: 'blocking' do? During SSG (build), paths not returned by getStaticPaths render at request time on the server once, then get cached. Users wait (“blocking”) for the HTML.
8 How do I revalidate stale static pages? Pages Router: return { revalidate: 60 } from getStaticProps. App Router: export revalidate = 60 or use fetch(url, { next:{ revalidate:60 }}).
9 Can dynamic API routes use the same pattern? Absolutely. Example (Pages): pages/api/posts/[id].js. App Router: app/api/posts/[id]/route.ts.
10 Will catch-all routes hurt SEO? Not if you pre-render or set suitable robots/canonical tags. Each real URL should still output unique meta tags and canonical hrefs.
11 How do I generate a sitemap for dynamic pages? Use getStaticPaths / generateStaticParams inside a script or API route to list all slugs, then emit XML. For very large sets, stream the sitemap or split it per 50 k URLs.
12 Any common mistakes to avoid? ✓ Forgetting to export getStaticPaths → build-time 404. ✓ Using (group) folders instead of [segment] in App. ✓ Hard-coding <a href> instead of <Link>. ✓ Not handling undefined params on first client render.

 

Comments

Please login to leave a comment.

No comments yet.

Related Posts

nextjs-explained-beginners-guide-2025
669 viewsnextjs
Himmat Regar Jun 27, 2025, 10:12 AM

Next.js Explained: A 2025 Beginner’s Guide to the React...

nextjs-incremental-static-regeneration-isr-guide
660 viewsnextjs
Himmat Regar Jun 29, 2025, 5:18 PM

Incremental Static Regeneration (ISR) Explained with Ex...

nextjs-markdown-blog-tutorial
732 viewsnextjs
Himmat Regar Jun 27, 2025, 10:18 AM

How to Build Your First Blog Using Next.js and Markdown

nextjs-vs-react-differences
691 viewsnextjs
Himmat Regar Jun 27, 2025, 11:09 AM

Next.js vs React: What’s the Difference and When to Use...

nextjs-file-based-routing-guide
712 viewsnextjs
Himmat Regar Jun 27, 2025, 11:23 AM

Understanding File-Based Routing in Next.js

nextjs-api-routes-backend-functionality
610 viewsnextjs
Himmat Regar Jun 29, 2025, 5:03 PM

How to Use API Routes in Next.js for Backend Functional...

image-optimization-nextjs-everything-you-should-know
642 viewsnextjs
Himmat Regar Jun 29, 2025, 5:20 PM

Image Optimization in Next.js: Everything You Should Kn...

multi-language-website-nextjs-i18n
486 viewsnextjs
Himmat Regar Jun 30, 2025, 5:14 PM

Building a Multi-Language Website with Next.js 15 & Mod...

nextjs-tailwind-css-perfect-ui-pairing
488 viewsnextjs
Himmat Regar Jun 30, 2025, 5:25 PM

Next.js 15 + Tailwind CSS 4: The Perfect UI Pairing

why-every-developer-should-learn-typescript-in-2025
387 viewsnextjs
Himmat Regar Jul 3, 2025, 5:56 PM

Why Every Developer Should Learn TypeScript in 2025