React

Route groups and nested layouts in the App Router

Folders in parentheses add no URL segment. They split layouts, and nested layouts stay mounted as you navigate. Rules and the traps.

Key points

  • A folder in parentheses is a route group: it does not appear in the URL.
  • Each group can carry its own root layout, with html and body.
  • A nested layout does not re-render when you navigate beneath it.
  • Two pages that resolve to the same URL stop the build.

A route group is a folder in parentheses that adds no URL segment: it gives two parts of the site different layouts and boundaries. A nested layout, by contrast, stays mounted as you navigate and does not re-render.

The structure

app/
  layout.tsx            # root: html, body, font
  (marketing)/
    layout.tsx          # public header
    page.tsx            # /
    pricing/page.tsx    # /pricing
  (app)/
    layout.tsx          # shell with sidebar
    dashboard/
      layout.tsx        # section title and tabs
      page.tsx          # /dashboard
      settings/page.tsx # /dashboard/settings
  (auth)/
    layout.tsx
    login/page.tsx      # /login

None of the three parenthesised folders appears in the URL: /pricing, /dashboard/settings and /login are the real addresses. The group only decides which layout wraps the page.

What a nested layout does

A layout receives children and stays mounted while navigation remains inside its segment. Moving from /dashboard to /dashboard/settings re-renders the page, not the shell: sidebar state survives.

// app/(app)/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  return (
    
      Dashboard
      {children}
    
  );
}

The layout does not receive searchParams: only the page gets them. If a filter lives in the URL and the shell needs it too, read the parameter in the page and pass it as a prop to a client component.

When the group earns its place

CaseGroupsWhy
Marketing site and product(marketing) and (app)Different header and navigation, one domain
Two root layouts(shop) and (docs)Each with its own html and body; moving between them reloads the page
Login and password reset(auth)Outside the shell, no sidebar

The mistakes you pay for

  • Two page.tsx files that resolve to the same URL: the build fails with a path conflict.
  • A layout that reads searchParams: it never receives them.
  • Session logic in the root layout: it costs a query on every request, even for pages that do not need it.
  • Groups created to group files: if the layouts are identical, the group does nothing.

Layouts are built from blocks, not whole pages: header, sidebar and footer land in your repository and follow your tree.

The general picture is in how to structure an App Router project; for parallel panels there is parallel routes and for waiting streaming and Suspense. The framework comparison is Astro vs Next.js.

npx next build

Known limitation: a route group changes neither the URL nor the file path. If two groups declare the same route, Next.js does not pick one: it stops the build.

Frequently asked questions

Does a route group change the URL?

No. The parentheses drop the folder from the path: pricing inside (marketing) stays /pricing.

Can I have two root layouts?

Yes, if each group has its own layout with html and body. Moving between groups reloads the whole page, so you lose client navigation.

Does the layout re-render on every navigation?

No, while you stay inside its segment. It changes when navigation leaves the layout, or when the shared data is invalidated on the server.

Where do I put the session check?

In the page, or in a server component the page calls. In the layout it costs a query even for routes that do not use it.

Do route groups work with parallel routes?

Yes, a slot can sit inside a group. The group picks the layout, the slot picks the panel: two different axes.