Dynamic Routes
Dynamic segments [param] for parameterized URLs like /blog/:slug and /users/:id.
Overview
Dynamic routes use [param] syntax to match variable segments. Each folder or file named [param] creates a URL that accepts any value for that segment and provides it via useParams().
| Pattern | Example URL | Creates URL? |
|---|---|---|
| [slug] | /blog/hello-world | Yes - dynamic creates URL |
| [id] | /users/123 | Yes - dynamic creates URL |
| [category]/[slug] | /blog/tech/hello-world | Yes - multiple dynamic creates URL |
useParams() is auto-imported - no import needed. Param names must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.Dynamic Segments
Wrap folder or file name in brackets [name]. Creates URL for any value.
export default function BlogPost() {
const { slug } = useParams<{ slug: string }>()
return <h1>Post: {slug}</h1>
}export default function UserProfile() {
const { id } = useParams<{ id: string }>()
const [user, setUser] = useState<{ name: string } | null>(null)
useEffect(() => {
fetchUser(id!).then(setUser)
}, [id])
if (!user) return null
return <h1>{user.name}</h1>
}Multiple Parameters
Multiple dynamic segments in one route. Each creates a URL part and becomes a property in useParams().
export default function BlogPost() {
const { category, slug } = useParams<{
category: string
slug: string
}>()
return (
<div>
<p>Category: {category}</p>
<h1>Post: {slug}</h1>
</div>
)
}| URL | params | Creates URL? |
|---|---|---|
| /blog/tech/hello-world | { category: "tech", slug: "hello-world" } | Yes |
| /blog/lifestyle/travel | { category: "lifestyle", slug: "travel" } | Yes |
Dynamic Segments in Layouts
Layouts can access dynamic params via useParams(). The layout itself does not create a URL.
export default function BlogLayout({
children,
}: {
children: React.ReactNode
}) {
const { slug } = useParams<{ slug: string }>()
return (
<div>
<header>
<h2>Post: {slug}</h2>
<Link to="/blog">Back to blog</Link>
</header>
<main>{children}</main>
</div>
)
}Flat File Dynamic Routes
Dynamic routes as flat files without folders. Each file creates a URL directly.
export default function BlogPost() {
const { slug } = useParams<{ slug: string }>()
return <h1>Post: {slug}</h1>
}Route Priority
Dynamic routes have lower priority than static routes. Static wins if both exist.
- Static routes -
/blog/featured- creates URL, highest priority - Dynamic segments -
[slug]→/blog/:slug- creates URL
| URL | Matched Route | Creates URL? |
|---|---|---|
| /blog/featured | featured/page.tsx - static | Yes |
| /blog/hello-world | [slug]/page.tsx - dynamic | Yes |
Complete Example
Dynamic routes only - [param] patterns that create URLs.
| Pattern | Example URL | Creates URL? |
|---|---|---|
| /blog/featured | /blog/featured | Yes - static |
| /blog/:slug | /blog/hello-world | Yes - dynamic creates URL |
| /blog/:category/:slug | /blog/tech/hello-world | Yes - multiple dynamic creates URL |
| /products/:id | /products/123 | Yes - flat file dynamic creates URL |
| /users/:userId/settings | /users/john/settings | Yes - nested dynamic creates URL |