Custom Bindings
Declare extra Cloudflare bindings (send_email, r2_buckets, queues, services, durable_objects, vars, ai) in quickback.config.ts so they survive every compile.
Quickback's compiler owns the D1/KV/R2/ASSETS/queue blocks it needs for its own features. Anything else your worker binds to — Cloudflare Email, an extra R2 bucket, a custom queue, a service binding, your own Durable Object, Workers AI, or non-secret [vars] — goes under the top-level bindings key:
import { defineConfig, defineRuntime, defineDatabase, defineAuth } from "@kardoe/quickback";
export default defineConfig({
name: "studio-mail",
template: "hono",
providers: {
runtime: defineRuntime("cloudflare"),
database: defineDatabase("cloudflare-d1", { splitDatabases: true }),
auth: defineAuth("better-auth"),
},
bindings: {
sendEmail: [{ name: "EMAIL" }],
r2Buckets: [
{ binding: "MAIL_RAW", bucketName: "studio-mail-raw" },
{ binding: "MAIL_ATTACHMENTS", bucketName: "studio-mail-attachments" },
],
vars: {
MAIL_SENDING_DOMAIN: "studio.example.com",
},
},
});camelCase field names map 1:1 to the snake_case TOML blocks in wrangler.toml. Every compile regenerates wrangler.toml from your config, so these entries are the source of truth — no more post-compile patch scripts.
Fields
sendEmail
Emits [[send_email]]. Use when your worker calls env.<NAME>.send(...) via Cloudflare Email Service.
sendEmail: [
{
name: "EMAIL",
// Optional: restrict who the worker is allowed to send to.
destinationAddress: "alerts@example.com",
allowedDestinationAddresses: ["alerts@example.com", "ops@example.com"],
},
]r2Buckets
Emits additional [[r2_buckets]] blocks alongside the compiler-owned files bucket.
r2Buckets: [
{
binding: "MAIL_RAW",
bucketName: "studio-mail-raw",
previewBucketName: "studio-mail-raw-preview", // optional
jurisdiction: "eu", // optional
},
]queueProducers / queueConsumers
Emits [[queues.producers]] and [[queues.consumers]]. Useful for app-owned queues beyond the compiler's webhook/embedding queues.
queueProducers: [
{ binding: "MAIL_QUEUE", queue: "mail-send" },
],
queueConsumers: [
{
queue: "mail-send",
maxBatchSize: 5,
maxBatchTimeout: 30,
maxRetries: 3,
maxConcurrency: 2,
deadLetterQueue: "mail-dlq",
},
]services
Emits [[services]] — service bindings to sibling workers.
services: [
{ binding: "INBOUND", service: "studio-mail-inbound", environment: "production" },
]durableObjects
Emits [[durable_objects.bindings]] for app-owned Durable Objects. Don't use this for Quickback's built-in BROADCASTER realtime DO — that one is compiler-owned.
durableObjects: [
{ name: "SESSION_ROOM", className: "SessionRoom" },
// Cross-worker DO: reference the exporting worker explicitly.
{ name: "RATE_LIMITER", className: "RateLimiter", scriptName: "rate-limit-worker" },
]vars
Merged into the compiler's own [vars] table — emitting a second [vars] block would be invalid TOML. Values must be string, number, or boolean.
vars: {
MAIL_SENDING_DOMAIN: "studio.example.com",
MAIL_MAX_ATTACHMENTS: 10,
MAIL_DEBUG: false,
}Secrets do not go here. Use Wrangler's secret store instead:
wrangler secret put MAIL_INBOUND_SECRETai
Emits a top-level [ai] block. Use this if you need Workers AI bound under a name different from Quickback's internal AI.
ai: { binding: "USER_AI" }Reserved binding names
Binding names that clash with compiler-owned bindings are rejected at validation time, with the offending field path in the error message. Reserved names depend on what your config enables:
| Name | Reserved when |
|---|---|
AUTH_DB, DB | splitDatabases: true (default) |
DATABASE | splitDatabases: false |
AUDIT_DB | always (cross-tenant unsafe-action audit) |
WEBHOOKS_DB, WEBHOOKS_QUEUE | a webhooks binding is configured |
KV | always |
R2_BUCKET, FILES_DB | fileStorage: defineFileStorage("cloudflare-r2") |
VECTORIZE | a Vectorize index is configured |
BROADCASTER | realtime is enabled |
EMAIL | email: { provider: "cloudflare" } |
ASSETS | cms: true or account: true |
AI, EMBEDDINGS_QUEUE | embeddings are configured |
Pick a different name — the generated env on the handler side takes whatever binding you pick.
See also
- Environment Variables — the non-secret
[vars]/ secret split - Providers — runtime / database / auth selection