Skip to content
Ownfold
Esc
navigateopen⌘Jpreview
On this page

Framework adapters

Choose a full-stack or backend-only Ownfold adapter and mount the same framework-independent vault server.

Ownfold framework packages are server adapters, not UI kits. They translate the host framework’s request boundary to one VaultServer; none requires React unless the host application independently chooses the React bindings.

How adapters fit

your authentication       your database
         │                      │
         ▼                      ▼
      getUserId             VaultAdapter
             ╲              ╱
              ╲            ╱
               VaultServer

          framework adapter

          your existing routes

Validation, authorization, ownership, rate limits, audit hooks, state transitions, and storage semantics live below the framework layer.

Full-stack frameworks

Framework Package Server boundary Guide
Next.js App Router @ownfold/next Route handlers using Web Request and Response Next.js
TanStack Start @ownfold/tanstack-start Splat server route using Web requests TanStack Start

These guides show an optional browser client because the frameworks can host both sides. Their server adapters still work independently of @ownfold/react.

Backend frameworks

Framework/runtime Package Bridge Guide
Raw Node.js / Express @ownfold/node Node request/response to Web handler Node.js and Express
Fastify @ownfold/fastify Raw Node objects through @ownfold/node Fastify
Hono @ownfold/hono Native Web request Hono
Elysia @ownfold/elysia Native Web request Elysia
tRPC v11 @ownfold/trpc Typed procedures calling VaultServer tRPC
Fetch-compatible runtime @ownfold/fetch Canonical Request => Response handler Fetch handler

All are suitable for API-only applications. Start with the backend quickstart if no frontend exists.

Choose by runtime

Deployment Recommended choice
Node.js with Express @ownfold/node
Node.js with Fastify @ownfold/fastify
Bun with Elysia @ownfold/elysia
Node, Bun, Deno, or edge with Hono @ownfold/hono
Cloudflare Workers Hono or @ownfold/fetch, plus runtime-compatible storage/auth
Custom server exposing Web requests @ownfold/fetch
Existing tRPC v11 API @ownfold/trpc

Framework support and database support are separate. For example, Hono can run on Workers, but node:sqlite and an ordinary pg pool cannot. Select a database adapter compatible with the actual runtime.

Shared server setup

Choose one database and one identity. They are independent of the framework adapter:

import { DatabaseSync } from "node:sqlite"
import { SqliteVaultAdapter } from "@ownfold/sqlite"

export const adapter = new SqliteVaultAdapter(new DatabaseSync("ownfold.db"))
import { nodePostgresVaultAdapter } from "@ownfold/postgres/node-postgres"
import { Pool } from "pg"

export const adapter = nodePostgresVaultAdapter(
  new Pool({ connectionString: process.env.DATABASE_URL }),
)
import { drizzleVaultAdapter } from "@ownfold/drizzle"
import { db } from "./db"

export const adapter = drizzleVaultAdapter(db)
import { prismaVaultAdapter } from "@ownfold/prisma"
import { prisma } from "./prisma"

export const adapter = prismaVaultAdapter(prisma)
export const getUserId = betterAuthUserResolver(auth)
export const getUserId = authJsUserResolver(async () => auth())
export const getUserId: OwnfoldUserResolver = async ({ request }) =>
  (await sessions.verify(request.headers))?.user.id ?? null
export const getUserId = singleUserResolver("local-owner")

Private single-user processes only. This resolver does not authenticate callers.

Every guide begins with the same server:

import { createVaultServer } from "@ownfold/server"

export const vaultServer = createVaultServer({
  adapter,
  getUserId,
})

Authentication may come from Better Auth, Auth.js, or a custom resolver. Storage may use SQLite, PostgreSQL, Drizzle, Prisma, or a custom adapter.

Application records are separate

Framework adapters expose Ownfold coordination operations. Your application still owns record routes and tables for messages, documents, files, or domain data. Validate encrypted writes with VaultServer.validateEncryptedRecordWrite; do not add plaintext or decryption to the coordination router.

Build a custom adapter

If your framework accepts Web Request and returns Web Response, delegate directly:

import { createVaultFetchHandler } from "@ownfold/fetch"

const handle = createVaultFetchHandler({ server: vaultServer })

export const frameworkHandler = (context: { request: Request }) => handle(context.request)

Node-style frameworks should reuse createNodeVaultHandler rather than reimplementing streaming, header conversion, response writing, or size limits. See the adapter architecture and run the shared tests before publishing an adapter.

Last updated on August 4, 2026

Was this page helpful?