Build & Deploy
Build & deploy
x produces optimized production builds with static HTML export, a server entry point, and content collection rendering — all in a single command.
Build command
Run x build to produce a production build. The build output goes to a .x/ directory.
x build[x] resolving routes...[x] found 12 routes[x] building static pages...[x] building server bundle...[x] rendering content collections...[x] build complete in 1.2s
Output structure
The .x/ directory contains everything needed to deploy — static files, server bundle, and assets.
.x/client/ // Client-side assetsassets/*.js // Bundled JS*.css // Extracted CSSserver/ // Server entry pointindex.js // Bun server bundlestatic/ // Prerendered HTML pagesindex.htmlabout/index.htmlblog/hello-world/index.htmlx.json // Build manifest
Static page export
Pages with mode = "static" are exported as HTML files in .x/static/. Each page is fully rendered at build time, including its loader output. For dynamic-static pages (static pages with dynamic params), x generates one HTML file per unique path.
Server entry
Server-rendered pages are bundled into .x/server/index.js. This file contains all server routes, API handlers, server functions, and middleware — everything needed to run the dynamic parts of your app.
Production server
Use x start to run the production server. It serves static files from .x/static/ and handles dynamic routes via the server bundle.
x start[x] production server running at http://localhost:3000
Docker deployment
Deploy with a minimal Docker image using the official Bun runtime. The build output is self-contained.
FROM oven/bun:1 AS buildWORKDIR /appCOPY package.json bun.lock .RUN bun installCOPY . .RUN x buildFROM oven/bun:1-slimWORKDIR /appCOPY --from=build /app/.x .xEXPOSE 3000CMD ["x", "start"]Content collections in builds
During x build, content collections are scanned and rendered. Each markdown file becomes a static HTML page if its route uses static mode, or is available for server-rendered routes to consume.
Deploy to Vercel
Vercel doesn't run a long-lived Bun process, so it uses a different adapter: @thexjs/adapter-vercel builds a .vercel/output/ tree (Build Output API v3) directly — no vercel.json required.
bun add -d @thexjs/adapter-vercelx build --adapter vercelvercel deploy --prebuilt
If every page in your app uses mode = "static" (no API routes, no server actions), no function is emitted at all — just static files and filesystem routing. Server-mode pages, API routes, and server actions run inside a single bundled nodejs20.x function.