mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
Refactor setup documentation for clarity
This commit is contained in:
@@ -1,123 +1,74 @@
|
||||
---
|
||||
title: "Setup & Modes"
|
||||
description: "Configuring bknd and choosing a mode"
|
||||
description: "Choose a mode and get bknd running with your app"
|
||||
icon: Pin
|
||||
tags: ["documentation"]
|
||||
---
|
||||
|
||||
import { TypeTable } from "fumadocs-ui/components/type-table";
|
||||
import { SquareMousePointer, Code, Blend } from 'lucide-react';
|
||||
|
||||
## Basic setup
|
||||
bknd supports three modes. Each mode determines how your backend is configured and where that configuration lives.
|
||||
|
||||
Regardless of how you run bknd, all adapters come down to instantiating the `App`:
|
||||
|
||||
```typescript
|
||||
import { createApp, type BkndConfig } from "bknd";
|
||||
|
||||
// create the app
|
||||
const config = {
|
||||
/* ... */
|
||||
} satisfies BkndConfig;
|
||||
const app = createApp(config);
|
||||
|
||||
// build the app
|
||||
await app.build();
|
||||
|
||||
// export for Web API compliant envs
|
||||
export default app;
|
||||
```
|
||||
|
||||
In Web API compliant environments, all you have to do is to default exporting the app, as it implements the `Fetch` API. In case an explicit `fetch` export is needed, you can use the `app.fetch` property.
|
||||
|
||||
```typescript
|
||||
const app = /* ... */;
|
||||
export default {
|
||||
fetch: app.fetch,
|
||||
}
|
||||
```
|
||||
|
||||
Check the integration details for your specific runtime or framework in the [integration](/integration/introduction) section.
|
||||
|
||||
## Modes
|
||||
## Choose your mode
|
||||
|
||||
<Cards className="grid-cols-1 sm:grid-cols-2 md:grid-cols-3">
|
||||
<Card title="UI-only (default)" href="/usage/setup#ui-only-mode" icon={<SquareMousePointer className="text-fd-primary !size-6" />}>
|
||||
This is the default mode, it allows visual configuration and saves the configuration to the database. Expects you to deploy your backend separately from your frontend.
|
||||
<Card title="UI-only (default)" href="#ui-only-mode" icon={<SquareMousePointer className="text-fd-primary !size-6" />}>
|
||||
Configure visually via the Admin UI. Config is stored in the database.
|
||||
</Card>
|
||||
<Card title="Code-only" href="/usage/setup#code-only-mode" icon={<Code className="text-fd-primary !size-6" />}>
|
||||
This mode allows you to configure your backend programmatically, and define your data structure with a Drizzle-like API. Visual configuration controls are disabled.
|
||||
<Card title="Code-only" href="#code-only-mode" icon={<Code className="text-fd-primary !size-6" />}>
|
||||
Define your schema in code with a Drizzle-like API. Config lives in your codebase.
|
||||
</Card>
|
||||
<Card title={"Hybrid"} href="/usage/setup#hybrid-mode" icon={<Blend className="text-fd-primary !size-6" />}>
|
||||
This mode allows you to configure your backend visually while in development, and uses the produced configuration in a code-only mode for maximum performance.
|
||||
<Card title="Hybrid" href="#hybrid-mode" icon={<Blend className="text-fd-primary !size-6" />}>
|
||||
Use the Admin UI in development, export to code for production.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
The configuration properties involved are the following:
|
||||
**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.
|
||||
|
||||
```typescript title="bknd.config.ts"
|
||||
import type { BkndConfig } from "bknd";
|
||||
|
||||
export default {
|
||||
config: { /* ... */ }
|
||||
options: {
|
||||
mode: "db", // or "code"
|
||||
manager: {
|
||||
secrets: { /* ... */ },
|
||||
storeSecrets: true,
|
||||
},
|
||||
}
|
||||
connection: { url: "file:data.db" },
|
||||
} satisfies BkndConfig;
|
||||
```
|
||||
|
||||
<TypeTable type={{
|
||||
config: {
|
||||
description: "The initial configuration when `mode` is `\"db\"`, and as the produced configuration when `mode` is `\"code\"`.",
|
||||
type: "object",
|
||||
properties: {
|
||||
/* ... */
|
||||
}
|
||||
},
|
||||
["options.mode"]: {
|
||||
description: "The options for the app.",
|
||||
type: '"db" | "code"',
|
||||
default: '"db"'
|
||||
},
|
||||
["options.manager.secrets"]: {
|
||||
description: "The app secrets to be provided when using `\"db\"` mode. This is required since secrets are extracted and stored separately to the database.",
|
||||
type: "object",
|
||||
properties: {
|
||||
/* ... */
|
||||
}
|
||||
},
|
||||
["options.manager.storeSecrets"]: {
|
||||
description: "Whether to store secrets in the database when using `\"db\"` mode.",
|
||||
type: "boolean",
|
||||
default: "true"
|
||||
}
|
||||
}} />
|
||||
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.
|
||||
|
||||
### UI-only mode
|
||||
|
||||
This mode is the default mode. It allows you to configure your backend visually with the built-in Admin UI. It expects that you deploy your backend separately from your frontend, and make changes there. No configuration is needed, however, if you want to provide an initial configuration, you can do so by passing a `config` object.
|
||||
|
||||
```typescript
|
||||
```typescript title="bknd.config.ts"
|
||||
import type { BkndConfig } from "bknd";
|
||||
|
||||
export default {
|
||||
// this will only be applied if the database is empty
|
||||
config: { /* ... */ },
|
||||
connection: { url: "file:data.db" },
|
||||
config: {
|
||||
auth: { enabled: true },
|
||||
},
|
||||
} satisfies BkndConfig;
|
||||
```
|
||||
|
||||
<Callout type="info">
|
||||
Note that when using the default UI-mode, the initial configuration using the `config` property will only be applied if the database is empty.
|
||||
In UI-only mode, the `config` property is only applied on first boot. After that, all changes are made through the Admin UI.
|
||||
</Callout>
|
||||
|
||||
**Next step:** Pick your [framework or runtime integration](/integration/introduction) to wire bknd into your app.
|
||||
|
||||
### Code-only mode
|
||||
---
|
||||
|
||||
This mode allows you to configure your backend programmatically, and define your data structure with a Drizzle-like API. Visual configuration controls are disabled.
|
||||
## 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.
|
||||
|
||||
```typescript title="bknd.config.ts"
|
||||
import { type BkndConfig, em, entity, text, boolean } from "bknd";
|
||||
@@ -131,119 +82,99 @@ const schema = em({
|
||||
});
|
||||
|
||||
export default {
|
||||
// example configuration
|
||||
connection: { url: "file:data.db" },
|
||||
config: {
|
||||
data: schema.toJSON(),
|
||||
auth: {
|
||||
enabled: true,
|
||||
jwt: {
|
||||
secret: secureRandomString(64),
|
||||
},
|
||||
}
|
||||
jwt: { secret: secureRandomString(64) },
|
||||
},
|
||||
},
|
||||
options: {
|
||||
// this ensures that the provided configuration is always used
|
||||
mode: "code",
|
||||
},
|
||||
} satisfies BkndConfig;
|
||||
```
|
||||
|
||||
Unlike the UI-only mode, the configuration passed to `config` is always applied. In case you make data structure changes, you may need to sync the schema to the database manually, e.g. using the [sync command](/usage/cli#syncing-the-database-sync).
|
||||
Unlike UI-only mode, the `config` is applied on every boot. If you change the schema, you may need to [sync the database](/usage/cli#syncing-the-database-sync).
|
||||
|
||||
### Hybrid mode
|
||||
**Next step:** Pick your [framework or runtime integration](/integration/introduction) to wire bknd into your app.
|
||||
|
||||
This mode allows you to configure your backend visually while in development, and uses the produced configuration in a code-only mode for maximum performance. It gives you the best of both worlds.
|
||||
---
|
||||
|
||||
While in development, we set the mode to `"db"` where the configuration is stored in the database. When it's time to deploy, we export the configuration, and set the mode to `"code"`. While in `"db"` mode, the `config` property interprets the value as an initial configuration to use when the database is empty.
|
||||
## 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.
|
||||
|
||||
```typescript title="bknd.config.ts"
|
||||
import type { BkndConfig } from "bknd";
|
||||
|
||||
// import your produced configuration
|
||||
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
|
||||
}
|
||||
secrets: process.env,
|
||||
},
|
||||
},
|
||||
} satisfies BkndConfig;
|
||||
```
|
||||
|
||||
To keep your config, secrets and types in sync, you can either use the CLI or the plugins.
|
||||
To export your config, secrets, and types, use the CLI or plugins:
|
||||
|
||||
| What | CLI Command | Plugin |
|
||||
|------|-------------|--------|
|
||||
| Configuration | [`bknd config`](/usage/cli/#getting-the-configuration-config) | [`syncConfig`](/extending/plugins/#syncconfig) |
|
||||
| Secrets | [`bknd secrets`](/usage/cli/#getting-the-secrets-secrets) | [`syncSecrets`](/extending/plugins/#syncsecrets) |
|
||||
| Types | [`bknd types`](/usage/cli/#generating-types-types) | [`syncTypes`](/extending/plugins/#synctypes) |
|
||||
|
||||
| Type | Plugin | CLI Command |
|
||||
|----------------|-----------------------------------------------------------------------|----------------------------|
|
||||
| Configuration | [`syncConfig`](/extending/plugins/#syncconfig) | [`config`](/usage/cli/#getting-the-configuration-config) |
|
||||
| Secrets | [`syncSecrets`](/extending/plugins/#syncsecrets) | [`secrets`](/usage/cli/#getting-the-secrets-secrets) |
|
||||
| Types | [`syncTypes`](/extending/plugins/#synctypes) | [`types`](/usage/cli/#generating-types-types) |
|
||||
**Next step:** Pick your [framework or runtime integration](/integration/introduction) to wire bknd into your app.
|
||||
|
||||
---
|
||||
|
||||
## Mode helpers
|
||||
|
||||
To make the setup using your preferred mode easier, there are mode helpers for [`code`](/usage/setup#code-only-mode) and [`hybrid`](/usage/setup#hybrid-mode) modes.
|
||||
For code and hybrid modes, bknd provides helper functions that handle syncing, mode switching, and schema validation automatically.
|
||||
|
||||
* built-in syncing of config, types and secrets
|
||||
* let bknd automatically sync the data schema in development
|
||||
* automatically switch modes in hybrid (from db to code) in production
|
||||
* automatically skip config validation in production to boost performance
|
||||
|
||||
To use it, you have to wrap your configuration in a mode helper, e.g. for `code` mode using the Bun adapter:
|
||||
|
||||
```typescript title="bknd.config.ts"
|
||||
import { code, type CodeMode } from "bknd/modes";
|
||||
```typescript title="bknd.config.ts (code mode with Bun)"
|
||||
import { code } from "bknd/modes";
|
||||
import { type BunBkndConfig, writer } from "bknd/adapter/bun";
|
||||
|
||||
export default code<BunBkndConfig>({
|
||||
// some normal bun bknd config
|
||||
connection: { url: "file:data.db" },
|
||||
// ...
|
||||
// a writer is required, to sync the types
|
||||
writer,
|
||||
// (optional) mode specific config
|
||||
isProduction: Bun.env.NODE_ENV === "production",
|
||||
typesFilePath: "bknd-types.d.ts",
|
||||
// (optional) e.g. have the schema synced if !isProduction
|
||||
syncSchema: {
|
||||
force: true,
|
||||
drop: true,
|
||||
}
|
||||
connection: { url: "file:data.db" },
|
||||
writer,
|
||||
isProduction: Bun.env.NODE_ENV === "production",
|
||||
typesFilePath: "bknd-types.d.ts",
|
||||
});
|
||||
```
|
||||
|
||||
Similarily, for `hybrid` mode:
|
||||
|
||||
```typescript title="bknd.config.ts"
|
||||
import { hybrid, type HybridMode } from "bknd/modes";
|
||||
```typescript title="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>({
|
||||
// some normal bun bknd config
|
||||
connection: { url: "file:data.db" },
|
||||
// ...
|
||||
// reader/writer are required, to sync the types and config
|
||||
writer,
|
||||
reader,
|
||||
// supply secrets
|
||||
secrets: await Bun.file(".env.local").json(),
|
||||
// (optional) mode specific config
|
||||
isProduction: Bun.env.NODE_ENV === "production",
|
||||
typesFilePath: "bknd-types.d.ts",
|
||||
configFilePath: "bknd-config.json",
|
||||
// (optional) and have them automatically written if !isProduction
|
||||
syncSecrets: {
|
||||
outFile: ".env.local",
|
||||
format: "env",
|
||||
includeSecrets: true,
|
||||
},
|
||||
// (optional) also have the schema synced if !isProduction
|
||||
syncSchema: {
|
||||
force: true,
|
||||
drop: true,
|
||||
},
|
||||
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
|
||||
|
||||
- [Framework & runtime integrations](/integration/introduction) — wire bknd into Next.js, Astro, Bun, Cloudflare, etc.
|
||||
- [Database configuration](/usage/database) — choose and configure your SQL database
|
||||
- [Configuration reference](/extending/config) — full `BkndConfig` API, plugins, events, and lifecycle hooks
|
||||
|
||||
Reference in New Issue
Block a user