For the complete documentation index, see llms.txt. Prefer markdown by appending.mdto documentation URLs or sendingAccept: text/markdown.
Wrangler and bindings
Configure Cloudflare bindings in wrangler.jsonc. D1, KV, R2, Queues, Email, AI, rate limits, flags, routes, and generated types.
wrangler.jsonc is the source of truth for your Cloudflare infrastructure. It declares the Worker, its routes, non-secret variables, and every binding. The Cloudflare Vite plugin reads it in development, and wrangler deploy reads it in production.
Update the relevant fields in your existing file. Keep its compatibility_date and compatibility_flags, change them deliberately when adopting and testing new Workers runtime behavior.
{
"name": "edge",
// Keep your project's compatibility_date.
"compatibility_flags": ["nodejs_compat"],
"main": "src/server.ts",
"vars": {
"BETTER_AUTH_URL": "https://edge.turbostarter.dev",
"EMAIL_FROM": "TurboEdge <noreply@edge.turbostarter.dev>",
"VITE_PRODUCT_NAME": "TurboEdge",
"VITE_URL": "https://edge.turbostarter.dev"
},
...
}Production resources
The committed file points at the demo's resources. Before you deploy, swap the name, domain, vars, and every binding ID for your own resources.
Bindings
| Binding | Type | Used for |
|---|---|---|
DB | D1 | Application database (Drizzle) |
KV | KV namespace | Caching and app configuration |
UPLOADS | R2 bucket | File storage and delivery |
QUEUE | Queue producer | Background job delivery |
EMAIL | Send email | Transactional email |
AUTH_RATE_LIMIT | Rate limit | Throttling sign-in routes |
FLAGS | Flagship | Feature flags (remote in dev) |
AI | Workers AI | AI inference (remote in dev) |
Use them anywhere on the server through the runtime:
import { env } from "cloudflare:workers";
const user = await env.DB.prepare("SELECT 1").first();D1
"d1_databases": [
{
"binding": "DB",
"database_name": "edge-production",
"database_id": "<your-database-id>",
"migrations_dir": "drizzle"
}
]Create your database with pnpm wrangler d1 create <name> and paste the returned database_id. migrations_dir points Wrangler at the Drizzle output.
KV
"kv_namespaces": [{ "binding": "KV", "id": "<your-namespace-id>" }]The KV binding and src/lib/kv.ts helper are already wired. Use them for cached public content, read-heavy lookup data, or application settings such as homepage announcements. The helper exposes kv.get, kv.put, and kv.remove.
Create your production namespace with pnpm wrangler kv namespace create KV and put its ID in wrangler.jsonc. Local development provides a local namespace that you can inspect in Local Explorer.
For example, add server-side helpers for a homepage announcement:
import { env } from "cloudflare:workers";
import { kv } from "@/lib/kv";
export const setAnnouncement = (value: string) =>
kv.put({
namespace: env.KV,
key: "homepage:announcement",
value,
options: { expirationTtl: 3600 },
});
export const getAnnouncement = () =>
kv.get({
namespace: env.KV,
key: "homepage:announcement",
});kv.get returns the stored string or null. When you withdraw an announcement, call kv.remove({ namespace: env.KV, key: "homepage:announcement" }). Keep writes behind an authorized server function, and return the value to your UI through a server function.
KV is optimized for frequent reads with infrequent updates. Use it for data that tolerates a short update delay; keep transactions and permission checks in D1.
The caching guide covers key design, expiration, invalidation, and the relationship between KV and client query caches.
R2
"r2_buckets": [{ "binding": "UPLOADS", "bucket_name": "<your-bucket>" }]Create it with pnpm wrangler r2 bucket create <name>.
Queues
"queues": {
"producers": [{ "binding": "QUEUE", "queue": "<your-queue>" }],
"consumers": [{ "queue": "<your-queue>" }]
}The same Worker produces and consumes jobs. Job handlers live in src/lib/queue/jobs. Create the queue with pnpm wrangler queues create <name>.
"send_email": [
{
"name": "EMAIL",
"allowed_sender_addresses": ["noreply@<your-domain>"]
}
]EMAIL_FROM must use an address listed in allowed_sender_addresses, on a domain you've onboarded to Cloudflare Email.
Rate limit
"ratelimits": [
{
"name": "AUTH_RATE_LIMIT",
"namespace_id": "91001",
"simple": { "limit": 10, "period": 60 }
}
]Allows 10 requests per 60 seconds on the auth routes. Pick a unique namespace_id per account and tune limit and period as needed.
Feature flags and AI
"flagship": [{ "binding": "FLAGS", "app_id": "<your-app-id>", "remote": true }],
"ai": { "binding": "AI", "remote": true }These are remote bindings: Wrangler can't simulate them, even with "remote": false. Local dev needs CLOUDFLARE_API_TOKEN or pnpm wrangler login and valid resources in your account. A remote proxy error can prevent startup. The flags helper returns a default for evaluation failures after startup; it does not repair remote credentials or an invalid app ID.
Follow feature flags for typed values, targeting, and rollouts, and AI setup for gateway and model access.
Routes and domain
"routes": [{ "pattern": "<your-domain>", "custom_domain": true }]With custom_domain, Cloudflare creates the DNS record and certificate for you. Remove the block to use only the workers.dev URL ("workers_dev": true).
Observability
Logs and traces are on by default through the observability block, with full sampling. Lower head_sampling_rate if volume or cost becomes a concern. Use log from src/lib/log.ts for structured logs.
See observability for request IDs, production logs, analytics, and liveness checks.
Binding types
Binding types live in worker-configuration.d.ts, generated from this file. After any change, run:
pnpm cf-typegenNever edit the generated file by hand.
How is this guide?
Last updated on
Environment variables
How Edge Kit loads and validates configuration. Secrets in .env.local, public VITE_ values, wrangler.jsonc vars, and envin validation.
App configuration
Shared product settings for your Edge app's name, public URL, default language, and version across the interface, metadata, and emails.