.agents/skills/bknd-env-config/SKILL.md
Use when configuring environment variables for Bknd projects. Covers .env files, secrets management, env injection in config, platform-specific variables, and production security.
npx skillsauth add cameronapak/cultivate-fellowship bknd-env-configInstall 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.
Configure environment variables for Bknd applications across development and production.
bknd.config.ts exists).env filesbknd.config.tsCreate .env in project root:
# Database
DB_URL=file:data.db
DB_TOKEN=
# Auth
JWT_SECRET=your-secret-here-min-32-chars
# Server
PORT=3000
# Development
LOCAL=true
Access env vars via the env parameter in bknd.config.ts:
import type { CliBkndConfig } from "bknd";
export default {
app: (env) => ({
connection: {
url: env.DB_URL ?? "file:data.db",
authToken: env.DB_TOKEN,
},
auth: {
jwt: {
secret: env.JWT_SECRET ?? "dev-secret-change-in-prod",
},
},
}),
} satisfies CliBkndConfig;
The env parameter receives all environment variables loaded from .env files and system environment.
Bknd loads env files in order (later takes precedence):
.env - Base configuration.dev.vars - Development-specific overrides (Cloudflare style)Create .dev.vars for local dev overrides:
# .dev.vars - Dev-only, overrides .env
DB_URL=:memory:
JWT_SECRET=dev-only-secret
| Variable | Description | Example |
|----------|-------------|---------|
| DB_URL | Database connection URL | file:data.db, libsql://db.turso.io |
| DB_TOKEN | LibSQL/Turso auth token | eyJhbGciOiJFZERTQSIs... |
| Variable | Description | Example |
|----------|-------------|---------|
| JWT_SECRET | JWT signing secret (min 32 chars) | your-very-long-secret-key-here |
| GOOGLE_CLIENT_ID | Google OAuth client ID | 123456.apps.googleusercontent.com |
| GOOGLE_CLIENT_SECRET | Google OAuth secret | GOCSPX-xxx |
| GITHUB_CLIENT_ID | GitHub OAuth client ID | Iv1.abc123 |
| GITHUB_CLIENT_SECRET | GitHub OAuth secret | secret_xxx |
| Variable | Description | Example |
|----------|-------------|---------|
| S3_ACCESS_KEY | S3/R2 access key | AKIAIOSFODNN7EXAMPLE |
| S3_SECRET_KEY | S3/R2 secret key | wJalrXUtnFEMI/K7MDENG/... |
| S3_ENDPOINT | S3-compatible endpoint | https://bucket.s3.region.amazonaws.com |
| CLOUDINARY_CLOUD_NAME | Cloudinary cloud name | my-cloud |
| CLOUDINARY_API_KEY | Cloudinary API key | 123456789012345 |
| CLOUDINARY_API_SECRET | Cloudinary API secret | abcdefghijk... |
| Variable | Description | Default |
|----------|-------------|---------|
| PORT | Server port | 3000 |
| LOCAL | Disable telemetry | - |
| NODE_ENV / ENVIRONMENT | Environment mode | development |
import type { CliBkndConfig } from "bknd";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", { title: text().required() }),
});
export default {
app: (env) => ({
// Database
connection: {
url: env.DB_URL ?? "file:data.db",
authToken: env.DB_TOKEN,
},
// Production flag
isProduction: env.NODE_ENV === "production",
// Pass all secrets to app
secrets: env,
}),
config: {
data: schema.toJSON(),
// Auth with env-based secrets
auth: {
enabled: true,
jwt: {
secret: env.JWT_SECRET,
issuer: "my-app",
},
strategies: {
password: { enabled: true },
google: env.GOOGLE_CLIENT_ID ? {
config: {
name: "google",
type: "oidc",
client: {
client_id: env.GOOGLE_CLIENT_ID,
client_secret: env.GOOGLE_CLIENT_SECRET,
},
},
} : undefined,
},
},
// Media with env-based adapter config
media: {
enabled: true,
adapter: {
type: "s3",
config: {
access_key: env.S3_ACCESS_KEY,
secret_access_key: env.S3_SECRET_KEY,
url: env.S3_ENDPOINT,
},
},
},
},
} satisfies CliBkndConfig;
Use wrangler.toml for non-secret vars and dashboard for secrets:
# wrangler.toml
[vars]
ENVIRONMENT = "production"
Set secrets via CLI:
npx wrangler secret put JWT_SECRET
npx wrangler secret put DB_TOKEN
Access in config:
import type { CloudflareBkndConfig } from "bknd/adapter/cloudflare";
export default {
app: (env) => ({
connection: env.DB, // D1 binding
isProduction: env.ENVIRONMENT === "production",
secrets: env,
}),
} satisfies CloudflareBkndConfig;
Use Vercel dashboard or CLI for env vars:
vercel env add JWT_SECRET production
vercel env add DB_URL production
Or .env.local for local development (auto-loaded by Next.js):
# .env.local
DB_URL=file:data.db
JWT_SECRET=dev-secret
Pass via docker-compose or -e flag:
# docker-compose.yml
services:
app:
environment:
- DB_URL=file:/data/app.db
- JWT_SECRET=${JWT_SECRET}
env_file:
- .env.production
Use CLI to generate env template from your config:
# Output required secrets as template
npx bknd secrets --template --format env
# Save to file
npx bknd secrets --template --format env --out .env.example
This creates a template without actual values, safe for version control.
Auto-generate .env.example on config changes:
export default {
syncSecrets: {
enabled: true,
outFile: ".env.example",
format: "env", // or "json"
},
app: (env) => ({ ... }),
} satisfies CliBkndConfig;
Conditionally enable features based on environment:
export default {
app: (env) => ({
connection: { url: env.DB_URL ?? "file:data.db" },
}),
config: {
auth: {
enabled: true,
// Only enable OAuth in production (requires secrets)
strategies: {
password: { enabled: true },
google: env.GOOGLE_CLIENT_ID ? {
config: {
name: "google",
type: "oidc",
client: {
client_id: env.GOOGLE_CLIENT_ID,
client_secret: env.GOOGLE_CLIENT_SECRET,
},
},
} : undefined,
},
},
// Only enable S3 media in production
media: env.S3_ACCESS_KEY ? {
enabled: true,
adapter: {
type: "s3",
config: {
access_key: env.S3_ACCESS_KEY,
secret_access_key: env.S3_SECRET_KEY,
url: env.S3_ENDPOINT,
},
},
} : {
enabled: false,
},
},
} satisfies CliBkndConfig;
Bknd resolves database connection in order:
--db-url CLI argumentconnection.url--memory flag (uses :memory:)DB_URL environment variablefile:data.dbCheck env loading:
# Server logs show connection source
npx bknd run
# Look for: "Using connection from ..."
Test env injection:
// Temporarily log env in config
app: (env) => {
console.log("Loaded env:", Object.keys(env));
return { ... };
},
Verify secrets command:
npx bknd secrets --template
Problem: Env vars undefined in config
Fix: Check file location and format:
# .env must be in project root (same level as bknd.config.ts)
ls -la .env
# No quotes around values
DB_URL=file:data.db # Correct
DB_URL="file:data.db" # May cause issues
Problem: Auth fails or warning about weak secret
Fix: Use minimum 32 characters:
# Generate secure secret
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# or
openssl rand -hex 32
Problem: Committed .env with real secrets
Fix:
# Add to .gitignore
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
echo ".dev.vars" >> .gitignore
# Remove from git history if committed
git rm --cached .env
Problem: env.VAR is undefined in deployed app
Fix: Platform-specific setup:
vercel env addwrangler secret put or dashboardenvironment: or env_file: in composeProblem: Using dev defaults in production
Fix: Fail fast instead of fallback:
app: (env) => {
if (!env.JWT_SECRET && env.NODE_ENV === "production") {
throw new Error("JWT_SECRET required in production");
}
return {
auth: {
jwt: { secret: env.JWT_SECRET ?? "dev-only" },
},
};
},
DO:
.env.example as template (no real values)syncSecrets to keep .env.example updatedDON'T:
.env with real secretsdevelopment
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.