Set up and define routes
The init callback
Register all custom routes inside the init callback. The callback receives the baseline instance as first parameter.
const app = baseline({
root: resolve(import.meta.dirname, ".."),
init: async ({api}) => {
// Register your routes here
api.get("magic", ...);
},
});
app.init();Routing Stack Order
Always define routes inside the init callback. Defining routes after app.init() has finished will not work. See Advanced: Routing
Create API routes
Use the HTTP method helpers to define your endpoints. Note that all routes defined via baseline.api are automatically prefixed with /api.
// Defines a POST endpoint at /api/magic
baseline.api.post("magic", async (req, res) => {
return res.status(200).send({
success: true,
});
});Validate request data with schemas
Baseline uses Zod for all schema definitions. Defining schema.body, schema.query, or schema.path automatically injects validation middleware and populates the req.validated object:
req.validated.bodyreq.validated.queryreq.validated.path
Schemas also enable automatic generation of an interactive API reference at /api/docs.
Useful documentation for creating schema objects:
// Defines a POST endpoint at /api/user/:id/magic with validation
baseline.api.post(
"user/:id/magic",
{
schema: {
tags: ["magic"],
description: "Perform some magic",
path: z.object({
id: z.string()
}),
body: z.object({
spell: z.string(),
}),
response: {
200: {
description: "OK",
content: {
"application/json": {
schema: z.object({
success: z.boolean(),
}),
},
},
},
},
},
},
async (req, res) => {
// Access validated and typed data directly from req.validated
const { id } = req.validated.path;
return res.status(200).send({
success: true,
});
},
);The schema object is passed through to the OpenAPI Schema Object, with the exception of some helpers that make writing a schema a bit easier:
- schema.body is transformed to schema.requestBody
- if you define both, they will get merged
- schema.query is transformed to schema.requestParams.query
- schema.path is transformed to schema.requestParams.path
- schema.response is transformed to schema.responses
Boolean Parameter Parsing
To enable automatic boolean parsing for query or path parameters, use z.stringbool in your schema. See Boolean Parameter Parsing.
Secure your routes
All API routes require authentication by default. To make an endpoint public, set auth: false in the options object. For more details, see authentication.
// Public route: no authentication required
baseline.api.get("/health", { auth: false }, (req, res) => {
return res.send({ status: "ok" });
});Use middleware
Middleware offered by baseline can be accessed at baseline.api.middleware.
//Example: automatically fetching an entity from a path parameter
const { getEntityFromPath } = baseline.api.middleware;
const entity = baseline.database.entities.get("users");
const userFromPathMiddleware = getEntityFromPath(baseline, entity);
baseline.api.get("/user/:id/check", userFromPathMiddleware, (req, res) => {
const user = req.entity;
return res.send(`Checked user ${user.id}`);
});Inject custom middleware
Pass multiple handler functions as subsequent arguments to chain middleware and route handlers.
import { rateLimit } from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
});
// The limiter runs before the route handler
baseline.api.get("/audit", limiter, (req, res) => {
return res.send("Audit complete");
});Control middleware order
If you need to execute custom middleware before baseline's internal validation or authentication logic, use the middleware.pre option.
The execution order is:
- Middleware configured via
middleware.pre. - Automatically added middleware (validation from schemas, authentication, file upload handling).
- Your route handler functions.
Access raw Express endpoints
If you need to bypass the baseline routing system, access the underlying Express instance via baseline.app. Use this for standard Express logic that does not require baseline features.
baseline.app.get("/legacy", (req, res) => {
res.send("Standard Express response");
});Bypass Warning
When using baseline.app to define routes, baseline will not:
- Generate API documentation.
- Inject validation middleware.
- Enforce authentication.