Vercel Deployment#
BunTok provides a Bun runtime configuration for Vercel. Select "Yes" when prompted during buntok init to create vercel.json.
How It Works#
The generated server.ts entry point starts a local Bun server with app.listen(). A serverless deployment uses the app's fetch handler instead of binding a local port.
server.ts - local server entry point#
import { app } from "./src/index";
import { env } from "./src/env";
app.listen(env.PORT);Why `app.listen()` Works Everywhere#
- Local dev -
app.listen()callsBun.serve()and binds to a port - Serverless deployment - expose
app.fetchthrough the deployment adapter instead of binding a local port - Keep the local server entry point separate from the serverless adapter.
app.fetch() vs app.listen()#
| Method | Use Case | Binds Port |
|---|---|---|
| app.listen(port) | Local development | Yes |
| app.fetch(request) | Vercel/serverless | No |
| app.request(input, init?) | Testing | No |
vercel.json#
Generated by buntok init when Vercel is selected:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "bun",
"bunVersion": "1.4.x",
"outputDirectory": "buntok",
"regions": ["sin1"]
}framework: "bun"- tells Vercel to use Bun runtime (required for GitHub-triggered deploys).bunVersion: "1.4.x"- pins the Bun runtime version.outputDirectory: "buntok"- build output directory produced bybuntok build; required for a successful deploy (the build fails withUNRESOLVED_ENTRYotherwise).regions: ["sin1"]- deploy to the Singapore region (closest to ID users; lower latency).
Deploy#
# Install Vercel CLI
npm i -g vercel
# Deploy (preview)
vercel
# Production deploy
vercel --prodLocal Development#
bun run dev # runs: bun --watch server.tsThe dev script runs server.ts, which calls app.listen() for local development. A serverless deployment uses app.fetch instead.
Project Structure#
my-app/
├── src/
│ ├── index.ts # export const app = new Buntok()
│ ├── env.ts # Buntok.validateEnv({ PORT, ... })
│ ├── controllers/
│ ├── services/
│ └── repositories/
├── server.ts # app.listen(env.PORT) - local server entry point
├── vercel.json # Vercel config (framework: "bun")
├── package.json
└── ...Common Issues#
SyntaxError: Unexpected token in import call#
This error occurs when package.json is missing "type": "module". Without it, Vercel's Node.js runtime treats .js files as CommonJS, causing ESM import syntax to fail.
package.json includes "type": "module". BunTok requires ESM.{
"name": "my-app",
"type": "module",
"scripts": {
"dev": "bun --watch server.ts",
"build": "bun run build.ts",
"start": "node dist/index.js"
}
}`cannot read properties of undefined (reading 'readFile')`#
This error occurs when typescript is listed as a peerDependency in your project. Vercel tries to resolve peer dependencies during build, and if the version doesn't exist (e.g., typescript@^7), the TypeScript compiler fails to load.
typescript from peerDependencies in your package.json. Keep it only as a devDependency if needed. TypeScript is already included transitively through tsup, @prisma/client, and other build tools.{
"peerDependencies": {
"bun": ">=1.2.0"
// ❌ Don't add "typescript" here
},
"devDependencies": {
"typescript": "^5.0.0" // ✅ Only as devDependency
}
}Build fails with `Module not found`#
Make sure all dependencies are installed before building. Run bun install locally and verify node_modules exists. For Vercel, ensure your installCommand or buildCommand includes dependency installation.
Notes#
- WebSocket routes require a runtime that supports WebSockets; verify platform support before deploying.
- For monorepos, set the Root Directory in Vercel dashboard to your project subfolder
app.listen() for a local Bun server. Use app.fetch through your platform's serverless adapter when the platform invokes a fetch handler.