Plugins
A plugin packages procedures, raw routes, and H3 middleware behind one .use() call. Built-in features (.auth(), .admin(), .files(), .mcp(), .openapi()) stay as they are — plugins are the extension point for third-party and app-specific features.
Write a plugin
An OuterPlugin has a unique name and optional hooks:
import type { OuterPlugin } from "@outerjs/server";
export const pingPlugin: OuterPlugin = {
name: "ping",
build(ctx) {
return {
procedures: {
ping: ctx.base.handler(() => "pong"),
},
};
},
};
Register it anywhere in the chain before .start() / .build():
const server = await new Outer({ db: pglite() }).schema(v1_0).use(pingPlugin).start();
POST /rpc/ping is now mounted. Double-registering the same name throws.
Lifecycle hooks
| Hook | When | Purpose |
|---|---|---|
configure | At .use() time | Fail fast on bad config. Store options on the plugin object. |
validate | At the start of build, after Outer’s built-in checks | Reject the build — for example if .auth() is missing. Pure validation, no side effects. |
build | After built-in procedures (admin, files) are assembled | Return procedures, routes, and/or middleware to mount. |
const needsAuth: OuterPlugin = {
name: "needs-auth",
validate(ctx) {
if (!ctx.resources.auth) throw new Error("This plugin requires .auth()");
},
build(ctx) {
return {
procedures: {
"secure.ping": ctx.base.handler(() => "pong"),
},
routes: [
{
method: "get",
path: "/plugin-health",
handler: () => ({ ok: true }),
},
],
middleware: [
async (event, next) => {
event.res.headers.set("x-plugin", "needs-auth");
return next();
},
],
};
},
};
What build can return
| Field | Shape | Behavior |
|---|---|---|
procedures | Record<string, AnyProcedure> | Registered like .procedure() — keys are dot-names ("webhook.receive" → POST /rpc/webhook/receive). |
routes | { method, path, handler }[] | Mounted like .route(), before /rpc/**. |
middleware | (event, next) => Promise<unknown>[] | Runs after CORS and rate-limit middleware, before routes. |
build receives a PluginContext:
| Field | Description |
|---|---|
resources | Read-only snapshot of the resources bag (auth, storage, cors, …). |
base | The oRPC base builder with the current context type — chain .handler() on it. |
schemas | Schema versions registered so far. |
name | The Outer instance name, if any. |
Prefer returning procedures over mutating resources. Routes and middleware from plugins are collected and mounted by Outer.
Next steps
- Procedures — hand-written endpoints without a plugin
- API reference — full
OuterPlugintypes