Add a Cloudflare feature
Goribu writes your Wrangler configuration (Workers configuration) from goribu.config.js. Put the extra Wrangler fields in a wrangler block:
import { defineConfig } from "goribu/server";
export default defineConfig({
name: "my-app",
compatibilityDate: "2026-09-01",
// Add this
wrangler: {
ai: { binding: "AI" },
services: [{ binding: "SEARCH", service: "search-worker" }],
vars: { API_HOST: "api.example.com" },
observability: { enabled: true, head_sampling_rate: 0.1 },
},
});
Your handlers then read each binding from req.env by the name you gave it:
import type { Handler } from "goribu/server";
type Env = {
AI: { run(model: string, input: { prompt: string }): Promise<{ response?: string }> };
};
export const GET: Handler<Record<string, unknown>, Env> = async (req, res) => {
const prompt = req.query.get("q") ?? "Say hi in five words";
const answer = await req.env.AI.run("@cf/meta/llama-3.2-1b-instruct", { prompt });
return res.json({ answer: answer.response });
};
export const GET = async (req, res) => {
const prompt = req.query.get("q") ?? "Say hi in five words";
const answer = await req.env.AI.run("@cf/meta/llama-3.2-1b-instruct", { prompt });
return res.json({ answer: answer.response });
};
- Cloudflare's names: The block uses Wrangler's field names and shapes exactly as Cloudflare documents them, such as
ai,services,vectorize,queues.producers,analytics_engine_datasets,browser,vars,observabilityandlimits. - Goribu's settings first: Goribu writes its own fields, then adds yours. Always edit
goribu.config.js, never the generatedgoribu.wrangler.jsonc. - Resources exist already: Goribu doesn't create what these non-integrated bindings point to. An index, a queue or another Worker must already exist on Cloudflare.
- Telemetry: Wrangler sends anonymous usage data to Cloudflare by default. Add
send_metrics: falseto the block to turn it off for this app.
Mistakes are caught early
Every pnpm dev and pnpm build checks the block before Cloudflare sees it, so a typo fails right away instead of being quietly ignored:
[Goribu] wrangler.observability contains unknown field "head_samplng_rate". Check its spelling against Wrangler's configuration reference. This Goribu installation uses Wrangler 4.127.1; if the field needs a newer Wrangler, update goribu.
- Plain data only: The block must be JSON. Functions,
undefined,Infinity, dates, sparse arrays and circular objects fail with the path to fix, such aswrangler.vars.STARTED_AT. - Unknown fields: The whole generated config is checked against the schema that comes with Goribu's Wrangler, including nested fields and array entries such as
wrangler.services[0]. - Wrangler's own rules: Problems like two bindings sharing a name are caught by Wrangler itself and shown as a
[Goribu]error. - Newer features: Goribu deploys with the Wrangler version it includes, and Wrangler ignores fields it doesn't know yet. The check turns those into errors. If a field from Cloudflare's docs is rejected, update
goribu, or use a newer Wrangler yourself.
Use a newer Wrangler
To use a Cloudflare feature before Goribu includes a Wrangler that knows it, override Goribu's Wrangler version in package.json, then run pnpm install:
{
"pnpm": {
"overrides": {
"wrangler": "4.151.0"
}
}
}
- Everything follows:
pnpm dev,pnpm build,pnpm checkandpnpm run deployuse that version, and the check reads its schema, so errors name the version you chose. - Not tested by Goribu: Goribu relies on some of Wrangler's experimental APIs, which can change between releases. If dev or build breaks, remove the override.
- Remove it later: Once a Goribu update includes that Wrangler version or newer, delete the override.
What Goribu manages
Some Wrangler fields belong to Goribu. Setting them in the block fails with the reason and where to configure them instead:
| Fields | Why |
|---|---|
name, compatibility_date, compatibility_flags, workers_dev, main, assets, preview_urls, account_id | Set them with Goribu's own options. CLOUDFLARE_ACCOUNT_ID chooses the account. |
d1_databases, kv_namespaces, r2_buckets, hyperdrive | Use database, kv and r2. Extra databases, namespaces and buckets aren't supported yet. |
routes, route, env, previews, compliance_region, pages_build_output_dir | Goribu deploys one production Worker and connects your domain itself. |
dev, build, alias, define, minify, rules, no_bundle, tsconfig and other bundling fields | Vite builds your app. Use vite.config.js instead. |
triggers, migrations, exports, containers, queues.consumers | They need Worker handlers or exported classes, which Goribu doesn't support yet. |
unsafe | It bypasses Wrangler's checks. |
Durable Objects and Workflows
You can bind a Durable Object or a Workflow that another Worker defines. Name that Worker with script_name:
import { defineConfig } from "goribu/server";
export default defineConfig({
name: "my-app",
compatibilityDate: "2026-09-01",
wrangler: {
durable_objects: {
bindings: [{ name: "COUNTER", class_name: "Counter", script_name: "counter-worker" }],
},
workflows: [
{ binding: "ONBOARDING", name: "onboarding", class_name: "Onboarding", script_name: "onboarding-worker" },
],
},
});
A class defined in your own app needs exports Goribu doesn't offer yet, so an entry without script_name fails.
Reserved names
ASSETS, DB, KV, R2, R2_PRIVATE, POSTGRES, POSTGRES_CACHED, and any name starting with GORIBU_ or __GORIBU_ belong to Goribu. You can't use them for a binding or a var, even if you don't use the matching feature. That way, adding KV later can never clash with a KV of your own.
Vars and secrets
wrangler.vars is for plain settings, such as an API host or a feature switch. Values can be strings or other JSON, such as numbers or objects.
- Not for secrets: Vars are written into the deploy config and into your Worker's code, because the Worker imports
goribu.config.js. Put API keys in.env.productioninstead or on your Worker via dashboard directly. - Local overrides: In development, the same key in
.envor.dev.varswins over the var.
Placement
Your Worker normally runs in the Cloudflare location closest to each visitor. If a request spends most of its time waiting on one backend, such as your database, placement runs the Worker near that backend instead:
import { defineConfig } from "goribu/server";
export default defineConfig({
name: "my-app",
compatibilityDate: "2026-09-01",
wrangler: {
placement: { mode: "smart" },
},
});
- Smart: Cloudflare watches your traffic and moves the Worker only once a closer location proves faster.
- Your choice: Use
{ region: "aws:us-east-1" }for a cloud region,{ host: "db.example.com:5432" }for a database or other TCP service, or{ hostname: "api.example.com" }for an HTTP API. See Cloudflare's placement docs. - Static pages: They're still served near the visitor. Placement moves only requests that reach the Worker.
- Development:
pnpm devruns on your machine, so placement has no effect there.
Development
Most bindings run locally in pnpm dev. Workers AI is different: Cloudflare runs it even while you develop, and so do AI Search, Media, VPC and a few others, plus any binding you mark remote: true.
- Login needed: When your app declares one of these,
pnpm devfirst checks your Cloudflare login and uses the same account as deploy. Without a login it stops with an error that names the binding. - Fix: Run
pnpm exec goribu cloudflare-login, or setCLOUDFLARE_API_TOKENin CI. With several accounts, setCLOUDFLARE_ACCOUNT_ID. - Real usage: Calls made in development reach the real service and count toward your Cloudflare usage.
- Other Workers: A service binding to a Worker that isn't running on your machine answers with an error until you start that Worker.
Builds and static pages
pnpm build never needs a Cloudflare login. When it prerenders pages, it runs your app without the block's bindings, except vars. The uploaded Worker gets all of them.
- Vars work: A static page that reads only vars prerenders normally.
- Bindings don't: A page that calls a binding such as
AIwhile rendering stays on the Worker and is rendered per request.
Check and deploy
pnpm check lists these bindings in their own section, marked as not inspected or managed by Goribu. pnpm run deploy uploads them exactly as written, alongside everything Goribu sets up.
Not supported yet
- More resources: A second D1 database, KV namespace, R2 bucket or Hyperdrive config.
- Worker handlers and classes: Cron triggers, queue consumers, your own Durable Objects and Workflows, and containers. Run them in a separate Worker and connect your app to it with
services,queues.producersorscript_name. - Other: Wrangler environments.
If a later version makes Goribu own a field that works today, it will be a breaking change with upgrade notes.