File-Based Routing
⏱ 12 min read read
File-Based Routing Rules:
app/page.tsx → /
app/about/page.tsx → /about
app/blog/page.tsx → /blog
app/blog/[slug]/page.tsx → /blog/:slug (dynamic)
app/shop/[...slug]/page.tsx → /shop/a/b/c (catch-all)
app/(auth)/login/page.tsx → /login (group --- (auth) not in URL)
Special Files:
page.tsx ← the route UI (makes a URL segment public)
layout.tsx ← wraps page and all children; persists across navigations
loading.tsx ← automatic loading UI (Suspense boundary)
error.tsx ← automatic error boundary for the segment
not-found.tsx ← rendered when notFound() is called
route.ts ← API endpoint (no UI)
Dynamic Routes:
// app/blog/[slug]/page.tsx
// Receives { params: { slug: string } }
export default function BlogPost({
params,
}: {
params: { slug: string };
}) {
return <h1>Post: {params.slug}</h1>;
}
Layouts --- Persist Across Navigation:
Layouts wrap pages and do NOT re-render when navigating between child
pages. Perfect for nav bars, sidebars, and shells.
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="dashboard">
<Sidebar />
<main>{children}</main>
</div>
);
}
Route Groups (auth) --- wrap routes in a folder with () to share a
layout
without adding the folder name to the URL.
app/(marketing)/page.tsx → /
app/(marketing)/about/page.tsx → /about
app/(auth)/login/page.tsx → /login
Both groups can have their own layout.tsx.
app/page.tsx → /
app/about/page.tsx → /about
app/blog/page.tsx → /blog
app/blog/[slug]/page.tsx → /blog/:slug (dynamic)
app/shop/[...slug]/page.tsx → /shop/a/b/c (catch-all)
app/(auth)/login/page.tsx → /login (group --- (auth) not in URL)
Special Files:
page.tsx ← the route UI (makes a URL segment public)
layout.tsx ← wraps page and all children; persists across navigations
loading.tsx ← automatic loading UI (Suspense boundary)
error.tsx ← automatic error boundary for the segment
not-found.tsx ← rendered when notFound() is called
route.ts ← API endpoint (no UI)
Dynamic Routes:
// app/blog/[slug]/page.tsx
// Receives { params: { slug: string } }
export default function BlogPost({
params,
}: {
params: { slug: string };
}) {
return <h1>Post: {params.slug}</h1>;
}
Layouts --- Persist Across Navigation:
Layouts wrap pages and do NOT re-render when navigating between child
pages. Perfect for nav bars, sidebars, and shells.
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="dashboard">
<Sidebar />
<main>{children}</main>
</div>
);
}
Route Groups (auth) --- wrap routes in a folder with () to share a
layout
without adding the folder name to the URL.
app/(marketing)/page.tsx → /
app/(marketing)/about/page.tsx → /about
app/(auth)/login/page.tsx → /login
Both groups can have their own layout.tsx.
Log in to track your progress and earn badges as you complete lessons.
Log In to Track Progress