Framework Portability
Mount app.handler in TanStack Start, React SPA, Solid 2, Bun SSR, Next.js, and other modern TypeScript frameworks
app.handler(req: Request): Promise<Response> — every modern TypeScript framework knows this Web Standard shape.
Bunderstack runs in any environment supporting standard Web Requests and Responses. Below are the recommended integration patterns, configuration files, and deployment setups for each supported framework.
TanStack Start (Full-Stack SSR)
TanStack Start provides full-stack React with server-side rendering and streaming. The official bunderstack/start adapter handles API routing, SSR-aware data fetching, session lookup, and auth client configuration.
1. Installation
bun add bunderstack drizzle-orm valibot @libsql/client @tanstack/react-query @tanstack/react-start2. Configuration (src/bunderstack.ts)
TanStack Start supports top-level await, allowing you to export app and its TypeScript type directly:
// src/bunderstack.ts
import { bunderstack } from 'bunderstack'
import { libsql } from 'bunderstack/libsql'
import { provision } from 'bunderstack/provision'
import { access } from './access'
import * as schema from './schema'
export const backend = bunderstack({
schema,
access,
database: {
adapter: libsql(),
url: process.env.DATABASE_URL || 'file:./data.db',
},
auth: { emailAndPassword: { enabled: true } },
realtime: true,
})
export const app = await backend.start()
export type App = typeof app
await provision(app)3. API Catch-All Route (src/routes/api/$.tsx)
Mount the API handler on TanStack Start's catch-all route:
// src/routes/api/$.tsx
import { createFileRoute } from '@tanstack/react-router'
import { createApiHandlers } from 'bunderstack/start'
import { app } from '~/bunderstack'
export const Route = createFileRoute('/api/$')({
server: { handlers: createApiHandlers(app) },
})4. Typed Client Setup (src/api.ts)
// src/api.ts
import { bunderstackStart } from 'bunderstack/start'
import type { App } from './bunderstack'
export const { createQueryClient, createApi } = bunderstackStart<App>()Important: Do not name this file
src/client.ts. TanStack Start reservesclient.tsas its hydration entry point.
5. Package Scripts & Deployment
{
"scripts": {
"build": "vite build",
"start": "bun .output/server/index.mjs"
}
}Running bunx bunderstack blueprint detects @tanstack/react-start and outputs framework: tanstack-start.
Solid 2 (Standalone Vite + Bun SSR)
Standalone Solid 2 (without SolidStart) uses a unified Bun server to handle static assets, perform server-side rendering, and delegate API requests directly to Bunderstack.
1. Installation
bun add bunderstack [email protected] @solidjs/[email protected] @solidjs/[email protected] drizzle-orm valibot @libsql/client @orpc/client
bun add -d vite [email protected]2. Configuration (src/bunderstack.ts)
// src/bunderstack.ts
import { bunderstack } from 'bunderstack'
import { libsql } from 'bunderstack/libsql'
import { provision } from 'bunderstack/provision'
import * as schema from './schema'
export const backend = bunderstack({
schema,
database: {
adapter: libsql(),
url: process.env.DATABASE_URL || 'file:./data.db',
},
auth: { emailAndPassword: { enabled: true } },
realtime: true,
})
export const app = await backend.start()
export type App = typeof app
await provision(app)3. Unified HTTP Server (src/server.ts)
In production, src/server.ts routes all /api/* requests to app.handler, serves compiled client assets, and renders Solid 2 components via renderToString:
// src/server.ts
import { renderToString } from '@solidjs/web/server'
import { app } from './bunderstack'
import App from './App'
const port = Number(process.env.PORT) || 3000
Bun.serve({
port,
async fetch(req) {
const url = new URL(req.url)
// 1. Route API, auth, storage, jobs, and health check
if (url.pathname.startsWith('/api/')) {
return app.handler(req)
}
// 2. Serve static client assets from dist/client
const filePath = `dist/client${url.pathname}`
const file = Bun.file(filePath)
if (await file.exists()) {
return new Response(file)
}
// 3. Render Solid 2 SSR HTML
const html = renderToString(() => <App url={url.pathname} />)
return new Response(
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script type="module" src="/entry-client.js"></script>
</head>
<body>
<div id="app">${html}</div>
</body>
</html>`,
{ headers: { 'Content-Type': 'text/html; charset=utf-8' } },
)
},
})
console.log(`Solid 2 + Bunderstack running on port ${port}`)4. Client Setup (src/api.ts)
// src/api.ts
import { createClient } from 'bunderstack/query'
import { QueryClient } from '@tanstack/solid-query'
import type { App } from './bunderstack'
export const queryClient = new QueryClient()
export const api = createClient<App>({ queryClient, baseUrl: '/api' })5. Package Scripts & Deployment
{
"bunderstack": {
"entry": "src/bunderstack.ts"
},
"scripts": {
"build": "vite build --outDir dist/client && vite build --ssr src/entry-server.tsx --outDir dist/server",
"start": "bun src/server.ts"
}
}Running bunx bunderstack blueprint detects solid-js and sets framework: solid.
TanStack Router / React SPA (Vite)
In a Single Page Application (SPA) with Vite and React (or TanStack Router), the frontend bundle runs entirely in the browser and connects to a Bunderstack backend.
1. Configuration & Server (server.ts or src/bunderstack.ts)
// server.ts
import { bunderstack } from 'bunderstack'
import { libsql } from 'bunderstack/libsql'
import { provision } from 'bunderstack/provision'
import * as schema from './schema'
export const backend = bunderstack({
schema,
database: {
adapter: libsql(),
url: process.env.DATABASE_URL || 'file:./data.db',
},
auth: { emailAndPassword: { enabled: true } },
realtime: true,
})
export const app = await backend.start()
export type App = typeof app
await provision(app)
const port = Number(process.env.PORT) || 3000
Bun.serve({
port,
async fetch(req) {
const url = new URL(req.url)
if (url.pathname.startsWith('/api/')) {
return app.handler(req)
}
const file = Bun.file(`dist/${url.pathname}`)
if (await file.exists()) return new Response(file)
return new Response(Bun.file('dist/index.html'))
},
})2. Client Setup (src/api.ts)
// src/api.ts
import { createClient } from 'bunderstack/query'
import { QueryClient } from '@tanstack/react-query'
import type { App } from '../server'
export const queryClient = new QueryClient()
export const api = createClient<App>({
queryClient,
baseUrl: '/api',
})3. Vite Proxy for Development (vite.config.ts)
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/api': 'http://localhost:3000',
},
},
})Bun SSR (Pure Web Standards Bun Server)
For server-rendered applications using Bun with template literals, JSX, HTMX, Alpine.js, or Web Components without a full frontend framework.
1. Configuration (src/bunderstack.ts)
// src/bunderstack.ts
import { bunderstack } from 'bunderstack'
import { libsql } from 'bunderstack/libsql'
import { provision } from 'bunderstack/provision'
import * as schema from './schema'
export const backend = bunderstack({
schema,
database: {
adapter: libsql(),
url: process.env.DATABASE_URL || 'file:./data.db',
},
auth: { emailAndPassword: { enabled: true } },
realtime: true,
})
export const app = await backend.start()
export type App = typeof app
await provision(app)2. Server Entry (src/server.ts)
// src/server.ts
import { app } from './bunderstack'
const port = Number(process.env.PORT) || 3000
Bun.serve({
port,
async fetch(req) {
const url = new URL(req.url)
// Route API requests (oRPC, Auth, Storage, Jobs, Health)
if (url.pathname.startsWith('/api/')) {
return app.handler(req)
}
// Server-rendered HTML response
return new Response(
`<!DOCTYPE html>
<html>
<head><title>Bun SSR App</title></head>
<body>
<h1>Welcome to Bunderstack on Bun SSR</h1>
</body>
</html>`,
{ headers: { 'Content-Type': 'text/html; charset=utf-8' } },
)
},
})3. Package Scripts & Deployment
{
"scripts": {
"build": "bun build ./src/client.ts --outdir ./dist",
"start": "bun src/server.ts"
}
}Running bunx bunderstack blueprint detects a generic Bun project and assigns framework: bun-ssr.
Next.js (App Router)
1. Lazy Singleton (lib/bunderstack.ts)
// lib/bunderstack.ts
import { bunderstack } from 'bunderstack'
import { provision } from 'bunderstack/provision'
import * as schema from './schema'
const backend = bunderstack({
schema,
auth: { emailAndPassword: { enabled: true } },
})
let _app: Awaited<ReturnType<typeof backend.start>> | null = null
export async function getApp() {
if (!_app) {
_app = await backend.start()
await provision(_app)
}
return _app
}2. Route Handler (app/api/[...bunderstack]/route.ts)
// app/api/[...bunderstack]/route.ts
import { getApp } from '@/lib/bunderstack'
export async function GET(req: Request) {
return (await getApp()).handler(req)
}
export const POST = GET
export const PATCH = GET
export const DELETE = GETNext.js runs on Node.js. If connecting to a PostgreSQL database, install the Node driver:
npm install postgres. When running under Bun, the nativeBun.sqldriver is selected automatically.
Other Web Standards Runtimes
Because app.handler implements the Web Standard (req: Request) => Promise<Response> signature, it integrates into any standard runtime in one line:
Hono
import { Hono } from 'hono'
import { app } from './bunderstack'
// Delegate all /api/* routes to Bunderstack
const server = createHonoApp()
server.all('/api/*', (c) => app.handler(c.req.raw))
export default serverAstro
// src/pages/api/[...all].ts
import type { APIRoute } from 'astro'
import { app } from '../../bunderstack'
export const ALL: APIRoute = ({ request }) => app.handler(request)Deployment Blueprint Comparison
When generating a deployment contract via bunx bunderstack blueprint, Bunderstack identifies the application type and specifies it in bunderstack.blueprint.yaml:
| Framework Type | Blueprint framework | Detection Rule | Typical build Script | Typical start Script |
|---|---|---|---|---|
| TanStack Start | tanstack-start | @tanstack/react-start in dependencies | vite build | bun .output/server/index.mjs |
| Solid 2 | solid | solid-js or @solidjs/web in dependencies | vite build && vite build --ssr ... | bun src/server.ts |
| Bun SSR | bun-ssr | Standard Bun scripts present | bun build ... | bun src/server.ts |
| Custom / SPA | custom | Custom specified framework | Custom build command | Custom startup command |