🎯

bknd-deploy-hosting

🎯Skill

from cameronapak/bknd-skills

VibeIndex|
What it does

Deploys Bknd applications across multiple hosting platforms like Cloudflare, Vercel, AWS Lambda, and Docker with platform-specific configuration and adapters.

πŸ“¦

Part of

cameronapak/bknd-skills(55 items)

bknd-deploy-hosting

Installation

npm installInstall npm package
npm install -g pm2
DockerRun with Docker
docker compose up -d
npxRun with npx
npx bknd types
πŸ“– Extracted from docs: cameronapak/bknd-skills
4Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Use when deploying a Bknd application to production hosting. Covers Cloudflare Workers/Pages, Node.js/Bun servers, Docker, Vercel, AWS Lambda, and other platforms.

Overview

# Deploy to Hosting

Deploy your Bknd application to various hosting platforms.

Prerequisites

  • Working Bknd application locally
  • Schema defined and tested
  • Database provisioned (see bknd-database-provision)
  • Environment variables prepared (see bknd-env-config)

When to Use UI Mode

  • Cloudflare/Vercel dashboards for environment variables
  • Platform-specific deployment settings
  • Viewing deployment logs

When to Use Code Mode

  • All deployment configuration and commands
  • Adapter setup for target platform
  • CI/CD pipeline configuration

Platform Selection Guide

| Platform | Best For | Database Options | Cold Start |

|----------|----------|------------------|------------|

| Cloudflare Workers | Edge, global low-latency | D1, Turso | ~0ms |

| Cloudflare Pages | Static + API | D1, Turso | ~0ms |

| Vercel | Next.js apps | Turso, Neon | ~200ms |

| Node.js/Bun VPS | Full control, dedicated | Any | N/A |

| Docker | Containerized, portable | Any | N/A |

| AWS Lambda | Serverless, pay-per-use | Turso, RDS | ~500ms |

Code Approach

Cloudflare Workers

Step 1: Install Wrangler

```bash

npm install -D wrangler

```

Step 2: Create wrangler.toml

```toml

name = "my-bknd-app"

main = "src/index.ts"

compatibility_date = "2024-01-01"

[[d1_databases]]

binding = "DB"

database_name = "my-database"

database_id = "your-d1-database-id"

# Optional: R2 for media storage

[[r2_buckets]]

binding = "R2_BUCKET"

bucket_name = "my-bucket"

[vars]

ENVIRONMENT = "production"

```

Step 3: Configure Adapter

```typescript

// src/index.ts

import { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";

import { d1Sqlite } from "bknd/adapter/cloudflare";

import { em, entity, text } from "bknd";

const schema = em({

posts: entity("posts", {

title: text().required(),

}),

});

export default hybrid({

app: (env) => ({

connection: d1Sqlite({ binding: env.DB }),

schema,

isProduction: true,

auth: {

jwt: {

secret: env.JWT_SECRET,

},

},

config: {

media: {

enabled: true,

adapter: {

type: "r2",

config: { bucket: env.R2_BUCKET },

},

},

},

}),

});

```

Step 4: Create D1 Database

```bash

# Create database

wrangler d1 create my-database

# Copy the database_id to wrangler.toml

```

Step 5: Set Secrets

```bash

wrangler secret put JWT_SECRET

# Enter your secret (min 32 chars)

```

Step 6: Deploy

```bash

wrangler deploy

```

---

Cloudflare Pages (with Functions)

Step 1: Create functions/api/[[bknd]].ts

```typescript

import { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";

import { d1Sqlite } from "bknd/adapter/cloudflare";

import schema from "../../bknd.config";

export const onRequest = hybrid({

app: (env) => ({

connection: d1Sqlite({ binding: env.DB }),

schema,

isProduction: true,

auth: {

jwt: { secret: env.JWT_SECRET },

},

}),

});

```

Step 2: Configure Pages

In Cloudflare dashboard:

  1. Connect your git repository
  2. Set build command (if any)
  3. Add D1 binding under Settings > Functions > D1 Database Bindings
  4. Add environment variables under Settings > Environment Variables

---

Node.js / Bun (VPS)

Step 1: Create Production Entry

```typescript

// index.ts

import { serve, type BunBkndConfig } from "bknd/adapter/bun";

// or for Node.js:

// import { serve } from "bknd/adapter/node";

const config: BunBkndConfig = {

connection: {

url: process.env.DB_URL!,

authToken: process.env.DB_TOKEN,

},

isProduction: true,

auth: {

jwt: {

secret: process.env.JWT_SECRET!,

expires: "7d",

},

},

config: {

media: {

enabled: true,

adapter: {

type: "s3",

config: {

bucket: process.env.S3_BUCKET!,

region: process.env.S3_REGION!,

accessKeyId: process.env.S3_ACCESS_KEY!,

secretAccessKey: process.env.S3_SECRET_KEY!,

},

},

},

guard: {

enabled: true,

},

},

};

serve(config);

```

Step 2: Set Environment Variables

```bash

export DB_URL="libsql://your-db.turso.io"

export DB_TOKEN="your-turso-token"

export JWT_SECRET="your-32-char-minimum-secret"

export PORT=3000

```

Step 3: Run with Process Manager

```bash

# Using PM2

npm install -g pm2

pm2 start "bun run index.ts" --name bknd-app

# Or systemd (create /etc/systemd/system/bknd.service)

```

---

Docker

Step 1: Create Dockerfile

```dockerfile

FROM oven/bun:1.0-alpine

WORKDIR /app

COPY package.json bun.lockb ./

RUN bun install --frozen-lockfile --production

COPY . .

# Create data directory for SQLite (if using file-based)

RUN mkdir -p /app/data

ENV PORT=3000

EXPOSE 3000

CMD ["bun", "run", "index.ts"]

```

Step 2: Create docker-compose.yml

```yaml

version: "3.8"

services:

bknd:

build: .

ports:

- "3000:3000"

volumes:

- bknd-data:/app/data

environment:

- DB_URL=file:/app/data/bknd.db

- JWT_SECRET=${JWT_SECRET}

- NODE_ENV=production

restart: unless-stopped

volumes:

bknd-data:

```

Step 3: Deploy

```bash

# Build and run

docker compose up -d

# View logs

docker compose logs -f bknd

```

---

Vercel (Next.js)

Step 1: Create API Route

```typescript

// app/api/bknd/[[...bknd]]/route.ts

export { GET, POST, PUT, DELETE, PATCH } from "bknd/adapter/nextjs";

```

Step 2: Create bknd.config.ts

```typescript

import type { NextjsBkndConfig } from "bknd/adapter/nextjs";

import { em, entity, text } from "bknd";

const schema = em({

posts: entity("posts", {

title: text().required(),

}),

});

type Database = (typeof schema)["DB"];

declare module "bknd" {

interface DB extends Database {}

}

export default {

app: (env) => ({

connection: {

url: env.DB_URL,

authToken: env.DB_TOKEN,

},

schema,

isProduction: env.NODE_ENV === "production",

auth: {

jwt: { secret: env.JWT_SECRET },

},

}),

} satisfies NextjsBkndConfig;

```

Step 3: Set Vercel Environment Variables

In Vercel dashboard or CLI:

```bash

vercel env add DB_URL

vercel env add DB_TOKEN

vercel env add JWT_SECRET

```

Step 4: Deploy

```bash

vercel deploy --prod

```

---

AWS Lambda

Step 1: Install Dependencies

```bash

npm install -D serverless serverless-esbuild

```

Step 2: Create handler.ts

```typescript

import { createHandler } from "bknd/adapter/aws";

export const handler = createHandler({

connection: {

url: process.env.DB_URL!,

authToken: process.env.DB_TOKEN,

},

isProduction: true,

auth: {

jwt: { secret: process.env.JWT_SECRET! },

},

});

```

Step 3: Create serverless.yml

```yaml

service: bknd-api

provider:

name: aws

runtime: nodejs20.x

region: us-east-1

environment:

DB_URL: ${env:DB_URL}

DB_TOKEN: ${env:DB_TOKEN}

JWT_SECRET: ${env:JWT_SECRET}

plugins:

- serverless-esbuild

functions:

api:

handler: handler.handler

events:

- http:

path: /{proxy+}

method: ANY

- http:

path: /

method: ANY

```

Step 4: Deploy

```bash

serverless deploy --stage prod

```

---

Pre-Deployment Checklist

```bash

# 1. Generate types

npx bknd types

# 2. Test locally with production-like config

DB_URL="your-prod-db" JWT_SECRET="your-secret" npx bknd run

# 3. Verify schema sync

# Schema auto-syncs on first request in production

```

Environment Variables (All Platforms)

| Variable | Required | Description |

|----------|----------|-------------|

| DB_URL | Yes | Database connection URL |

| DB_TOKEN | Depends | Auth token (Turso/LibSQL) |

| JWT_SECRET | Yes | Min 32 chars for security |

| PORT | No | Server port (default: 3000) |

Common Pitfalls

"Module not found" for Native SQLite

Problem: better-sqlite3 not available in serverless

Fix: Use LibSQL/Turso instead of file-based SQLite:

```typescript

connection: {

url: "libsql://your-db.turso.io",

authToken: process.env.DB_TOKEN,

}

```

"JWT_SECRET required" Error

Problem: Auth fails in production

Fix: Set JWT_SECRET environment variable:

```bash

# Cloudflare

wrangler secret put JWT_SECRET

# Vercel

vercel env add JWT_SECRET

# Docker

docker run -e JWT_SECRET="your-secret" ...

```

Cold Start Timeouts (Lambda)

Problem: First request times out

Fix:

  • Use lighter database (Turso over RDS)
  • Reduce bundle size
  • Enable provisioned concurrency for critical functions

D1 Binding Not Found

Problem: env.DB is undefined

Fix: Check wrangler.toml D1 binding:

```toml

[[d1_databases]]

binding = "DB" # Must match env.DB in code

database_name = "my-database"

database_id = "actual-id-from-wrangler-d1-create"

```

Media Uploads Fail in Serverless

Problem: Local storage doesn't work in serverless

Fix: Use cloud storage adapter:

```typescript

config: {

media: {

adapter: {

type: "s3", // or "r2", "cloudinary"

config: { / credentials / },

},

},

}

```

CORS Errors

Problem: Frontend can't access API

Fix: Configure CORS in your adapter:

```typescript

// Most adapters handle this automatically

// For custom needs, check platform docs

```

Deployment Commands Reference

```bash

# Cloudflare Workers

wrangler deploy

wrangler tail # View logs

# Vercel

vercel deploy --prod

vercel logs

# Docker

docker compose up -d

docker compose logs -f

# AWS Lambda

serverless deploy --stage prod

serverless logs -f api

```

DOs and DON'Ts

DO:

  • Set isProduction: true in production config
  • Use cloud storage (S3/R2/Cloudinary) for media
  • Set strong JWT_SECRET (min 32 chars)
  • Enable Guard for authorization
  • Test with production database before deploying
  • Use environment variables for all secrets

DON'T:

  • Use file-based SQLite in serverless
  • Hardcode secrets in code
  • Deploy without testing schema sync
  • Use local storage adapter in production
  • Skip JWT_SECRET configuration
  • Commit .env files with real secrets

Related Skills

  • bknd-database-provision - Set up production database
  • bknd-production-config - Production security settings
  • bknd-storage-config - Configure media storage
  • bknd-env-config - Environment variable setup
  • bknd-local-setup - Local development (pre-deploy testing)