One of the most common Next.js interview questions is:

Explain the routing system of the Next.js App Router. How do Layouts, Templates, and Route Groups differ, and how do you handle dynamic parameters?

The App Router introduced file-system based routing built on React Server Components. Understanding page layouts, navigation hierarchies, and rendering states is essential for building scalable applications.


1. App Router File Conventions#

Routes are defined by folders. A route is a nested folder structure leading to a leaf folder containing a special page file:

  • page.tsx: The unique UI of a route, making the path publicly accessible.
  • layout.tsx: Shared UI for a segment and its children. Layouts preserve state, remain interactive, and do not re-render when navigating between siblings.
  • template.tsx: Similar to layouts but creates a new instance for each child on navigation. State is reset, and effects run on every route change.
  • loading.tsx: An automatically wrapped React Suspense fallback UI for loading states.
  • error.tsx: An automatically wrapped React Error Boundary UI to catch runtime routing or data fetching crashes.
app/
 ├── layout.tsx         (Root Layout)
 ├── page.tsx           (Homepage: /)
 └── dashboard/
      ├── layout.tsx    (Dashboard Layout - wraps children)
      ├── loading.tsx   (Skeleton/Spinner UI)
      └── page.tsx      (Dashboard Page: /dashboard)

2. Layouts vs. Templates#

Interviewers frequently ask when to use template.tsx instead of layout.tsx:

Featurelayout.tsxtemplate.tsx
Component InstancePreserved across navigationRecreated on navigation
React StateMaintainedReset
useEffect HooksDo not re-fire on sibling navigateRe-fire on every navigation
Typical Use CasesPersistent headers, sidebars, context providersPage entry animations, analytics pageview tracking, forms reset

3. Dynamic Segments & Dynamic Routes#

When you don't know the segment names beforehand (e.g. blog posts, product IDs), you create a dynamic folder wrapped in square brackets: [slug].

A. Simple Dynamic Route (app/blog/[id]/page.tsx)#

Resolves to /blog/123, /blog/hello-world, etc. The parameter is passed to the page component:

TYPESCRIPT
type Props = {
  params: Promise<{ id: string }>;
};

export default async function BlogPost({ params }: Props) {
  const { id } = await params;
  return <h1>Blog Post ID: {id}</h1>;
}

B. Catch-All Segments (app/shop/[...slug]/page.tsx)#

Matches /shop/clothes, /shop/clothes/shirts/blue. The slug param is passed as an array: ['clothes', 'shirts', 'blue'].

C. Optional Catch-All (app/shop/[[...slug]]/page.tsx)#

Matches all routes above, plus /shop (without dynamic segments). The array parameter will be undefined on /shop.


4. Route Groups (groupname)#

Folder names wrapped in parentheses represent a Route Group: (marketing), (auth).

  • Route groups are omitted from the URL path structure.
  • They are used to organize files logically or to define nested layouts for specific groups of sub-pages without adding segment names to the paths.
app/
 ├── (auth)/
 │    ├── layout.tsx    (Auth Layout: e.g. login cards)
 │    ├── login/page.tsx   (Resolves to /login)
 │    └── register/page.tsx(Resolves to /register)

Key Takeaways#

  • File-based Routing: App Router uses nested folders to map URLs; special file names declare UI behaviors.
  • Layout Persistence: Layouts do not re-render during nested navigation, preserving client state like scrolling position.
  • Template Re-mounts: Use templates when you need custom CSS animations or page view analytics tracking triggered on every single route change.
  • Dynamic Segment destruct: Always define param models correctly and resolve dynamic params asynchronously if using newer Next.js patterns.