Dynamic Routes

This list page is static. Each post below is served by ONE file — app/blog/[slug]/page.tsx — parameterized by whichever slug you click.

The list, generated from data

In a real app these titles would come from a CMS or database. generateStaticParams() (see the [slug] page) tells Next.js which slugs exist so it can pre-render every post at build time.
export default function BlogIndexPage() {
  const posts = getAllPosts()
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.slug}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}