Providers

Cloudflare

Serve bundles from R2 behind a Cloudflare Worker.

The Cloudflare provider serves bundles from an R2 bucket through a Worker, using a KV namespace to record which version is deployed.

Provision the server

@wvb/remote-cloudflare-provider-pulumi provisions the Worker, R2 bucket, and KV namespace as a Pulumi component:

npm install @wvb/remote-cloudflare-provider-pulumi
index.ts
import { WebviewBundleRemoteProvider } from '@wvb/remote-cloudflare-provider-pulumi';

const remote = new WebviewBundleRemoteProvider('wvb', {
  accountId: '<cloudflare-account-id>',
});

export const bucketName = remote.bucketName;
export const kvNamespaceId = remote.kvNamespaceId;

To write the Worker yourself, @wvb/remote-cloudflare-provider exports a Hono app. Bind an R2 bucket as BUCKET and a KV namespace as KV, then map them into the handler:

src/worker.ts
import { wvbRemote } from '@wvb/remote-cloudflare-provider';

const app = wvbRemote();

export default {
  fetch(req: Request, env: { KV: KVNamespace; BUCKET: R2Bucket }) {
    return app.fetch(req, { kv: env.KV, r2: env.BUCKET });
  },
};

Publish to it

@wvb/remote-cloudflare provides the uploader and deployer for your config:

npm install -D @wvb/remote-cloudflare
wvb.config.ts
import { defineConfig } from '@wvb/config';
import { cloudflareRemote } from '@wvb/remote-cloudflare';

export default defineConfig({
  remote: {
    endpoint: 'https://updates.example.com',
    ...cloudflareRemote({
      accountId: '<cloudflare-account-id>',
      bucket: 'webview-bundle',
      kvNamespaceId: '<kv-namespace-id>',
    }),
  },
});

The uploader writes to R2 over the S3-compatible API, so pass R2 access keys through its s3ClientConfig.credentials; the deployer updates KV with a Cloudflare API token. See the Cloudflare client reference for the full config.

The Worker reads an R2 binding named BUCKET and a KV binding named KV. Match those names in your wrangler.jsonc.

On this page