Documentation menu

Bun, Deno, Netlify and Vercel

Run the gateway on Bun, Deno, Netlify Edge Functions or Vercel: wrap the fetch handler you already have, or add routing middleware in front of your site.

Last updated

Wrap the handler you already have

Each of these runtimes serves requests through a web-standard (request) => Response function. Wrap yours with the fetch middleware: agents asking for markdown are answered by the gateway, and every other request reaches your handler with Vary: Accept added to its response.

Using a framework on one of these runtimes? Use that framework’s recipe on the frameworks page. Cloudflare Workers have their own adapter.

Bun

server.ts
// server.ts
import { createFetchMiddleware } from '@rebilder/gateway/fetch'
import { gatewayConfig } from './gateway-config'
import { app } from './app' // your existing (request) => Response handler

const gateway = createFetchMiddleware(gatewayConfig)

Bun.serve({ fetch: (request) => gateway(request, () => app(request)) })

Requests matched by the routes option of Bun.serve skip fetch. If you use routes, wrap those handlers the same way.

Deno

main.ts
// main.ts
import { createFetchMiddleware } from '@rebilder/gateway/fetch'
import { gatewayConfig } from './gateway-config.ts'
import { app } from './app.ts' // your existing (request) => Response handler

const gateway = createFetchMiddleware(gatewayConfig)

Deno.serve((request) => gateway(request, () => app(request)))

Netlify Edge Functions

netlify/edge-functions/rebilder.ts
// netlify/edge-functions/rebilder.ts
import type { Config, Context } from '@netlify/edge-functions'
import { createFetchMiddleware } from '@rebilder/gateway/fetch'
import { gatewayConfig } from '../../gateway-config.ts'

const gateway = createFetchMiddleware(gatewayConfig)

export default (request: Request, context: Context) => gateway(request, () => context.next())

export const config: Config = { path: '/*', excludedPath: ['/*.css', '/*.js'] }

The edge function sits in front of your site, whatever built it. Agents are answered at the edge; everything else continues to your site through context.next(). Narrow path to the pages your sources answer, and keep static assets in excludedPath.

Vercel

In a Next.js project, use the Next.js adapter. For any other project, add Routing Middleware at the project root:

middleware.ts
// middleware.ts at the project root (Vercel Routing Middleware, outside Next.js)
import { next } from '@vercel/functions'
import { handleRequest, negotiationHeaders } from '@rebilder/gateway/fetch'
import { gatewayConfig } from './gateway-config'

export default async function middleware(request: Request) {
  const served = await handleRequest(request, gatewayConfig)
  return served ?? next({ headers: Object.fromEntries(negotiationHeaders(gatewayConfig, new URL(request.url))) })
}

Routing Middleware runs before your site and cannot read its response, so the recipe answers agents with handleRequest and passes the negotiation headers to next() for everything else. Limit it to your pages with export const config = { matcher: [...] }.

If a single Vercel Function already serves your whole site, give the edge adapter your handler as the fallback instead:

api/[...path].ts
// api/[...path].ts: a Vercel Function that answers the whole site itself
import { createGatewayFetchHandler } from '@rebilder/gateway/edge'
import { gatewayConfig } from '../gateway-config'
import { app } from '../app' // your existing (request) => Response handler

export default { fetch: createGatewayFetchHandler(gatewayConfig, { fallback: app }) }