HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
6 Topics
Chapter•95 Minutes

App Router, Layouts, Navigation and Dynamic Routes

Master file-system routing, nested layouts, dynamic segments, route groups, parallel routes, intercepting routes, navigation, and URL design.

File-System Routing

Next.js App Router uses the directory structure to define URLs. A page.tsx file represents a publicly reachable page at the corresponding route.

For example, app/about/page.tsx maps to /about, while app/products/page.tsx maps to /products.

The important distinction is between folders and pages. A folder alone does not necessarily create a user-facing route. The route becomes renderable when the required special file exists.

Basic Routes
// app/page.tsx
export default function HomePage() {
  return <h1>Home</h1>;
}

// app/about/page.tsx
export default function AboutPage() {
  return <h1>About</h1>;
}
💡 The two files produce / and /about respectively.
Key Takeaways
  • Folders represent URL segments.
  • A page.tsx file makes a segment renderable as a page.
  • Route structure should reflect the information architecture of the application.

Dynamic Routes and Route Parameters

Dynamic segments allow one route to represent many resources. A folder such as [id] captures one URL segment.

For example, app/products/[id]/page.tsx can render /products/101, /products/202, and /products/abc.

Dynamic routes are especially useful for product pages, user profiles, blog posts, documentation pages, and database-backed resources.

Dynamic Product Route
type ProductPageProps = {
  params: Promise<{ id: string }>;
};

export default async function ProductPage({ params }: ProductPageProps) {
  const { id } = await params;

  return <h1>Product: {id}</h1>;
}
💡 The dynamic [id] segment provides the identifier captured from the URL.
Key Takeaways
  • Use [segment] for dynamic URL segments.
  • Dynamic parameters are useful for resource-oriented pages.
  • Validate dynamic parameters before using them in database queries.

Catch-All and Optional Catch-All Routes

Catch-all segments are useful when a route can contain an arbitrary number of path segments. [...slug] captures one or more segments, while [[...slug]] also allows the route to match without any segments.

Documentation systems are a classic example. A documentation page might be available at /docs/react/hooks/use-effect where the entire path after /docs is represented by a slug array.

Catch-All Documentation Route
export default async function DocsPage({
  params
}: {
  params: Promise<{ slug: string[] }>;
}) {
  const { slug } = await params;

  return <pre>{JSON.stringify(slug, null, 2)}</pre>;
}
💡 A URL such as /docs/react/hooks/use-effect produces an array containing each captured path segment.
Key Takeaways
  • Use [...slug] when at least one segment is required.
  • Use [[...slug]] when the entire segment is optional.
  • Catch-all routes are useful for documentation and hierarchical content.

Nested Layouts

Layouts allow shared UI to persist across navigation. A root layout can contain global HTML structure, while nested layouts can provide section-specific navigation or context.

Imagine an application containing public pages and an admin dashboard. The dashboard can have a nested layout containing its sidebar, while the public layout remains independent.

Layouts are not merely a way to avoid duplicated JSX. They define persistent UI boundaries and can improve the user experience during navigation.

Dashboard Layout
export default function DashboardLayout({
  children
}: {
  children: React.ReactNode;
}) {
  return (
    <div className='dashboard'>
      <aside>Dashboard Navigation</aside>
      <main>{children}</main>
    </div>
  );
}
💡 The dashboard layout wraps all pages nested beneath its directory.
Key Takeaways
  • Layouts are shared UI boundaries.
  • Nested layouts let different parts of an application have different shells.
  • Persistent navigation can live in a layout instead of being recreated in every page.

Route Groups

Route groups allow you to organize routes without adding the grouping folder to the URL. A folder such as (marketing) can group marketing pages while keeping the URLs clean.

This becomes valuable when different sections require different layouts. For example, (auth) can contain login and registration pages, while (dashboard) can contain authenticated application pages.

Route Group Structure
app/
  (marketing)/
    page.tsx
    pricing/
      page.tsx
  (auth)/
    login/
      page.tsx
    register/
      page.tsx
💡 The parentheses indicate organizational route groups. They do not become part of the public URL.
Key Takeaways
  • Route groups organize related routes without changing their URL.
  • They are useful for applying different layouts to different application areas.
  • Grouping is especially useful in large applications.

Navigation with Link and Router APIs

Next.js provides navigation primitives designed to work with its routing architecture. The Link component is preferred for normal application navigation because it can provide framework-aware navigation and prefetching.

Client components can use useRouter, usePathname, and useSearchParams when navigation depends on browser interaction.

Use declarative links whenever possible. Imperative router calls are better suited for actions such as redirecting after form submission.

Navigation Examples
import Link from 'next/link';

export default function Navigation() {
  return (
    <nav>
      <Link href='/'>Home</Link>
      <Link href='/products'>Products</Link>
    </nav>
  );
}
💡 Link provides framework-aware navigation and should normally be preferred over manually manipulating window.location.
Key Takeaways
  • Prefer Link for normal internal navigation.
  • Use router hooks for interactive client-side navigation.
  • Do not use window.location as the default navigation mechanism.