Packages
@thexjs/adapter-vercel
Vercel Build Output API v3 adapter for x apps. Produces a .vercel/output/ tree directly — no vercel.json required.
bun add -d @thexjs/adapter-vercelx build --adapter vercelvercel deploy --prebuilt
What it produces
The adapter writes a complete Build Output API v3 tree:
.vercel/output/config.json routes: filesystem first, then fallback -> renderstatic/ HTML, CSS, island JS chunks (served via Vercel's CDN)functions/render.func/.vc-config.json runtime: nodejs20.x, handler: index.mjsindex.mjs standalone SSR + API bundle
If your app is 100% static (every page is mode = "static", no API routes, no server actions), no function is emitted at all — config.json only does filesystem routing.
How it works
- Runs @thexjs/core's normal build() to prerender every static-mode page and content entry, and to compile island bundles. This becomes static/.
- Separately resolves every server-mode page, API route, layout, middleware file, and server-action file at build time (reusing @thexjs/core's own scanners), so nothing at request time depends on walking the filesystem or on a dynamic import(path) of a .tsx file — both of those only work under Bun.
- Transpiles each of those files from Bun-flavored TSX/TS into plain Node ESM, then bundles them together with @thexjs/core and React into one standalone index.mjs.
- Bridges Vercel's Node-style (req, res) function invocation to x's Web-standard Request/ Response handler, streaming the response body through (so renderToReadableStream-based SSR streams end-to-end, not just non-streaming pages).
Options
VercelAdapterOptions
interface VercelAdapterOptions { projectRoot?: string; pagesDir?: string; routesDir?: string; apiDir?: string; layoutsDir?: string; actionsDir?: string; contentDir?: string; outputDir?: string; // default: ".vercel/output" runtime?: "nodejs18.x" | "nodejs20.x" | "nodejs22.x"; additionalStaticDirs?: string[]; security?: { csrf?: { allowedOrigins?: string[]; requireToken?: boolean; disabled?: boolean }; headers?: SecurityHeadersOptions | false; rateLimit?: { limit?: number; windowMs?: number } | false; }; observability?: { logging?: boolean; // default: true };}The adapter accepts the same directory options as x.config.ts. Security and observability options are forwarded into the generated render function so your Vercel deployment gets the same CSRF protection, security headers, rate limiting, and structured logging as your Bun server.
Usage with x.config.ts
The adapter reads your x.config.ts automatically — no extra configuration needed. Just install the adapter and run:
bun add -d @thexjs/adapter-vercelx build --adapter vercelvercel deploy --prebuilt
Known limitations
- ISR-style revalidate caching (in-memory in the long-running Bun dev/prod server) doesn't carry over to stateless serverless invocations — use Vercel's own Cache-Control/CDN caching on the response instead.
- Markdown contentDir entries are always statically prerendered (matches @thexjs/core's build() behavior today) — there's no server-mode content route yet.
- Custom errorReporter functions and health.checks cannot be serialized into the standalone serverless bundle. The adapter provides /healthz (liveness) without custom readiness checks.