API Routes
Files named route.ts under the pastoria/ directory become server-side
Express API handlers, mounted at the corresponding URL path.
Basic example
pastoria/api/greet/[name]/route.ts → Express route /api/greet/:name
A route.ts file default-exports an Express router:
import express from 'express';
const router = express.Router({mergeParams: true});
router.get<'/', {name: string}>('/', (req, res) => {
res.json({greeting: `Hello ${req.params.name}`});
});
export default router;
Key points
- Use
express.Router({mergeParams: true})to access path params from the parent URL. - Dynamic segments in directory names (e.g.
[name]) become Express path params (:name). - Route handlers are mounted at their directory path, so define handlers
relative to
/. - API routes support all Express methods (
get,post,put,delete, etc.).
Catch-all routes
Use router.all() with a splat pattern to forward all requests to middleware or
external handlers:
import express from 'express';
import {toNodeHandler} from 'better-auth/node';
import {auth} from '#src/lib/server/auth.js';
const router = express.Router();
router.all('/*splat', (req, res, next) => {
toNodeHandler(auth)(req, res).catch(next);
});
export default router;
This is useful for authentication endpoints, proxying, or any route that needs to handle multiple HTTP methods and sub-paths.
Code generation
When you add or remove a route.ts file, run code generation so the server
entry picks it up:
pnpm generate
Note that route.ts changes are not auto-detected by the dev server's file
watcher (which only watches .tsx files). You must run pnpm generate manually
after adding or modifying API routes.