Next.js Route Groups: Organize Without URLs
In the App Router, folders normally become URL segments. But what if you want to organize your code into logical groups without those folders appearing in the URL? That's where route groups come in. A route group is a folder wrapped in parentheses—(groupName)—that organizes routes but doesn't add to the URL path. This feature enables clean code organization, multiple root layouts, and complex app architectures without URL clutter.
What Are Route Groups?
A route group is a folder whose name is wrapped in parentheses, like (auth) or (dashboard). Next.js treats it as a logical container for organizing code but completely ignores it when generating URLs. A file at app/(auth)/login/page.tsx becomes /login, not /(auth)/login. The parentheses are purely for developer organization.
This is powerful for several reasons:
- Organize related routes together without changing their URLs.
- Create multiple root layouts in a single app—different sections can have entirely different UI shells.
- Extract shared logic for a group of routes (like authentication or admin features) without nesting them under a prefix.
Syntax and Naming
To create a route group, wrap the folder name in parentheses:
app/
├── (auth)/ # Route group (not in URL)
│ ├── login/
│ │ └── page.tsx # /login
│ ├── signup/
│ │ └── page.tsx # /signup
│ └── reset/
│ └── page.tsx # /reset
├── (marketing)/ # Another route group
│ ├── page.tsx # /
│ └── features/
│ └── page.tsx # /features
└── page.tsx # This is now unreachable; see note below
Files in (auth) become /login, /signup, /reset—no auth in the path. Files in (marketing) become /, /features, and so on. Route groups don't affect the URL; they're purely organizational.
Important: URL Collision and Page Routing
When you use multiple route groups at the root level, be careful about URL collisions. A file at app/(auth)/page.tsx and app/(marketing)/page.tsx both claim the / route. Next.js will error. At the root level, only one page.tsx or set of routes should exist across all groups. However, for sub-routes, conflicts are fine: (auth)/login and (marketing)/login can coexist (both /login), though this is confusing and usually avoided.
Use Case 1: Organizing Authentication Routes
Group all login, signup, and password reset pages together without a /auth prefix:
app/
├── (auth)/
│ ├── layout.tsx
│ ├── login/
│ │ └── page.tsx # /login
│ ├── signup/
│ │ └── page.tsx # /signup
│ └── reset-password/
│ └── page.tsx # /reset-password
└── page.tsx # / (public home)
The (auth) group keeps these routes together in your codebase but doesn't add /auth/ to the URLs.
// app/(auth)/layout.tsx
export default function AuthLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex items-center justify-center min-h-screen bg-gradient-to-r from-blue-500 to-purple-600">
<div className="bg-white p-8 rounded-lg shadow-lg">{children}</div>
</div>
);
}
// app/(auth)/login/page.tsx
export default function LoginPage() {
return (
<div>
<h1 className="text-2xl font-bold mb-4">Login</h1>
<form className="space-y-4">
<input
type="email"
placeholder="Email"
className="w-full px-4 py-2 border rounded"
/>
<input
type="password"
placeholder="Password"
className="w-full px-4 py-2 border rounded"
/>
<button className="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700">
Login
</button>
</form>
<p className="mt-4 text-center text-sm">
No account?{" "}
<a href="/signup" className="text-blue-600 hover:underline">
Sign up
</a>
</p>
</div>
);
}
Now users visit /login, /signup, /reset-password—clean URLs with organized code.
Use Case 2: Multiple Root Layouts
A powerful pattern is using route groups to create multiple, independent layout trees in a single app. For example, a site with a public marketing section and a logged-in dashboard—completely different UIs.
app/
├── (marketing)/
│ ├── layout.tsx # Public layout (header, footer)
│ ├── page.tsx # / (home)
│ ├── about/
│ │ └── page.tsx # /about
│ └── pricing/
│ └── page.tsx # /pricing
├── (dashboard)/
│ ├── layout.tsx # Dashboard layout (sidebar, top nav)
│ ├── page.tsx # /dashboard view (but actually / if at root)
│ ├── users/
│ │ └── page.tsx # /users
│ └── settings/
│ └── page.tsx # /settings
└── layout.tsx # Root layout (shared by both groups)
Wait—this setup has an issue. Both groups want to claim / and /users, etc. Here's a better structure: split by path prefix after all:
Actually, let me clarify. If you want truly independent UIs (like a public site and a private dashboard), you'd typically use a prefix:
app/
├── layout.tsx # Root (shared)
├── page.tsx # / (public home)
├── (marketing)/
│ ├── about/
│ │ └── page.tsx # /about
│ └── pricing/
│ └── page.tsx # /pricing
└── dashboard/
├── layout.tsx # Dashboard layout
├── page.tsx # /dashboard
├── users/
│ └── page.tsx # /dashboard/users
└── settings/
└── page.tsx # /dashboard/settings
However, you can use route groups to organize the (marketing) group's routes without a prefix:
app/
├── layout.tsx # Root
├── (marketing)/
│ ├── layout.tsx # Marketing-specific layout (optional)
│ ├── page.tsx # / (home)
│ ├── about/
│ │ └── page.tsx # /about
│ └── pricing/
│ └── page.tsx # /pricing
└── dashboard/
├── layout.tsx
├── page.tsx
├── users/
│ └── page.tsx
└── settings/
└── page.tsx
The (marketing) group keeps public routes organized without affecting URLs. The root layout wraps everything; optionally, add (marketing)/layout.tsx for section-specific styling.
Nesting Route Groups
You can nest route groups inside other folders (though this is rare):
app/
├── admin/
│ ├── (settings)/
│ │ ├── general/
│ │ │ └── page.tsx # /admin/general
│ │ └── users/
│ │ └── page.tsx # /admin/users
│ └── (analytics)/
│ ├── dashboard/
│ │ └── page.tsx # /admin/dashboard
│ └── reports/
│ └── page.tsx # /admin/reports
The (settings) and (analytics) groups organize admin routes logically without adding to URLs. /admin/general, /admin/users, etc., are clean and grouped in code.
Practical Example: Multi-Section App
Here's a realistic structure for a SaaS app:
app/
├── layout.tsx # Root (all pages)
├── (site)/
│ ├── page.tsx # / (home)
│ ├── pricing/page.tsx # /pricing
│ └── about/page.tsx # /about
├── (auth)/
│ ├── login/page.tsx # /login
│ ├── signup/page.tsx # /signup
│ └── reset-password/page.tsx # /reset-password
└── app/
├── layout.tsx # Dashboard layout
├── page.tsx # /app (dashboard home)
├── projects/
│ ├── page.tsx # /app/projects
│ └── [id]/page.tsx # /app/projects/:id
└── settings/
└── page.tsx # /app/settings
URLs: /, /pricing, /about, /login, /signup, /reset-password, /app, /app/projects, /app/projects/123, /app/settings.
Code organization: (site), (auth), and app groups keep routes separated without affecting URLs.
Key Takeaways
- Route groups use parentheses—
(groupName)—to organize code without changing URLs. - Syntax rule: folder name in parentheses is ignored in URL routing; only actual page/route files and non-grouped folders affect the path.
- Multiple root layouts are possible by using route groups at the root level, each with their own
layout.tsx. - URL collisions must be avoided at the same level—two
page.tsxfiles can't both claim the same route. - Nesting route groups keeps large apps organized logically without URL bloat.
Frequently Asked Questions
Can I have a route group at the root level and a non-grouped page.tsx at root?
No. If you use route groups like (auth) and (marketing), both containing routes meant for /, there's a conflict. Use non-grouped folders at the root level, or ensure route groups don't collide. A single page.tsx at app/page.tsx (root) plus groups like (marketing) for sub-routes works fine.
Do route groups affect performance?
No. Route groups are a development-time organizational tool. They're stripped during the build; at runtime, URLs are identical to a non-grouped structure. No performance difference.
Can I put a layout.tsx in a route group?
Yes. A route group can have its own layout.tsx, which applies only to routes within that group. For example, (auth)/layout.tsx wraps all (auth)/* pages. This layout is independent of layouts in other groups.
What's the difference between route groups and nested folders?
Nested folders (e.g., app/admin/users/page.tsx) create URL segments (/admin/users). Route groups (e.g., app/(admin)/users/page.tsx) don't affect the URL (/users). Use groups for organization, folders for URL structure.
Can I use special filenames (like error.tsx) in a route group?
Yes. (auth)/error.tsx is an error boundary for all (auth)/* routes. (auth)/loading.tsx is a Suspense placeholder. All special files work in route groups.
Further Reading
- Next.js Route Groups Documentation – official reference and examples.
- Next.js File Conventions – all special files and their scopes.
- App Router Best Practices – architectural patterns for scalable apps.