A router is a plain JavaScript object where the values are procedures or nested routers. oRPC traverses this object to route incoming requests to the correct procedure.
Defining a router
You can define a router by composing procedures into an object:
import { listPlanet, findPlanet, createPlanet } from './procedures'
export const router = {
planet: {
list: listPlanet,
find: findPlanet,
create: createPlanet,
},
}
The nesting depth is unlimited. A procedure is also a valid router — it can be used directly as the root.
Using os.router()
The os.router() method lets you apply shared options (middleware, error maps, prefix, tags) to an entire router:
import { os } from '@orpc/server'
export const planetRouter = os
.use(authMiddleware) // applied to every procedure in this router
.router({
list: listPlanet,
find: findPlanet,
create: createPlanet,
})
os.router() returns a new router with the middleware and options merged into every procedure. The original procedures are not mutated.
Nested routers
Combine multiple routers to build your full API:
import { os } from '@orpc/server'
const planetRouter = {
list: listPlanet,
find: findPlanet,
create: createPlanet,
}
const starRouter = {
list: listStar,
find: findStar,
}
export const router = {
planet: planetRouter,
star: starRouter,
}
Prefixing routes
When serving an OpenAPI spec, you can add a URL prefix to all procedures in a router:
export const planetRouter = os
.prefix('/planets')
.router({
list: listPlanet,
find: findPlanet,
create: createPlanet,
})
Prefixes only affect procedures that define an explicit route with a path. They are ignored for procedures served via the default RPC path convention.
Tagging procedures for OpenAPI
Add OpenAPI tags to all procedures in a router at once:
export const planetRouter = os
.tag('planets')
.router({
list: listPlanet,
find: findPlanet,
create: createPlanet,
})
Router utility types
@orpc/server exports several utility types for introspecting your router:
import type {
InferRouterInputs,
InferRouterOutputs,
InferRouterInitialContexts,
RouterClient,
} from '@orpc/server'
// Extract all input/output types
type Inputs = InferRouterInputs<typeof router>
type Outputs = InferRouterOutputs<typeof router>
// The client type — used when creating a typed client
type Client = RouterClient<typeof router>
Lazy routers
For large routers that impact cold start times, you can wrap sub-routers in lazy() to defer loading until first use. See Lazy Routers for details.
import { lazy } from '@orpc/server'
export const router = {
planet: lazy(() => import('./planet-router').then(m => ({ default: m.planetRouter }))),
}