Skip to main content

Static API Routes

Static routes are the foundation of BurgerAPI's file-based routing system. They match exact URL paths and are always checked first in the routing priority order.

What Are Static Routes?

Static routes are API endpoints with fixed, predetermined paths. Unlike dynamic or wildcard routes, static routes don't capture any URL parameters—they match exact paths only.

Examples:

  • /api/products - Lists all products
  • /api/users/profile - Gets current user's profile
  • /api/settings/security - Gets security settings

File-Based Routing Basics

BurgerAPI makes defining API endpoints intuitive using a file-based routing approach. Simply create files and folders within your designated apiDir (configured in the Burger constructor, e.g., apiDir: 'api'), and BurgerAPI handles the rest.

How It Works

Directory Structure = URL Path: The folder structure inside apiDir directly maps to the URL segments.

Example: api/users/profile/route.ts becomes /api/users/profile (assuming the default apiPrefix of 'api').

route.ts Files: Each file named route.ts defines the handlers for a specific path.

HTTP Method Exports: Inside route.ts, export functions named after uppercase HTTP methods (GET, POST, PUT, DELETE, etc.) to handle requests for that method.

Creating Your First Static Route

Let's create a simple products API endpoint:

api/products/route.ts
import type { BurgerRequest } from "burger-api";

// Handles GET requests to /api/products
export function GET(req: BurgerRequest) {
// Example: Accessing query parameters
const query = new URL(req.url).searchParams;
const searchTerm = query.get("search");
console.log("Search Term:", searchTerm);

// Always return a Response object
return Response.json({
message: `Fetched products${
searchTerm ? ` matching \"${searchTerm}\"` : ""
}`,
});
}

// Handles POST requests to /api/products
export async function POST(req: BurgerRequest) {
// Example: Reading and echoing the request body
try {
const body = await req.json();
console.log("Received product data:", body);
return Response.json({ message: "Product created", received: body });
} catch (error) {
return new Response("Invalid JSON body", { status: 400 });
}
}

This creates two static routes:

  • GET /api/products - Lists products
  • POST /api/products - Creates a new product

Route Handlers

Your exported HTTP method functions are the route handlers:

Handler Arguments

  • Argument: They receive a single argument: the BurgerRequest object.

BurgerRequest Object

This object extends the standard Request and provides helpful properties and methods:

  • req.url: The full request URL.
  • req.method: The HTTP method.
  • req.headers: Request headers.
  • await req.json() and await req.text() etc.: Methods to read the request body.
  • req.validated: Contains validated data if using Schema Validation.

Return Value

Handlers must return a standard Response object.

Supported HTTP Methods

BurgerAPI supports all standard HTTP methods:

  • GET - Retrieve resources
  • POST - Create new resources
  • PUT - Update/replace resources
  • PATCH - Partially update resources
  • DELETE - Remove resources
  • OPTIONS - Get communication options
  • HEAD - Get headers only

Example: Nested Static Routes

Create a multi-level API structure:

api/
users/
profile/
route.ts → /api/users/profile
settings/
route.ts → /api/users/settings
products/
featured/
route.ts → /api/products/featured
route.ts → /api/products
api/products/featured/route.ts
import type { BurgerRequest } from "burger-api";

export function GET(req: BurgerRequest) {
return Response.json({
message: "Featured products",
products: [
{ id: 1, name: "Product A", featured: true },
{ id: 2, name: "Product B", featured: true },
],
});
}

Route Matching Priority

Static Routes Have Highest Priority

BurgerAPI uses an efficient routing mechanism (a trie) that prioritizes more specific routes. Static routes are always matched first, before dynamic or wildcard routes.

  • Static routes (e.g., /products/featured) are matched before dynamic routes (/products/[id]).
  • Routes with more static segments are generally matched before routes with fewer.

This helps avoid ambiguity when multiple route patterns could potentially match a request URL.

Priority Example

Given these routes:

api/products/featured/route.ts    → Static: /api/products/featured
api/products/[id]/route.ts → Dynamic: /api/products/[id]
api/products/[...]/route.ts → Wildcard: /api/products/[...]

Request matching:

  • GET /api/products/featured → Matches static route (highest priority)
  • GET /api/products/123 → Matches dynamic route (static doesn't match, dynamic checked next)
  • GET /api/products/123/reviews → Matches wildcard route (only wildcard can match multiple segments)

Best Practices

1. Keep Routes Simple and Predictable

// ✅ Good: Clear, predictable paths
api/users/route.ts → /api/users
api/users/profile/route.ts → /api/users/profile

// ❌ Avoid: Overly nested or unclear paths
api/v1/data/users/info/personal/route.ts

2. Use Proper HTTP Methods

// ✅ Good: RESTful methods
export function GET(req: BurgerRequest) { /* Get resource */ }
export function POST(req: BurgerRequest) { /* Create resource */ }
export function DELETE(req: BurgerRequest) { /* Delete resource */ }

// ❌ Avoid: Using GET for mutations
export function GET(req: BurgerRequest) { /* Don't delete in GET! */ }

3. Return Proper Response Objects

// ✅ Good: Always return Response
export function GET(req: BurgerRequest) {
return Response.json({ data: [] });
}

// ❌ Avoid: Returning plain objects
export function GET(req: BurgerRequest) {
return { data: [] }; // Won't work!
}

4. Handle Errors Gracefully

export async function POST(req: BurgerRequest) {
try {
const body = await req.json();
// Process body...
return Response.json({ success: true });
} catch (error) {
return Response.json(
{ error: "Invalid request body" },
{ status: 400 }
);
}
}

Next Steps

Now that you understand static routes, learn about other routing patterns:

Static routes form the backbone of your API. Use them for well-defined endpoints with fixed paths, and combine them with dynamic and wildcard routes for a powerful, flexible routing system.