.agents/skills/bknd-local-setup/SKILL.md
Use when setting up a new Bknd project locally or configuring local development environment. Covers CLI installation, project creation, runtime adapters, config file setup, and development server options.
npx skillsauth add cameronapak/cultivate-fellowship bknd-local-setupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Set up a Bknd local development environment from scratch.
http://localhost:3000/adminNote: Initial project setup requires CLI/code.
Quickest way to start:
# Interactive project creation
npx bknd create my-app
# Follow prompts:
# - Project name
# - Database type (SQLite recommended for local dev)
# - Include example schema?
This creates project structure with:
bknd.config.ts - Main configurationpackage.json - Dependencies.env - Environment variables templatecd my-app
# npm
npm install
# bun (faster)
bun install
# pnpm
pnpm install
# Default (port 3000, file-based SQLite)
npx bknd run
# In-memory database (fastest for prototyping, data lost on restart)
npx bknd run --memory
# Custom port
npx bknd run --port 8080
# Don't auto-open browser
npx bknd run --no-open
# Specify runtime explicitly
npx bknd run --server bun
npx bknd run --server node
Server starts at http://localhost:3000 with:
/api/data/*, /api/auth/*, /api/media/*/adminmkdir my-bknd-app && cd my-bknd-app
npm init -y
npm install bknd
Create bknd.config.ts:
import type { CliBkndConfig } from "bknd";
import { em, entity, text, boolean } from "bknd";
// Define schema
const schema = em({
todos: entity("todos", {
title: text().required(),
done: boolean(),
}),
});
// Register types
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
export default {
app: (env) => ({
connection: {
url: env.DB_URL ?? "file:data.db",
},
schema,
}),
} satisfies CliBkndConfig;
For programmatic control, create index.ts:
import { serve } from "bknd/adapter/bun";
import { em, entity, text, boolean } from "bknd";
const schema = em({
todos: entity("todos", {
title: text().required(),
done: boolean(),
}),
});
serve({
connection: { url: "file:data.db" },
config: {
data: schema.toJSON(),
},
});
Run with:
# Bun
bun run index.ts
# Node (requires tsx or ts-node)
npx tsx index.ts
import { serve } from "bknd/adapter/bun";
serve({
connection: { url: "file:data.db" },
});
import { serve } from "bknd/adapter/node";
serve({
connection: { url: "file:data.db" },
});
Next.js:
// app/api/bknd/[[...bknd]]/route.ts
import { createHandler } from "bknd/adapter/nextjs";
export const { GET, POST, PUT, DELETE, PATCH } = createHandler(config);
Astro:
// src/pages/api/[...bknd].ts
import { createHandler } from "bknd/adapter/astro";
export const ALL = createHandler(config);
React Router (Remix):
// app/routes/api.$.tsx
import { createHandler } from "bknd/adapter/react-router";
export const loader = createHandler(config);
export const action = createHandler(config);
| Option | Description | Default |
|--------|-------------|---------|
| -p, --port <port> | Server port | 3000 |
| -m, --memory | Use in-memory database | - |
| --server <server> | Runtime: node or bun | Auto-detected |
| --no-open | Don't auto-open browser | Opens by default |
| -c, --config <path> | Config file path | Auto-detected |
| --db-url <url> | Database URL override | - |
Bknd auto-detects config files (in order):
bknd.config.tsbknd.config.jsbknd.config.mjsbknd.config.cjsbknd.config.jsonmy-bknd-app/
├── bknd.config.ts # Main configuration
├── bknd-types.d.ts # Generated types (run: npx bknd types)
├── .env # Environment variables
├── .dev.vars # Dev-specific overrides (optional)
├── data.db # SQLite file (auto-created)
├── uploads/ # Local media storage (if using local adapter)
└── package.json
my-nextjs-app/
├── app/
│ ├── api/
│ │ └── bknd/
│ │ └── [[...bknd]]/
│ │ └── route.ts
│ └── admin/
│ └── page.tsx
├── bknd.config.ts
├── bknd-types.d.ts
└── .env.local
After defining schema, generate types for IDE support:
# Generate to bknd-types.d.ts (default)
npx bknd types
# Custom output
npx bknd types -o types/bknd.d.ts
# Print to console (debug)
npx bknd types --dump
| Database | URL Format | Best For |
|----------|------------|----------|
| In-memory SQLite | :memory: or --memory flag | Quick prototyping |
| File SQLite | file:data.db | Persistent local dev |
| LibSQL (Turso) | libsql://your-db.turso.io | Remote dev database |
npx bknd run --memory
Data resets on server restart. Best for rapid prototyping.
npx bknd run
# or explicitly:
npx bknd run --db-url "file:data.db"
Data persists in data.db file.
# Delete SQLite file for fresh start
rm data.db
# Then restart server
npx bknd run
Schema changes require server restart. Use watch mode:
# Bun
bun --watch index.ts
# Node with nodemon
npx nodemon --exec "npx bknd run"
# Show internal paths
npx bknd debug paths
# Show all registered routes
npx bknd debug routes
# CLI help
npx bknd --help
npx bknd run --help
After setup, verify everything works:
1. Server running:
curl http://localhost:3000/api/data
# Should return entity list
2. Admin panel accessible:
Open http://localhost:3000/admin in browser
3. Types generated:
npx bknd types
# Check bknd-types.d.ts created
Problem: Config file could not be resolved error
Fix: Ensure config file exists with correct extension:
# Check file exists
ls bknd.config.*
# Or specify explicitly
npx bknd run -c ./bknd.config.ts
Problem: EADDRINUSE: address already in use
Fix: Use different port or kill existing process:
# Use different port
npx bknd run --port 3001
# Or find and kill process
lsof -i :3000
kill -9 <PID>
Problem: SQLITE_CANTOPEN: unable to open database file
Fix: Ensure write permissions in directory:
# Check permissions
ls -la
# Fix permissions
chmod 755 .
Problem: Type errors when using em() return value
Fix: Remember em() returns schema definition, not EntityManager:
// WRONG - em() is schema builder only
const em = em({ ... });
em.repo("posts").find(); // ERROR
// CORRECT - use api.data for queries
const api = new Api({ url: "http://localhost:3000" });
api.data.readMany("posts");
Problem: bun: command not found
Fix: Install Bun or use Node:
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Or use Node runtime
npx bknd run --server node
Problem: File paths not resolving on Windows
Fix: Use forward slashes:
// WRONG
connection: { url: "file:C:\\data\\my.db" }
// CORRECT
connection: { url: "file:C:/data/my.db" }
// or relative
connection: { url: "file:data.db" }
DO:
--memory flag for quick experimentsfile:data.db for persistent developmentbknd.config.ts to version control.env for environment-specific valuesDON'T:
data.db to version control (add to .gitignore).env with secrets (use .env.example template)em() result as EntityManagerdevelopment
Use btca (Better Context App) to efficiently query and learn from the bknd backend framework. Use when working with bknd for (1) Understanding data module and schema definitions, (2) Implementing authentication and authorization, (3) Setting up media file handling, (4) Configuring adapters (Node, Cloudflare, etc.), (5) Learning from bknd source code and examples, (6) Debugging bknd-specific issues
development
Use when configuring webhook integrations in Bknd. Covers receiving incoming webhooks via HTTP triggers, sending outgoing webhooks with FetchTask, event-triggered webhooks on data changes, signature verification, retry patterns, and async processing.
development
Use when encountering Bknd errors, getting error messages, something not working, or needing quick fixes. Covers error code reference, quick solutions, and common mistake patterns.
tools
Use when writing tests for Bknd applications, setting up test infrastructure, creating unit/integration tests, or testing API endpoints. Covers in-memory database setup, test helpers, mocking, and test patterns.