Architecture
Repository layout
index.ts the adapter: options + adapt()
templates/ runtime entrypoints, compiled into the app
├── index.ts Bun.serve() setup, graceful shutdown
├── handler.ts static files, health endpoint, SvelteKit SSR
├── env.ts env() lookup with envPrefix
└── healthcheck.ts the healthcheck binary
internal.d.ts types for the virtual modules templates import
examples/ compiled-app and native-addon (compile: false)
test/ integration tests (build + run the examples)What adapt() does
- Writes client assets to
out/client/and prerendered pages toout/prerendered/(compressing them ifprecompressis on). - Writes the SvelteKit server and a
manifest.jsinto.svelte-kit/adapter-bun/. - Copies
templates/next to it, swapping the placeholder tokens —ENV,HANDLER,MANIFEST,SERVERbecome relative imports;ENV_PREFIX,BUILD_OPTIONS,SERVE_OPTIONSbecome JSON literals. - Prepends
import "./server/instrumentation.server.js"to the entrypoint if the app has one, so it loads before anything else. - Runs
Bun.buildontemplates/index.ts—compileto a binary, or a plainindex.jswhencompile: false— and compileshealthcheck.tsseparately.
Templates ship as raw .ts; Bun transpiles them during the compile, so the
published package has no build step for them.
Request flow
handler.ts answers, in order:
GETon the health path → JSON status.- A prerendered page or client asset, when
serveAssetsis on. - Everything else →
server.respond(), with the URL rebuilt fromORIGINor the forwarded headers andgetClientAddress()wired toADDRESS_HEADERor the socket.
platform is { request, server } — the raw request and the Bun.Server.
Finding assets at runtime
A compiled binary's import.meta.dir is virtual, so assets are located from
dirname(process.execPath). A plain index.js uses import.meta.dir instead,
since process.execPath is the bun binary there. ASSETS_DIR overrides both.
Loading under Node
index.ts only touches Bun inside adapt(). Tooling that loads
svelte.config.js under Node — svelte-check, the language server,
svelte-kit sync — works without Bun.
This guide lives in the project repo: edit it there, and this page follows within a day.