How to Handle Route Parameters in OmniRoute: Dynamic Routing with Next.js App Router
OmniRoute handles route parameters using Next.js 16 App Router dynamic segments, extracting values from URL paths via the params property and validating them with Zod schemas before delegating to core handlers in open-sse/handlers/.
The OmniRoute API gateway is built on the Next.js 16 App Router file-system convention. Dynamic URL segments map directly to folder names, creating a type-safe bridge between incoming requests and provider-specific business logic. Understanding how to extract, validate, and process these parameters is essential for extending the platform or debugging provider integrations.
Dynamic Segment Syntax in Next.js App Router
OmniRoute follows Next.js App Router conventions for dynamic routing. Single brackets capture specific path segments, while double brackets create optional catch-all patterns.
- [param] – Captures a single path segment as a named parameter (e.g.,
[provider]becomesparams.provider). - [[...slug]] – Captures zero or more path segments as an array, useful for variable-length identifiers like model paths or combo tokens.
In src/app/api/v1/providers/[provider]/models/route.ts, the [provider] directory captures provider names such as openai or anthropic. For routes requiring flexible path depths, such as src/app/api/v1/vscode/combos/[token]/[[...slug]]/route.ts, the double-bracket syntax stores remaining segments as params.slug.
Extracting Route Parameters from the Request Context
Route handlers in OmniRoute receive parameters through the second argument of the route function, typed explicitly for safety.
// src/app/api/v1/providers/[provider]/models/route.ts
import { NextRequest } from 'next/server';
export async function GET(
req: NextRequest,
{ params }: { params: { provider: string } }
) {
const { provider } = params; // "openai", "anthropic", etc.
// ... handler logic
}
The params object contains key-value pairs where keys match the bracket names in the file path. For catch-all routes, the value is a string array:
// src/app/api/v1/vscode/combos/[token]/[[...slug]]/route.ts
export async function POST(
req: NextRequest,
{ params }: { params: { token: string; slug?: string[] } }
) {
const token = params.token;
const comboPath = (params.slug ?? []).join('/'); // e.g., "gpt-4o/preview"
}
Validating Parameters with Zod Schemas
OmniRoute enforces strict input validation using Zod schemas before any business logic executes. Validation typically occurs in the same folder as the route or via shared helpers like src/app/api/v1/_helpers/apiKeyScope.ts.
Single parameter validation:
import { z } from 'zod';
const ProviderSchema = z.enum(['openai', 'anthropic', 'gemini']);
const provider = ProviderSchema.parse(params.provider);
Complex parameter validation:
const TokenSchema = z.string().uuid();
const token = TokenSchema.parse(params.token);
This pattern guarantees that only well-formed values reach the core handlers, preventing malformed provider names or invalid tokens from propagating through the system.
Handling Catch-All and Optional Catch-All Segments
Variable-length routes handle model identifiers or combo paths that may contain slashes. The [[...slug]] convention stores segments as an array, allowing reconstruction of the original path.
// src/app/api/v1/vscode/combos/[token]/[[...slug]]/route.ts
const modelPath = params.slug?.join('/') ?? '';
This approach supports endpoints where the identifier itself contains multiple segments, such as gpt-4o/preview or custom combo configurations, without requiring rigid URL structures.
Routing Pipeline: From Extraction to Execution
After parameter extraction and validation, OmniRoute follows a standardized pipeline:
- CORS pre-flight handling – Managed at the route edge.
- Parameter validation – Zod schemas verify
paramsand request body. - Feature flag checks – Gates like PII redaction consult
src/shared/constants/featureFlagDefinitions.ts. - Handler delegation – Validated parameters pass to core functions in
open-sse/handlers/, such ashandleChatCoreorhandleEmbedding.
The API route files act as thin wrappers. For example, src/app/api/v1/relay/chat/completions/route.ts extracts parameters, validates them, then delegates to the central routing service in src/open-sse/services/combo.ts for provider selection and circuit-breaker checks.
Summary
- OmniRoute uses Next.js 16 App Router file-system routing with
[param]and[[...slug]]conventions. - Parameters extract via the
paramsproperty in the request context, typed explicitly for TypeScript safety. - Zod schemas validate all dynamic segments before business logic executes, typically defined in
*_schema.tsfiles or shared helpers. - Catch-all segments
[[...slug]]capture variable-length paths as arrays, reconstructing identifiers like model paths. - Validated requests delegate from route files to core handlers in
open-sse/handlers/after CORS handling and feature flag checks.
Frequently Asked Questions
What format does OmniRoute use for dynamic route parameters?
OmniRoute uses Next.js 16 App Router bracket notation. Single brackets like [provider] capture individual path segments, while double brackets like [[...slug]] create optional catch-all patterns that capture multiple segments into an array. These map directly to the file system under src/app/api/v1/.
How does OmniRoute validate route parameters?
All dynamic values undergo validation using Zod schemas. The route handler calls parse methods on schemas defined locally or imported from shared locations like src/app/api/v1/_helpers/apiKeyScope.ts. This ensures type safety and prevents invalid provider names or malformed tokens from reaching downstream services.
What is the difference between [param] and [...slug] in OmniRoute?
The [param] syntax captures exactly one path segment as a string value (e.g., params.provider). The [[...slug]] syntax (double brackets) captures zero or more segments as a string array, allowing reconstruction of multi-part identifiers. OmniRoute uses single brackets for fixed entities like providers and double brackets for variable model paths or combo identifiers.
Where does the actual business logic execute after parameter extraction?
After validation, API routes delegate to centralized handlers located in open-sse/handlers/. Files like src/app/api/v1/relay/chat/completions/route.ts serve as thin wrappers that validate inputs, check feature flags against src/shared/constants/featureFlagDefinitions.ts, then call core services such as src/open-sse/services/combo.ts to execute provider selection and request routing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →