Route Groups
Route groups organize API route files into logical folders without affecting the URL structure.
What Are Route Groups?
Route groups use parentheses (folder) to create organizational folders that are ignored when BurgerAPI builds the route path. The folder exists for your organization, but doesn't appear in the URL.
Syntax
Wrap any folder name in parentheses to make it a route group:
(groupName)
Basic Example
Without Route Groups
api/
users/
route.ts → /api/users
products/
route.ts → /api/products
orders/
route.ts → /api/orders
All files are at the root level: hard to organize as your API grows.
With Route Groups
api/
(public)/
users/
route.ts → /api/users
products/
route.ts → /api/products
(admin)/
orders/
route.ts → /api/orders
settings/
route.ts → /api/settings
The (public) and (admin) folders don't appear in URLs:
/api/users(not/api/public/users)/api/orders(not/api/admin/orders)
Common Use Cases
1. Organizing by Access Level
Separate public, authenticated, and admin routes:
api/
(public)/
products/
route.ts → /api/products
health/
route.ts → /api/health
(authenticated)/
profile/
route.ts → /api/profile
orders/
route.ts → /api/orders
(admin)/
users/
route.ts → /api/users
analytics/
route.ts → /api/analytics
Benefits:
- Clear visual separation by access level
- Maintains clean, simple URLs
2. Organizing by Feature
Group related functionality together:
api/
(shop)/
products/
route.ts → /api/products
cart/
route.ts → /api/cart
checkout/
route.ts → /api/checkout
(user-management)/
users/
route.ts → /api/users
roles/
route.ts → /api/roles
permissions/
route.ts → /api/permissions
3. Organizing by Version
Two route groups must never resolve to the same URL. A route group is ignored in the path, so copying a route into a second group creates a duplicate:
api/
(v1)/
users/
route.ts → /api/users
(v2-draft)/
users/
route.ts → /api/users ❌ duplicate: startup fails
Keep the version in the URL when it matters, using regular folders instead of groups:
api/
v1/
users/
route.ts → /api/v1/users
products/
route.ts → /api/v1/products
v2/
users/
route.ts → /api/v2/users
Alternatively, serve one version at a time by pointing apiDir at a different directory.
4. Organizing by Team
Large teams can organize by ownership:
api/
(team-commerce)/
products/
route.ts → /api/products
orders/
route.ts → /api/orders
(team-auth)/
login/
route.ts → /api/login
register/
route.ts → /api/register
Nested Route Groups
You can nest route groups for more granular organization:
api/
(features)/
(shop)/
products/
route.ts → /api/products
cart/
route.ts → /api/cart
(auth)/
login/
route.ts → /api/login
register/
route.ts → /api/register
Both (features) and (shop) are ignored, resulting in /api/products.
Combining with Other Route Types
Route groups work seamlessly with all other routing patterns:
Route Groups + Dynamic Routes
api/
(admin)/
users/
[userId]/
route.ts → /api/users/[userId]
URL: /api/users/123 (not /api/admin/users/123)
Route Groups + Wildcard Routes
api/
(internal)/
proxy/
[...]/
route.ts → /api/proxy/[...]
URL: /api/proxy/any/nested/path (not /api/internal/proxy/...)
Example: Complete Organization
Here's a real-world example of a well-organized API:
api/
(public)/
health/
route.ts → /api/health
products/
route.ts → /api/products
[productId]/
route.ts → /api/products/[productId]
(authenticated)/
profile/
route.ts → /api/profile
orders/
route.ts → /api/orders
[orderId]/
route.ts → /api/orders/[orderId]
(admin)/
users/
route.ts → /api/users
[userId]/
route.ts → /api/users/[userId]
analytics/
[...]/
route.ts → /api/analytics/[...]
Result: Clean URLs with clear organization.
Best Practices
1. Use Descriptive Group Names
// ✅ Good: Clear purpose
(admin)
(authenticated)
(public-api)
(feature-shop)
// ❌ Avoid: Vague names
(misc)
(stuff)
(routes)
2. Keep Nesting Shallow
// ✅ Good: 1-2 levels of grouping
api/(features)/(shop)/products/route.ts
// ❌ Avoid: Too many nested groups
api/(org)/(dept)/(team)/(feature)/(sub)/route.ts
3. Consistent Naming Convention
// ✅ Good: Pick a convention and stick with it
(admin)
(public)
(authenticated)
// ❌ Avoid: Mixed conventions
(admin)
(publicRoutes)
(Authenticated_Users)
4. Document Your Organization
Add a README in your api directory explaining your grouping strategy:
# API Structure
## Route Groups
- `(public)` - Public endpoints, no authentication
- `(authenticated)` - Requires user authentication
- `(admin)` - Requires admin privileges
Route Groups vs. URL Segments
It's important to understand the difference:
| Feature | Route Groups (folder) | Regular Folders |
|---|---|---|
| Affects URL | ❌ No | ✅ Yes |
| Purpose | Organization only | URL structure |
| Example | (admin)/users/ → /api/users | admin/users/ → /api/admin/users |
When NOT to Use Route Groups
Don't use route groups when:
-
The path should be in the URL
// ❌ Don't hide important URL segmentsapi/(v1)/users/route.ts → /api/users (version hidden!)// ✅ Keep version in URL if it mattersapi/v1/users/route.ts → /api/v1/users -
Organization doesn't add value
// ❌ Unnecessary groupingapi/(routes)/(endpoints)/users/route.ts// ✅ Simple is betterapi/users/route.ts
Types for this feature
Route groups do not change the types of a route. A group folder is removed from the URL, and the handlers inside are typed exactly like any other route.
✅ Correct: the handler type is the same as without the group:
// api/(admin)/users/route.ts → /api/users
import { defineRoute } from "burger-api";
import { GET as GetSchema } from "./schema";
export const GET = defineRoute(GetSchema, (ctx) => {
return Response.json({ ok: true });
});
There is no group type to learn. For the handler and parameter types, see Static Routes and Dynamic Routes. See the TypeScript overview.
Check your code: bun run typecheck.
Next Steps
Learn about other routing patterns:
- Static Routes - Fixed API endpoints
- Dynamic Routes - Capture URL parameters
- Wildcard Routes - Handle complex nested paths
Route groups keep your codebase organized as your API grows, without changing URLs.