Claude-skills bun-nextjs
This skill should be used when the user asks about "Next.js with Bun", "Bun and Next", "running Next.js on Bun", "Next.js development with Bun", "create-next-app with Bun", or building Next.js applications using Bun as the runtime.
install
source · Clone the upstream repo
git clone https://github.com/secondsky/claude-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/secondsky/claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/bun/skills/bun-nextjs" ~/.claude/skills/secondsky-claude-skills-bun-nextjs && rm -rf "$T"
manifest:
plugins/bun/skills/bun-nextjs/SKILL.mdsource content
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 |
|---|---|---|
| Wrong runtime | Use |
| Missing dependency | Run |
| Server/client diff | Check data fetching |
| 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