Next.js deployment adapter for Bun with SQLite-based ISR caching.
Produces a self-contained bun-dist/ directory — similar to Next.js output: 'standalone' — with optimal build size and SQLite-based caching. Only bun-dist/ needs to be copied to your Docker image.
Built on the official Next.js Adapter API (stable in Next.js 16.2+). Based on the reference Bun adapter by the Next.js team.
Note: This package exists because the official adapter is not yet published to npm. It will be deprecated once the official adapter is available as an npm package.
- Self-contained output —
bun-dist/includes everything needed to run:.next/build output, tracednode_modules/, server entry, static assets, and SQLite cache - Standalone tracing — leverages Next.js
output: 'standalone'for reliable dependency tracing, works in both monorepos and single-app repos - SQLite-based ISR cache (
bun:sqlite) — atomic writes, tag-based invalidation, revalidation locking - Image optimization cache — optimized images stored in SQLite with expiry tracking
- Two cache modes —
sqlite(direct access, lower overhead) orhttp(default, multi-process safe) - Preload support — bundle runtime preload modules (e.g. loggers) into the output
- Full Next.js coverage — App Router, Pages Router, ISR, middleware,
next/image, Server Actions, draft mode
bun add next-adapter-bunThe package provides two ready-to-use presets and a factory for custom configuration.
Direct SQLite access with lower overhead. Best for single-instance deployments (Docker containers, single-process servers).
// next.config.ts
import { fileURLToPath } from 'node:url'
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
adapterPath: fileURLToPath(import.meta.resolve('next-adapter-bun/sqlite')),
}
export default nextConfigUses an internal HTTP endpoint for cache operations. Best for multi-worker or multi-process setups.
// next.config.ts
import { fileURLToPath } from 'node:url'
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
adapterPath: fileURLToPath(import.meta.resolve('next-adapter-bun')),
}
export default nextConfigFor full control, create a custom adapter entry file:
// bun-adapter.ts
import { createBunAdapter } from 'next-adapter-bun'
export default createBunAdapter({
cacheHandlerMode: 'sqlite',
deploymentHost: 'app.example.com',
preload: ['jsonl-logger/preload'],
})// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
adapterPath: new URL('./bun-adapter.ts', import.meta.url).pathname,
}
export default nextConfigThe build is a two-step process:
# 1. Build with Next.js (adapter hooks fire during build)
bun --bun next build
# 2. Package standalone output into bun-dist/
next-adapter-bun package
# Run
bun bun-dist/server.jsWhy two steps? The adapter's onBuildComplete hook fires before Next.js generates the standalone directory. The package CLI bridges this gap by copying the standalone output into bun-dist/ after the build completes.
You can chain them in your build script:
{
"scripts": {
"build": "next build && next-adapter-bun package"
}
}Or run the CLI in your Dockerfile after the build step.
Options for createBunAdapter():
| Option | Type | Default | Description |
|---|---|---|---|
outDir |
string |
'bun-dist' |
Output directory for adapter build |
port |
number |
3000 |
Default listen port (overridden by PORT env) |
hostname |
string |
'0.0.0.0' |
Default listen hostname |
deploymentHost |
string |
— | Canonical host for Server Actions CSRF |
cacheHandlerMode |
'sqlite' | 'http' |
'http' |
Cache transport mode |
cacheEndpointPath |
string |
'/_adapter/cache' |
Internal cache endpoint (HTTP mode) |
cacheAuthToken |
string |
— | Cache endpoint auth token (HTTP mode) |
preload |
string[] |
— | Modules to bundle into output node_modules/ |
| Variable | Description |
|---|---|
PORT |
Override listen port |
NEXT_HOSTNAME |
Preferred hostname for internal origin |
NEXT_PROJECT_DIR |
Override project root (default: parent of bun-dist/) |
BUN_ADAPTER_CACHE_HTTP_TOKEN |
Override cache endpoint auth token |
BUN_ADAPTER_KEEP_ALIVE_TIMEOUT |
Override HTTP keep-alive timeout (ms) |
The bun-dist/ directory is fully self-contained. Copy its contents to your Docker image — no full node_modules required.
FROM oven/bun:1.3-alpine AS build
WORKDIR /app
COPY . .
RUN bun install --frozen-lockfile \
&& bun --bun next build \
&& next-adapter-bun package
FROM oven/bun:1.3-alpine
WORKDIR /app
COPY --from=build /app/bun-dist/ ./
ENV NODE_ENV=production PORT=3000 NEXT_PROJECT_DIR=/app
EXPOSE 3000
CMD ["bun", "server.js"]When the app lives in a subdirectory (e.g. apps/web):
FROM oven/bun:1.3-alpine AS build
WORKDIR /app
COPY . .
RUN bun install --frozen-lockfile \
&& bun --bun next build --filter=web \
&& cd apps/web && next-adapter-bun package
FROM oven/bun:1.3-alpine
WORKDIR /app
COPY --from=build /app/apps/web/bun-dist/ ./
ENV NODE_ENV=production PORT=3000 NEXT_PROJECT_DIR=/app
EXPOSE 3000
CMD ["bun", "server.js"]Tip: If your app needs runtime modules not traced by Next.js (e.g. a logger preload), either use the
preloadadapter option or add a separateCOPYin your Dockerfile.
Step 1 — next build (adapter hooks):
modifyConfigsetsoutput: 'standalone'and injects the SQLite cache handleronBuildCompleteprocesses build outputs:- Stages static assets to
bun-dist/static/ - Seeds prerender cache into
bun-dist/cache.db - Writes deployment manifest, runtime config, and server entry
- Copies runtime modules (cache handlers) to
bun-dist/runtime/
- Stages static assets to
Step 2 — next-adapter-bun package (CLI):
- Copies
.next/standalone/intobun-dist/:- App files (
.next/,package.json, localnode_modules/) - Hoisted
node_modules/(merged in monorepos) - Preload modules (if configured)
- App files (
- Cleans up build-time caches and syncs runtime modules
bun-dist/server.js:
- Reads deployment manifest for config (port, hostname, cache mode)
- Boots Next.js via
createNext()with runtime config overrides - Creates an HTTP server with:
- Cache-control header normalization for deployed environments
- Server Actions body buffering (Bun compatibility workaround)
- Optional internal cache HTTP endpoint (HTTP mode)
bun-dist/
├── server.js # Server entry point
├── .next/ # Next.js build output (from standalone)
│ ├── server/ # Server chunks, manifests
│ ├── BUILD_ID
│ └── ...
├── node_modules/ # Traced dependencies (from standalone)
│ ├── next/
│ ├── react/
│ ├── sharp/ # (if used)
│ └── ...
├── runtime/ # Adapter cache handlers
├── static/ # Static assets for direct serving
├── cache.db # SQLite prerender cache (seeded)
├── deployment-manifest.json # Build metadata
└── runtime-next-config.json # Runtime config overrides
This package implements the Next.js Adapter API:
modifyConfig— setsoutput: 'standalone', injects cache handler pathsonBuildComplete— processes build outputs (routes, prerenders, static assets)
For more details, see the Deploying to Platforms guide.
MIT