Cloudflare Workers
Hono is designed (primarily) for Cloudflare Workers, while Honocord works well with handling async interactions automatically to fit within Workers’ limits.
Why Cloudflare Workers?
Section titled “Why Cloudflare Workers?”- Global edge deployment with low latency.
- Generous free tier (100k requests/day).
- No cold starts, instant scaling.
- Honocord auto-manages async via
waitUntil.
See a full example here
Project Setup
Section titled “Project Setup”-
Initialize
Terminal window pnpm create cloudflare@latest my-discord-botcd my-discord-botpnpm add honocord -
wrangler.jsonc{"name": "my-discord-bot","main": "src/index.ts","compatibility_date": "2024-01-01","compatibility_flags": ["nodejs_compat"],"vars": {"IS_CF_WORKER": "true",},} -
Bot Entry Point
src/index.ts import { Honocord } from "honocord";import * as handlers from "./handlers";const bot = new Honocord({ isCFWorker: true }); // Auto-detected via IS_CF_WORKERbot.loadHandlers(...Object.values(handlers));export default bot.getApp(); // Export as Worker fetch handler -
Example Handler
src/handlers.ts import { SlashCommandHandler } from "honocord";export const pingCommand = new SlashCommandHandler().setName("ping").setDescription("Check bot latency").addHandler(async (interaction) => {await interaction.reply("🏓 Pong!");});Secrets
Section titled “Secrets”Never use plain environment variables for sensitive data.
Terminal window npx wrangler secret put DISCORD_TOKENnpx wrangler secret put DISCORD_PUBLIC_KEYnpx wrangler secret put DISCORD_APPLICATION_IDOr have an
.envfile and bulk upload your secrets with:Terminal window npx wrangler secret bulk .envLocal Development
Section titled “Local Development”Terminal window wrangler dev # Runs at http://localhost:8787To expose your local environment publicly for Discord’s verification:
Terminal window cloudflared tunnel --url http://localhost:8787 # Recommended# orngrok http 8787
Production Deployment
Section titled “Production Deployment”-
Deploy
Terminal window pnpm run deploy # Outputs your Worker URL, e.g., https://my-discord-bot.username.workers.dev/ -
Register Commands
Run this locally, not on the Worker itself.
src/register.ts import { registerCommands } from "honocord";import * as handlers from "./handlers/index"; // Assuming you have a src/handlers/index.ts fileawait registerCommands(process.env.DISCORD_TOKEN!, process.env.DISCORD_APPLICATION_ID!, Object.values(handlers));package.json {"scripts": {"register": "tsx --env-file=.env src/register.ts"},"devDependencies": {"tsx": "latest"}}Then run with
pnpm register. -
Discord Setup
- In the Discord Developer Portal → Your App → General Information.
- Set Interactions Endpoint URL to your Worker URL (e.g.,
https://.../interactions). - Save changes. Discord will automatically send a POST request to verify the URL.
Type Safety (optional but recommended)
Section titled “Type Safety (optional but recommended)”When you deploy on Workers, you should use the wrangler script cf-typegen automatically provided upon project creation.
This creates a worker-configuration.d.ts file which exports an Env interface which you can use in your project.
import type { BaseInteractionContext } from "honocord";
// `Env` is from the types generated by wranglertype WorkerEnv = Env;
export type MyVariables = { // Your custom Hono variables here};type MyContext = BaseInteractionContext<WorkerEnv, MyVariables>;Usage in a handler:
import type { Context } from "./types";
// ... inside handler ...await interaction.context.env.MY_KV.get("key");// Note: Don't confuse .context (the Hono Context) with .contexts (Discord Interaction Context)Best Practices
Section titled “Best Practices”- Use secrets only for sensitive data.
- Keep handlers lightweight (≤50ms CPU time on the free plan).
- Store data in Workers KV, D1, or Durable Objects.
- Monitor logs with
wrangler tail. - Update
compatibility_dateon a regular basis.
Common Issues
Section titled “Common Issues”- CPU limit exceeded: Split heavy work or use Durable Objects. Alternatively, upgrade to the Workers Paid plan.
- Verification fails: Double-check your public key, ensure the URL is correct (including any path like
/interactions), and ensure the Worker is deployed. - Module not found: Ensure you are using the correct relative paths and file extensions in your imports.