Bun Next.js
Run Next.js applications with Bun for faster development and builds.
Quick Start
Create new Next.js project with Bun
bunx create-next-app@latest my-app cd my-app
Install dependencies
bun install
Development
bun run dev
Build
bun run build
Production
bun run start
Project Setup
package.json
{ "scripts": { "dev": "next dev --turbo", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "next": "^16.1.1", "react": "^19.2.3", "react-dom": "^19.2.3" } }
Use Bun as Runtime
{ "scripts": { "dev": "bun --bun next dev", "build": "bun --bun next build", "start": "bun --bun next start" } }
The --bun flag forces Next.js to use Bun's runtime instead of Node.js.
Configuration
next.config.js
/** @type {import('next').NextConfig} */ const nextConfig = { // Enable experimental features experimental: { // Turbopack (faster dev) turbo: {}, },
// Server-side Bun APIs serverExternalPackages: ["bun:sqlite"],
// Webpack config (if needed) webpack: (config, { isServer }) => { if (isServer) { // Allow Bun-specific imports config.externals.push("bun:sqlite", "bun:ffi"); } return config; }, };
module.exports = nextConfig;
Using Bun APIs in Next.js
Server Components
// app/page.tsx (Server Component) import { Database } from "bun:sqlite";
export default async function Home() { const db = new Database("data.sqlite"); const users = db.query("SELECT * FROM users").all(); db.close();
return ( <div> {users.map((user) => ( <p key={user.id}>{user.name}</p> ))} </div> ); }
API Routes
// app/api/users/route.ts import { Database } from "bun:sqlite";
export async function GET() { const db = new Database("data.sqlite"); const users = db.query("SELECT * FROM users").all(); db.close();
return Response.json(users); }
export async function POST(request: Request) { const body = await request.json();
const db = new Database("data.sqlite"); db.run("INSERT INTO users (name) VALUES (?)", [body.name]); db.close();
return Response.json({ success: true }); }
File Operations
// app/api/files/route.ts export async function GET() { const file = Bun.file("./data/config.json"); const config = await file.json();
return Response.json(config); }
export async function POST(request: Request) { const data = await request.json(); await Bun.write("./data/config.json", JSON.stringify(data, null, 2));
return Response.json({ saved: true }); }
Server Actions
// app/actions.ts "use server";
import { Database } from "bun:sqlite"; import { revalidatePath } from "next/cache";
export async function createUser(formData: FormData) { const name = formData.get("name") as string;
const db = new Database("data.sqlite"); db.run("INSERT INTO users (name) VALUES (?)", [name]); db.close();
revalidatePath("/users"); }
export async function deleteUser(id: number) { const db = new Database("data.sqlite"); db.run("DELETE FROM users WHERE id = ?", [id]); db.close();
revalidatePath("/users"); }
Middleware
// middleware.ts import { NextResponse } from "next/server"; import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) { // Check auth const token = request.cookies.get("token");
if (!token && request.nextUrl.pathname.startsWith("/dashboard")) { return NextResponse.redirect(new URL("/login", request.url)); }
return NextResponse.next(); }
export const config = { matcher: ["/dashboard/:path*"], };
Environment Variables
.env.local
DATABASE_URL=./data.sqlite API_SECRET=your-secret-key
// Access in server components/actions const dbUrl = process.env.DATABASE_URL; const secret = process.env.API_SECRET;
// Expose to client (prefix with NEXT_PUBLIC_) // .env.local NEXT_PUBLIC_API_URL=https://api.example.com
Deployment
Build for Production
bun run build bun run start
Docker
FROM oven/bun:1
WORKDIR /app
COPY package.json bun.lockb ./ RUN bun install --frozen-lockfile
COPY . . RUN bun run build
EXPOSE 3000
CMD ["bun", "run", "start"]
Vercel
Install Vercel CLI
bun add -g vercel
Deploy
vercel
Note: Vercel's edge runtime uses V8, not Bun. Bun APIs work in:
-
Server Components (Node.js runtime)
-
API Routes (Node.js runtime)
-
Server Actions (Node.js runtime)
Performance Tips
Use Turbopack for faster dev:
bun run dev --turbo
Prefer Server Components - Less JavaScript sent to client
Use Bun SQLite instead of external databases for simple apps
Enable compression:
// next.config.js module.exports = { compress: true, };
Common Errors
Error Cause Fix
Cannot find bun:sqlite
Wrong runtime Use bun --bun next dev
Module not found
Missing dependency Run bun install
Hydration mismatch
Server/client diff Check data fetching
Edge runtime error
Bun API on edge Use Node.js runtime
When to Load References
Load references/app-router.md when:
-
App Router patterns
-
Route groups
-
Parallel routes
Load references/caching.md when:
-
Data caching strategies
-
Revalidation patterns
-
Static generation