> ## Documentation Index
> Fetch the complete documentation index at: https://better-router.bansal.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy to Cloudflare

> Add Wrangler, declare bindings, add a worker entrypoint, and deploy.

This walkthrough takes a better-router app from `vite dev` to a Cloudflare Worker with bindings on `env`.

## 1. Point Wrangler at the build

```jsonc title="wrangler.jsonc" theme={null}
{
  "name": "my-app",
  "compatibility_date": "2026-09-01",
  "compatibility_flags": ["nodejs_compat"],
  "main": "./dist/server/index.js",
  "assets": {
    "directory": "./dist/client"
  }
}
```

`nodejs_compat` is required for `getEnv()`. Static files from `dist/client` are served in front of the Worker. The plugin sees Wrangler and sets `target: "cloudflare"`.

## 2. Bindings

Add whatever Cloudflare products you need. They show up on `getEnv()` / `c.env` during `fetch`.

```jsonc title="wrangler.jsonc" theme={null}
{
  "vars": {
    "APP_URL": "https://example.com"
  },
  "d1_databases": [
    { "binding": "DB", "database_name": "app", "database_id": "<id>" }
  ]
}
```

```ts title="src/env.d.ts" theme={null}
declare module "better-router" {
  interface AppBindings {
    DB: D1Database;
    APP_URL: string;
  }
}
```

```ts title="src/routes/index.server.tsx" theme={null}
import { getEnv } from "better-router";

export async function loader() {
  const { DB, APP_URL } = getEnv();
  const { results } = await DB.prepare("select 1 as ok").all();
  return { appUrl: APP_URL, ok: results };
}
```

Secrets:

```bash theme={null}
npx wrangler secret put STRIPE_SECRET
```

Local Wrangler secrets go in `.dev.vars`. Full list of binding kinds: [Bindings](/bindings).

## 3. Worker entrypoint

`fetch` is the Hono app. Add cron, queue, or inbound email in `src/worker.ts`:

```ts title="src/worker.ts" theme={null}
import { defineWorker } from "better-router/worker";

export default defineWorker({
  async scheduled(event, env) {
    await (env.DB as D1Database)
      .prepare("insert into heartbeats (at) values (?)")
      .bind(event.scheduledTime)
      .run();
  },
});
```

List the same cron in Wrangler:

```jsonc theme={null}
{
  "triggers": {
    "crons": ["*/5 * * * *"]
  }
}
```

Details: [Worker entrypoint](/worker).

## 4. Deploy

```bash theme={null}
npx vite build
npx wrangler deploy
```

After deploy:

* `/` is SSR HTML with `/assets/client.js`
* `/api/hello` is JSON from Hono
* `getEnv().DB` is the D1 binding on Worker requests
* `scheduled` runs when Cloudflare fires the cron

`vite dev` serves HTTP only. Use `wrangler dev` after a build when you need Miniflare bindings.

A complete D1 + queue + cron app is in [`examples/cloudflare`](https://github.com/bansal/better-router/tree/main/examples/cloudflare).
