Skip to content
Ownfold
Esc
navigateopen⌘Jpreview
On this page

Framework handler API reference

Exact factories, options, signatures, mounting examples, origin requirements, and runtime behavior for every Ownfold framework package.

Framework packages adapt the canonical Fetch handler to route conventions. They do not configure a database, authenticate users, create browser clients, or render UI.

Shared setup

Every handler ultimately receives VaultFetchHandlerOptions:

PropType
serverVaultServer
TypeVaultServer
basePath?string
Typestring
isOriginAllowed?(input: { readonly request: Request }) => boolean | Promise<boolean>
Type(input: { readonly request: Request }) => boolean | Promise<boolean>

Create vaultServer once, then mount exactly one framework adapter. Keep the mount path equal to the browser transport’s baseURL.

Next.js App Router

pnpm add @ownfold/next@beta
import { createNextVaultHandlers } from "@ownfold/next"
import { vaultServer } from "@/src/lib/vault-server"

export const { GET, POST } = createNextVaultHandlers({
  server: vaultServer,
  basePath: "/api/ownfold",
})

createNextVaultHandlers(options)

Returns NextVaultHandlers, an object with (request: Request) => Promise<Response> functions for GET and POST. Export both from the catch-all route. Unsupported methods remain absent and are handled by Next.js.

PropType
GET(request: Request) => Promise<Response>
Type(request: Request) => Promise<Response>
POST(request: Request) => Promise<Response>
Type(request: Request) => Promise<Response>

This package is server-only. Do not import it into Client Components or the Edge runtime unless all selected server/database dependencies support that runtime.

Standard Node.js

pnpm add @ownfold/node@beta @ownfold/fetch@beta
import { createVaultFetchHandler } from "@ownfold/fetch"
import { createNodeVaultHandler } from "@ownfold/node"

const handler = createNodeVaultHandler({
  handler: createVaultFetchHandler({ server: vaultServer }),
  origin: process.env.PUBLIC_APP_ORIGIN,
})

httpServer.on("request", (request, response) => {
  void handler(request, response)
})
PropType
handlerVaultFetchHandler
TypeVaultFetchHandler
originNodeVaultOrigin
TypeNodeVaultOrigin
maxBodyBytes?number
Typenumber
Option Required behavior
handler Canonical VaultFetchHandler to invoke after conversion.
origin Exact public origin or resolver used to construct the standard Request URL. Never derive trust from an unvalidated Host header.
maxBodyBytes Native request-stream ceiling; defaults to the canonical HTTP maximum.

createNodeVaultHandler converts Node request headers, URL, method, and bounded body to a standard Request, invokes the Fetch handler, then writes status, headers, and body back once.

createExpressVaultMiddleware has the same option and return types. Mount it at the application level so the Fetch handler can see its configured base path:

app.use(
  createExpressVaultMiddleware({
    handler: createVaultFetchHandler({ server: vaultServer }),
    origin: "https://app.example.com",
  }),
)

Fastify

pnpm add @ownfold/fastify@beta
import { createFastifyVaultHandler } from "@ownfold/fastify"

const handler = createFastifyVaultHandler({
  server: vaultServer,
  basePath: "/api/ownfold",
  origin: "https://app.example.com",
})

fastify.route({
  method: ["GET", "POST"],
  url: "/api/ownfold/*",
  handler,
})
PropType
originNodeVaultOrigin
TypeNodeVaultOrigin
maxBodyBytes?number
Typenumber

The handler uses request.raw and reply.raw, then calls reply.hijack() so Fastify does not write a second response. origin and maxBodyBytes have the Node adapter semantics.

Hono

pnpm add @ownfold/hono@beta
import { createHonoVaultHandler } from "@ownfold/hono"

app.all(
  "/api/ownfold/*",
  createHonoVaultHandler({ server: vaultServer }),
)

createHonoVaultHandler(options) returns a native Hono Handler. It forwards context.req.raw to the Fetch handler and returns its Response. Use Hono middleware before the route for host session, CSRF, tracing, or request correlation.

Elysia

pnpm add @ownfold/elysia@beta
import { createElysiaVaultHandler } from "@ownfold/elysia"

const ownfold = createElysiaVaultHandler({ server: vaultServer })

app.all("/api/ownfold/*", ({ request }) => ownfold({ request }))

createElysiaVaultHandler(options) returns (context: { request: Request }) => Promise<Response>. Pass Elysia’s standard Request unchanged.

TanStack Start

pnpm add @ownfold/tanstack-start@beta
import { createTanStackStartVaultHandlers } from "@ownfold/tanstack-start"
import { createFileRoute } from "@tanstack/react-router"

const handlers = createTanStackStartVaultHandlers({
  server: vaultServer,
})

export const Route = createFileRoute("/api/ownfold/$")({
  server: {
    handlers,
  },
})
PropType
GET(input: TanStackStartServerRouteInput) => Promise<Response>
Type(input: TanStackStartServerRouteInput) => Promise<Response>
POST(input: TanStackStartServerRouteInput) => Promise<Response>
Type(input: TanStackStartServerRouteInput) => Promise<Response>

Each function accepts { request }, matching TanStack Start server-route callbacks, and returns the canonical response.

Choosing the generic Fetch handler

Use createVaultFetchHandler directly when the framework already provides standard web Requests and expects standard Responses. A dedicated package is useful only when its native handler shape differs or a typed convenience avoids glue code.

Handler invariants

All official framework handlers preserve the same behavior:

  • no browser-provided user ID;
  • exact bounded-body parsing before JSON validation;
  • the configured server’s authentication, rate-limit, and audit pipeline;
  • stable HTTP error mapping without internal causes;
  • no application-record persistence; and
  • no default hosted Ownfold service or outbound telemetry.

See Transport APIs, Vault server, and the complete export index.

Last updated on August 4, 2026

Was this page helpful?