Discord bot built with Carbon on Cloudflare Workers.
@buape/carbon- Cloudflare Workers (
@buape/carbon/adapters/fetch) - Gateway forwarding:
forwarder/Bun process usingGatewayForwarderPlugin - Cloudflare D1 + Drizzle ORM
- Install deps:
bun install
- Create
.envfrom.env.example.
Required:
BASE_URL= DEPLOY_SECRET= DISCORD_CLIENT_ID= DISCORD_PUBLIC_KEY= DISCORD_BOT_TOKEN=
Optional:
DISCORD_DEV_GUILDS= FORWARDER_PUBLIC_KEY= ANSWER_OVERFLOW_API_KEY= HELPER_THREAD_WELCOME_PARENT_ID= HELPER_THREAD_WELCOME_TEMPLATE= THREAD_LENGTH_CHECK_INTERVAL_HOURS=
- Configure
wrangler.jsoncD1 binding:
- set
d1_databases[0].database_idto your real D1 database id - keep
binding = "DB"
- Apply D1 migrations:
bun run db:apply:local
# or
bun run db:apply:remote- Run locally:
bun run dev
bun run dev→wrangler dev --env-file .envbun run deploy→ deploy worker locally with.envbun run deploy:cf→ apply remote D1 migrations, then deploy Worker for Cloudflare Buildsbun run deploy:dry-run→ validate the Worker bundle without deployingbun run cf-typegen→ regenerateworker-configuration.d.tsbun run typecheck→ TypeScript checkbun run db:generate→ generate Drizzle SQLbun run db:apply:local/db:apply:remote→ apply D1 migrations
Cloudflare Workers Builds deploys pushes to main. The deploy command should apply D1 migrations before deploying the Worker:
bun run deploy:cf
Drizzle only generates SQL migrations. Wrangler applies them to D1:
bun run db:generate bun run db:apply:remote
The main bot runs as a Cloudflare Worker. Gateway events are forwarded by the Bun app in forwarder/, usually running on Krill's machine.
Forwarder setup:
cd forwarder
bun install
bun run devForwarder production start:
cd forwarder
bun run startForwarder env:
BASE_URL= DEPLOY_SECRET= DISCORD_CLIENT_ID= DISCORD_PUBLIC_KEY= DISCORD_BOT_TOKEN= FORWARDER_PRIVATE_KEY=
The Worker must have the matching public key:
bunx wrangler secret put FORWARDER_PUBLIC_KEY
- Answer Overflow base URL is hardcoded to
https://www.answeroverflow.com. - Helper thread monitor runs via Worker cron (
wrangler.jsonctriggers.crons). - The old Cloudflare Gateway Durable Object path is not the active gateway setup.