Route Contracts
Routa is built around one source of truth:
schemas -> routes -> handlers -> OpenAPI -> docs/checksRoute files define what each HTTP method accepts, what it can return, which middleware applies, and where the handler boundary begins.
File-Based APIs
Section titled “File-Based APIs”Folders map to URL segments:
src/routes/users/route.tssrc/routes/users/$userId/route.tssrc/routes/users/$userId/posts/route.tsEach route.ts file owns the methods for one path. Keeping all verbs for one path together makes shared params, middleware, schemas, and metadata easier to maintain.
Contract Before Handler
Section titled “Contract Before Handler”export default defineRoute({ post: createRoute({ input: { body: CreateUserSchema, }, responses: { success: { status: 201, schema: UserSchema, }, emailConflict: { status: 409, schema: EmailConflictSchema, }, }, run: async ({ input, ctx }) => { return users.createUser({ body: input.body, actorId: ctx.state.auth.principal.id, }); }, }),});Handlers return named outcomes from the declared response map. If a route did not declare an outcome, TypeScript should reject it.
HTTP Boundary Only
Section titled “HTTP Boundary Only”Routa owns routing, validation, middleware context, typed responses, and OpenAPI. Your application owns services, use cases, domain models, persistence, and business logic.