Next.js Route Groups — Organize Without URL
Advertisement
Next.js Route Groups — Organize Without URL
Route groups enable logical organization of your codebase without changing public URLs, making large applications more maintainable.
- Next.js Route Groups — Organize Without URL
- What Are Route Groups?
- Basic Organization
- Multiple Route Groups
- Real-World Structure
- Shared Components Between Groups
- Nested Route Groups
- Grouping Related Features
- Middleware with Route Groups
- FAQ
What Are Route Groups?
Directories wrapped in parentheses are route groups. They organize files without appearing in the URL:
app/
├── (marketing)/
│ ├── page.tsx → /
│ └── about/
│ └── page.tsx → /about
├── (admin)/
│ ├── page.tsx → /
│ └── users/
│ └── page.tsx → /users
The parentheses don't affect URLs, so both groups can have their own page.tsx at /.
Basic Organization
Group related pages together:
app/
├── (auth)/
│ ├── login/
│ │ └── page.tsx → /login
│ ├── register/
│ │ └── page.tsx → /register
│ └── forgot-password/
│ └── page.tsx → /forgot-password
├── (dashboard)/
│ ├── page.tsx → /
│ ├── analytics/
│ │ └── page.tsx → /analytics
│ └── settings/
│ └── page.tsx → /settings
Multiple Route Groups
Create different layouts for different groups:
// app/(marketing)/layout.tsx
export default function MarketingLayout({ children }) {
return (
<div>
<nav>Marketing Navigation</nav>
{children}
</div>
)
}
// app/(admin)/layout.tsx
export default function AdminLayout({ children }) {
return (
<div className="flex">
<aside>Admin Sidebar</aside>
<main>{children}</main>
</div>
)
}
Real-World Structure
Organize a SaaS app:
app/
├── layout.tsx → Root layout
├── (marketing)/
│ ├── layout.tsx → Marketing layout
│ ├── page.tsx → / (landing)
│ ├── pricing/
│ │ └── page.tsx → /pricing
│ ├── features/
│ │ └── page.tsx → /features
│ └── blog/
│ ├── page.tsx → /blog
│ └── [slug]/
│ └── page.tsx → /blog/[slug]
├── (app)/
│ ├── layout.tsx → App layout (with sidebar)
│ ├── page.tsx → /app (dashboard)
│ ├── projects/
│ │ ├── page.tsx → /projects
│ │ └── [id]/
│ │ └── page.tsx → /projects/[id]
│ └── settings/
│ ├── page.tsx → /settings
│ └── [section]/
│ └── page.tsx → /settings/[section]
├── (auth)/
│ ├── layout.tsx → Auth layout
│ ├── login/
│ │ └── page.tsx → /login
│ ├── register/
│ │ └── page.tsx → /register
│ └── reset-password/
│ └── page.tsx → /reset-password
└── api/
└── route.ts → /api
Shared Components Between Groups
Share components across groups:
app/
├── components/ → Shared components
│ ├── navbar.tsx
│ ├── button.tsx
│ └── card.tsx
├── (marketing)/
│ ├── layout.tsx
│ └── page.tsx
└── (admin)/
├── layout.tsx
└── page.tsx
// app/(marketing)/layout.tsx
import { Navbar } from '@/components/navbar'
export default function MarketingLayout({ children }) {
return (
<div>
<Navbar />
{children}
</div>
)
}
// app/(admin)/layout.tsx
import { Navbar } from '@/components/navbar'
export default function AdminLayout({ children }) {
return (
<div>
<Navbar />
<div className="flex">
<Sidebar />
<main>{children}</main>
</div>
</div>
)
}
Nested Route Groups
Create hierarchies of groups:
app/
├── (site)/
│ ├── (auth)/
│ │ ├── login/
│ │ │ └── page.tsx → /login
│ │ └── register/
│ │ └── page.tsx → /register
│ ├── (public)/
│ │ ├── page.tsx → /
│ │ └── about/
│ │ └── page.tsx → /about
│ └── layout.tsx → Site layout
└── (admin)/
├── layout.tsx → Admin layout
└── dashboard/
└── page.tsx → /dashboard
Grouping Related Features
Organize by feature:
app/
├── (user)/
│ ├── profile/
│ │ ├── page.tsx
│ │ └── edit/
│ │ └── page.tsx
│ └── notifications/
│ └── page.tsx
├── (blog)/
│ ├── page.tsx
│ ├── [slug]/
│ │ └── page.tsx
│ └── category/
│ └── [name]/
│ └── page.tsx
├── (api)/
│ └── posts/
│ └── route.ts
Middleware with Route Groups
Apply middleware to specific groups:
// middleware.ts
import { NextRequest, NextResponse } from 'next/server'
export function middleware(request: NextRequest) {
// Protect admin group
if (request.nextUrl.pathname.startsWith('/admin')) {
const hasAuth = request.cookies.get('auth-token')
if (!hasAuth) {
return NextResponse.redirect(new URL('/login', request.url))
}
}
return NextResponse.next()
}
export const config = {
matcher: ['/((?!api|_next/static).*)']
}
FAQ
Q: Can route groups contain other route groups? A: Yes, create nested hierarchies. (group1)/(group2)/page.tsx is valid.
Q: Do route groups affect SEO? A: No, route groups only affect file organization. URLs and metadata are unaffected.
Q: Can I have a page.tsx both inside and outside a route group? A: Yes. page.tsx in (group1) and page.tsx in (group2) can both exist at the same URL level, but layout.tsx files control rendering.
Use route groups to maintain clean, scalable project structure.
Advertisement