Skip to main content

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:

FeatureRoute Groups (folder)Regular Folders
Affects URL❌ No✅ Yes
PurposeOrganization onlyURL structure
Example(admin)/users/ → /api/usersadmin/users/ → /api/admin/users

When NOT to Use Route Groups​

Don't use route groups when:

  1. The path should be in the URL

    // ❌ Don't hide important URL segments
    api/(v1)/users/route.ts → /api/users (version hidden!)

    // ✅ Keep version in URL if it matters
    api/v1/users/route.ts → /api/v1/users
  2. Organization doesn't add value

    // ❌ Unnecessary grouping
    api/(routes)/(endpoints)/users/route.ts

    // ✅ Simple is better
    api/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:

Route groups keep your codebase organized as your API grows, without changing URLs.