bknd logo
Frameworks

SvelteKit

Run bknd inside SvelteKit

Installation

To get started with SvelteKit and bknd, create a new SvelteKit project by following the official guide, and then install bknd as a dependency:

npm install bknd
pnpm install bknd
yarn add bknd
bun add bknd

Configuration

When run with Node.js, a version of 22 (LTS) or higher is required. Please verify your version by running node -v, and upgrade if necessary.

Now create a bknd.config.ts file in the root of your project:

bknd.config.ts
import type { SvelteKitBkndConfig } from "bknd/adapter/sveltekit";

export default {
  connection: {
    url: "file:data.db",
  },
} satisfies SvelteKitBkndConfig;

See bknd.config.ts for more information on how to configure bknd. The SvelteKitBkndConfig type extends the base config type with the following properties:

export type SvelteKitBkndConfig<Env> = Pick<RuntimeBkndConfig<Env>, "adminOptions">;

Serve the API

The SvelteKit adapter uses SvelteKit's hooks mechanism to handle API requests. Create a src/hooks.server.ts file:

src/hooks.server.ts
import type { Handle } from "@sveltejs/kit";
import { serve } from "bknd/adapter/sveltekit";
import { env } from "$env/dynamic/private";
import config from "../bknd.config";

const bkndHandler = serve(config, env);

export const handle: Handle = async ({ event, resolve }) => {
  // handle bknd API requests
  const pathname = event.url.pathname;
  if (pathname.startsWith("/api/")) {
    const res = await bkndHandler(event);
    if (res.status !== 404) {
      return res;
    }
  }

  return resolve(event);
};

For more information about the connection object, refer to the Database guide.

The adapter uses $env/dynamic/private to access environment variables, making it runtime-agnostic and compatible with any deployment target (Node.js, Bun, Cloudflare, etc.).

Enabling the Admin UI

The SvelteKit adapter supports serving the Admin UI statically. First, copy the required assets to your static folder by adding a postinstall script to your package.json:

package.json
{
  "scripts": {
    "postinstall": "bknd copy-assets --out static"
  }
}

Then update your bknd.config.ts to configure the admin base path:

bknd.config.ts
import type { SvelteKitBkndConfig } from "bknd/adapter/sveltekit";

export default {
  connection: {
    url: "file:data.db",
  },
  adminOptions: {  
    adminBasepath: "/admin"
  },  
} satisfies SvelteKitBkndConfig;

Finally, update your hooks.server.ts to also handle admin routes:

src/hooks.server.ts
import type { Handle } from "@sveltejs/kit";
import { serve } from "bknd/adapter/sveltekit";
import { env } from "$env/dynamic/private";
import config from "../bknd.config";

const bkndHandler = serve(config, env);

export const handle: Handle = async ({ event, resolve }) => {
  // handle bknd API and admin requests
  const pathname = event.url.pathname;
  if (pathname.startsWith("/api/") || pathname.startsWith("/admin")) {  
    const res = await bkndHandler(event);
    if (res.status !== 404) {
      return res;
    }
  }

  return resolve(event);
};

Example usage of the API

You can use the getApp function to access the bknd API in your server-side load functions:

src/routes/+page.server.ts
import type { PageServerLoad } from "./$types";
import { getApp } from "bknd/adapter/sveltekit";
import { env } from "$env/dynamic/private";
import config from "../../bknd.config";

export const load: PageServerLoad = async () => {
  const app = await getApp(config, env);
  const api = app.getApi();

  const todos = await api.data.readMany("todos");

  return {
    todos: todos.data ?? [],
  };
};

Then display the data in your Svelte component:

src/routes/+page.svelte
<script lang="ts">
  import type { PageData } from "./$types";

  let { data }: { data: PageData } = $props();
</script>

<h1>Todos</h1>
<ul>
  {#each data.todos as todo (todo.id)}
    <li>{todo.title}</li>
  {/each}
</ul>

Using authentication

To use authentication in your load functions, pass the request headers to the API:

src/routes/+page.server.ts
import type { PageServerLoad } from "./$types";
import { getApp } from "bknd/adapter/sveltekit";
import { env } from "$env/dynamic/private";
import config from "../../bknd.config";

export const load: PageServerLoad = async ({ request }) => {
  const app = await getApp(config, env);
  const api = app.getApi({ headers: request.headers });
  await api.verifyAuth();

  const todos = await api.data.readMany("todos");

  return {
    todos: todos.data ?? [],
    user: api.getUser(),
  };
};

Check the SvelteKit repository example for more implementation details.