bknd logo

Setup & Modes

Choose a mode and get bknd running with your app

bknd supports three modes. Each mode determines how your backend is configured and where that configuration lives.

Choose your mode

Not sure which to pick?

  • UI-only is best for prototyping and small projects. No code needed — configure everything through the dashboard.
  • Code-only is best for teams, CI/CD, and version-controlled schemas. You define your data structure programmatically.
  • Hybrid gives you the best of both — visual configuration while developing, locked-down code config in production.

You can always change modes later. Start with UI-only if you're exploring.


UI-only mode

This is the default. Run bknd and configure everything through the Admin UI. No setup code required beyond a database connection.

bknd.config.ts
import type { BkndConfig } from "bknd";

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

If you want to provide an initial data structure (entities, auth settings, etc.), pass it via config. It will only be applied when the database is empty.

bknd.config.ts
import type { BkndConfig } from "bknd";

export default {
  connection: { url: "file:data.db" },
  config: {
    auth: { enabled: true },
  },
} satisfies BkndConfig;

In UI-only mode, the config property is only applied on first boot. After that, all changes are made through the Admin UI.

Next step: Pick your framework or runtime integration to wire bknd into your app.


Code-only mode

Define your data structure programmatically with a Drizzle-like API. The Admin UI becomes read-only for configuration — you still use it to manage data.

bknd.config.ts
import { type BkndConfig, em, entity, text, boolean } from "bknd";
import { secureRandomString } from "bknd/utils";

const schema = em({
  todos: entity("todos", {
    title: text(),
    done: boolean(),
  }),
});

export default {
  connection: { url: "file:data.db" },
  config: {
    data: schema.toJSON(),
    auth: {
      enabled: true,
      jwt: { secret: secureRandomString(64) },
    },
  },
  options: {
    mode: "code",
  },
} satisfies BkndConfig;

Unlike UI-only mode, the config is applied on every boot. If you change the schema, you may need to sync the database.

Next step: Pick your framework or runtime integration to wire bknd into your app.


Hybrid mode

Use the Admin UI to configure your backend while developing. When you're ready to deploy, export the config and run in code mode for production.

bknd.config.ts
import type { BkndConfig } from "bknd";
import appConfig from "./appconfig.json" with { type: "json" };

export default {
  connection: { url: "file:data.db" },
  config: appConfig,
  options: {
    mode: process.env.NODE_ENV === "development" ? "db" : "code",
    manager: {
      secrets: process.env,
    },
  },
} satisfies BkndConfig;

To export your config, secrets, and types, use the CLI or plugins:

WhatCLI CommandPlugin
Configurationbknd configsyncConfig
Secretsbknd secretssyncSecrets
Typesbknd typessyncTypes

Next step: Pick your framework or runtime integration to wire bknd into your app.


Mode helpers

For code and hybrid modes, bknd provides helper functions that handle syncing, mode switching, and schema validation automatically.

bknd.config.ts (code mode with Bun)
import { code } from "bknd/modes";
import { type BunBkndConfig, writer } from "bknd/adapter/bun";

export default code<BunBkndConfig>({
  connection: { url: "file:data.db" },
  writer,
  isProduction: Bun.env.NODE_ENV === "production",
  typesFilePath: "bknd-types.d.ts",
});
bknd.config.ts (hybrid mode with Bun)
import { hybrid } from "bknd/modes";
import { type BunBkndConfig, writer, reader } from "bknd/adapter/bun";

export default hybrid<BunBkndConfig>({
  connection: { url: "file:data.db" },
  writer,
  reader,
  secrets: await Bun.file(".env.local").json(),
  isProduction: Bun.env.NODE_ENV === "production",
  typesFilePath: "bknd-types.d.ts",
  configFilePath: "bknd-config.json",
});

Mode helpers give you:

  • Built-in syncing of config, types, and secrets
  • Automatic schema syncing in development
  • Automatic mode switching (db → code) in production for hybrid
  • Skipped config validation in production for faster boot

Further reading