Course outline · 0% complete

0/29 lessons0%

Course overview →

[slug] routes and params

lesson 5-1 · ~10 min · 15/29

Quiz

Warm-up from 'Async server components': how does a server component wait for data?

One file, a thousand pages

A blog has one post layout but thousands of post URLs. You cannot create a folder per post. Instead you create one dynamic segment by wrapping a folder name in square brackets:

app/blog/[slug]/page.js

This single file serves /blog/hello-world, /blog/why-frameworks-win, and every other /blog/<anything> URL. The changing part is handed to your component as the params prop. This should feel familiar: in Backend with Node.js you wrote app.get("/posts/:id") and read req.params.id. Same idea, spelled with brackets instead of a colon.

app/blog/[slug]/page.js/blog/hello-world/blog/why-frameworks-win/blog/ship-itone fileevery matching URL
A dynamic segment: the single [slug] page file answers every /blog/<slug> URL, and params tells it which one was requested.

Reading params (await it!)

// app/blog/[slug]/page.js
export default async function PostPage({ params }) {
  const { slug } = await params;
  const res = await fetch(`https://api.example.com/posts/${slug}`);
  const post = await res.json();
  return <h1>{post.title}</h1>;
}

Decode it:

  • In current Next.js, params is a Promise, so you must await it before destructuring. Older tutorials show plain params.slug, which is the outdated API.
  • Visiting /blog/hello-world gives slug === "hello-world", which the component uses to fetch exactly that post.
  • One file, one fetch, infinitely many URLs.

Quiz

With app/shop/[productId]/page.js deployed, a user visits /shop/42. What does await params resolve to?

Code exercise · javascript

Blog posts need URL-safe slugs like the ones in [slug] routes. Write slugify(title): lowercase the title, remove every character that is not a lowercase letter, digit, or space, trim the ends, and turn each run of spaces into a single hyphen. Regex from Advanced JavaScript does the heavy lifting.