> The same package supports SvelteKit 3 (currently a prerelease). The adapter detects which SvelteKit is building the app and runs the matching implementation, so there is nothing to…
> Source: https://orochibraru.com/svelte-smol/docs/sveltekit-3 · Site index: https://orochibraru.com/llms.txt

# SvelteKit 3

The same package supports SvelteKit 3 (currently a prerelease). The adapter
detects which SvelteKit is building the app and runs the matching
implementation, so there is nothing to switch. On SvelteKit 3, static assets and
prerendered pages are embedded in the executable, and the options follow the
official [`@sveltejs/adapter-bun`](https://svelte.dev/docs/kit/adapter-bun).

Options from the other SvelteKit version fail the build with an error naming
them, see [Migrating from the SvelteKit 2 options](#migrating-from-the-sveltekit-2-options).

## Install

```bash
bun add -d @orochibraru/svelte-smol @sveltejs/kit@next
```

## Usage

```typescript
// vite.config.js
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
import adapter from "@orochibraru/svelte-smol";

export default defineConfig({
  plugins: [sveltekit({ adapter: adapter() })],
});
```

The build runs under the Bun runtime:

```bash
bun run --bun vite build
```

## Output

```text
build/
├── server        # the executable, assets embedded
└── healthcheck   # tiny probe for Docker HEALTHCHECK
```

```bash
./build/server
```

Static assets and prerendered pages are served with an `ETag`, `Last-Modified`
and `Accept-Ranges: bytes`, the same way whether they are embedded or on disk.
A single byte `Range` gets a `206` (so `<video>` can seek without downloading
the whole file), a range past the end a `416`, and `If-Range` is honoured.
Multiple ranges and malformed headers are ignored and answered with the full
body. Ranges always apply to the uncompressed file, never to a `.br` / `.gz`
variant.

### `buildOptions.compile: false`

A native (`.node`) addon like `sharp` can't be embedded in a binary. Set
`buildOptions: { compile: false }` to emit a plain bundle instead:

```text
build/
├── index.js       # the server entry, run with `bun`
├── server/        # split chunks
├── healthcheck    # still a compiled binary
├── client/
└── prerendered/
```

```bash
bun ./build/index.js
```

Pure-JS dependencies are still bundled. Native addons resolve from
`node_modules` at runtime, so ship a production install alongside.

## Options

```typescript
adapter({
  out: "build", // output directory
  precompress: false, // .br/.gz variants (compile: false only)
  envPrefix: "", // prefix for the runtime env vars below
  serverOptions: {}, // JSON-serializable Bun.serve() defaults; env vars win
  buildOptions: {
    compile: true, // true | "bun-linux-x64-musl" | { target, outfile, … } | false
    // also: sourcemap, minify, bytecode, banner, footer, drop, features,
    // optimizeImports, splitting
  },
  healthcheck: true, // or { path: "/healthz" }, or false
});
```

`compile` accepts any Bun compile target string (`"bun-linux-x64"`,
`"bun-linux-arm64-musl"`, `"bun-darwin-arm64"`, `"bun-windows-x64"`, …) to
cross-compile; the healthcheck binary uses the same target.

## Runtime environment variables

| Variable                  | Default    | Purpose                                                             |
| ------------------------- | ---------- | ------------------------------------------------------------------- |
| `HOST`                    | `0.0.0.0`  | Listen address                                                      |
| `PORT`                    | `3000`     | Listen port                                                         |
| `SOCKET_PATH`             | none       | Listen on a Unix socket instead of `HOST`/`PORT`                    |
| `ORIGIN`                  | none       | Public origin, e.g. `https://my.site`; overrides `paths.origin`     |
| `REUSE_PORT`              | `false`    | `SO_REUSEPORT`                                                      |
| `IPV6_ONLY`               | `false`    | Disable dual-stack                                                  |
| `CONNECTION_IDLE_TIMEOUT` | `10`       | Bun socket idle timeout in seconds, max 255 (SSE responses opt out) |
| `BODY_SIZE_LIMIT`         | `512K`     | Max request body (`K`/`M`/`G` suffixes, or `Infinity`)              |
| `SHUTDOWN_TIMEOUT`        | `30`       | Seconds to drain in-flight requests on `SIGINT`/`SIGTERM`           |
| `DEVELOPMENT`             | `false`    | Bun.serve development mode                                          |
| `PROTOCOL_HEADER`         | none       | Header carrying the forwarded protocol (e.g. `x-forwarded-proto`)   |
| `HOST_HEADER`             | none       | Header carrying the forwarded host                                  |
| `PORT_HEADER`             | none       | Header carrying the forwarded port                                  |
| `ADDRESS_HEADER`          | none       | Header carrying the client address (e.g. `x-forwarded-for`)         |
| `XFF_DEPTH`               | `1`        | Trusted-proxy depth when `ADDRESS_HEADER=x-forwarded-for`           |
| `HEALTHCHECK_PATH`        | `/_health` | Endpoint the `healthcheck` binary probes                            |
| `HEALTHCHECK_TIMEOUT`     | `2000`     | `healthcheck` binary request timeout in ms                          |

Set `envPrefix` to namespace these (`envPrefix: "MY_APP_"` → `MY_APP_PORT`).
The public origin comes from `ORIGIN`, read at runtime so one build can be
deployed at several origins, then SvelteKit's `paths.origin` config, then the
request headers above.

## Health check

With `healthcheck` enabled (the default) the server answers `GET /_health` with
`{ "status": "ok", "uptime": … }`, and the build also produces
`build/healthcheck`, which probes it over loopback (or the Unix socket) and
exits `0` when healthy, `1` otherwise:

```dockerfile
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
	CMD ["./build/healthcheck"]
```

It reads the same `HOST` / `PORT` / `SOCKET_PATH` as the server.

## Migrating from the SvelteKit 2 options

| SvelteKit 2                       | SvelteKit 3                                       |
| --------------------------------- | ------------------------------------------------- |
| `compile: false`                  | `buildOptions: { compile: false }`                |
| `target: "bun-linux-x64"`         | `buildOptions: { compile: "bun-linux-x64" }`      |
| `name: "app"`                     | `buildOptions: { compile: { outfile: "app" } }`   |
| `bytecode`, `minify`, `sourcemap` | `buildOptions.*`                                  |
| `serveOptions`                    | `serverOptions` (JSON-serializable only)          |
| `serveAssets: false`              | removed, assets are embedded                      |
| `IDLE_TIMEOUT`                    | `CONNECTION_IDLE_TIMEOUT`                         |
| `ASSETS_DIR`                      | removed, assets are embedded                      |

