Skip to main content

Route groups in Next.js

Route groups in Next.js are folders wrapped in parentheses that organize your file structure without adding anything to the URL path.

Theory

TL;DR

  • Syntax: wrap a folder name in parentheses, like (marketing) or (auth)
  • The folder name never appears in the URL
  • Each group can have its own layout.tsx, loading.tsx, and error.tsx
  • Main use: separate layouts for public pages vs. authenticated pages
  • Two groups that produce the same URL path will conflict at build time

Quick example

app/ (marketing)/ about/page.tsx → /about pricing/page.tsx → /pricing (dashboard)/ settings/page.tsx → /settings analytics/page.tsx → /analytics

(marketing) and (dashboard) are stripped out by the router. The URLs are /about, /pricing, /settings, /analytics. The group names are gone.

How route groups differ from regular folders

A regular folder app/marketing/about/page.tsx produces /marketing/about. A route group app/(marketing)/about/page.tsx produces /about. That one difference unlocks a specific option: you can attach a separate layout.tsx to each group. So /about and /pricing share a layout with a public navbar and footer, while /settings and /analytics share a different layout with a sidebar and auth check. No extra segment in the URL for either.

How the router processes group names

Next.js reads the parentheses as a signal to exclude the folder from URL generation. The folder still exists on disk and can hold any special files (layout.tsx, loading.tsx, error.tsx, template.tsx). The router treats the group as a scope, not a segment.

When to use

  • Public site and authenticated app sections that need different layouts
  • Auth pages (/login, /register, /forgot) grouped under a shared wrapper
  • Admin panel that needs a completely different root layout with its own <html> and <body>
  • Large codebase organized by feature without adding URL segments

Common mistakes

Conflicting paths across groups:

// Both produce /about — Next.js errors at build time app/(marketing)/about/page.tsx app/(info)/about/page.tsx

The parentheses hide the folder name from the URL, not from the routing logic. I've seen this surface in code review when two developers add a page to different groups on the same day. Keep a flat list of all URL paths when planning group structure.

Assuming different group names prevent conflicts:

// Groups have different names, routes still clash app/(site)/contact/page.tsx → /contact app/(support)/contact/page.tsx → /contact ❌

Both still map to /contact. The group name is irrelevant to the final path.

Leaving pages outside all groups when using multiple root layouts:

If you split your app into (main) and (admin) with separate root layouts and delete app/layout.tsx, every top-level route must live inside one group. A page at app/about/page.tsx sitting outside both groups has no root layout to attach to.

Follow-up questions

Q: Can you nest route groups inside each other?
A: Yes. app/(marketing)/(campaigns)/summer/page.tsx is valid, and neither group name appears in the URL. Most teams only do this when a sub-section needs its own shared layout.

Q: Do route groups affect middleware matching?
A: No. Middleware matches against the actual URL path. A matcher for /dashboard/:path* works the same whether files live in app/dashboard/ or app/(auth)/dashboard/.

Q: What is the difference between a route group layout and a regular nested layout?
A: A regular nested layout adds a URL segment. A route group layout wraps routes the same way without adding anything to the URL. The wrapping behavior is identical.

Q: If two route groups both have a layout.tsx, do they stack?
A: They stack with the root app/layout.tsx at the top, then the group layout below it. Two group layouts from sibling groups do not interact with each other since a given route belongs to exactly one group.

Examples

Separate layouts for public and authenticated sections

A marketing site and a dashboard live in the same Next.js project but need different page chrome. Route groups handle this without any URL change.

tsx
// app/(marketing)/layout.tsx export default function MarketingLayout({ children, }: { children: React.ReactNode; }) { return ( <div> <PublicNavbar /> <main>{children}</main> <Footer /> </div> ); } // app/(dashboard)/layout.tsx export default function DashboardLayout({ children, }: { children: React.ReactNode; }) { return ( <div className="flex"> <Sidebar /> <main className="flex-1">{children}</main> </div> ); }

/about and /pricing get the navbar and footer. /settings and /analytics get the sidebar. No group name appears anywhere in the URL.

Multiple root layouts

When the admin panel needs a different <html> structure, different fonts, or stricter CSP rules, you can remove the top-level app/layout.tsx and give each group its own root layout.

app/ (main)/ layout.tsx ← root layout with analytics scripts, open graph tags page.tsx about/page.tsx (admin)/ layout.tsx ← stripped-down root layout, no third-party scripts dashboard/page.tsx users/page.tsx

Each layout.tsx here is a full document (<html>, <head>, <body>). Next.js renders each section with its own document shell. If you go this route, every page must live inside one of the groups. There is no fallback.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?