Cloudflare R2
Use the Cloudflare provider when Blob storage should resolve through a Cloudflare R2 bucket.
Cloudflare needs two pieces: an R2 bucket bound to the runtime and Blob config that uses the same binding name.
Create and Bind an R2 Bucket
Create an R2 bucket in Cloudflare, then bind it to the Worker or Pages project that runs your app.
ViteHub looks for a binding named BLOB by default.
Configure Blob
Register the Vite plugin and set blob.driver to cloudflare-r2:
import { defineConfig } from 'vite'
import { hubBlob } from '@vitehub/blob/vite'
export default defineConfig({
plugins: [hubBlob()],
blob: {
driver: 'cloudflare-r2',
binding: 'BLOB',
bucketName: 'assets',
},
})
Use a Different Binding Name
Set binding when your R2 binding does not use the default BLOB name.
blob: {
driver: 'cloudflare-r2',
binding: 'FILES',
bucketName: 'assets',
}
At runtime, the Cloudflare driver reads that binding from the active request environment. If the binding is missing, Blob throws:
R2 binding "FILES" not found
Generate Cloudflare Output
When bucketName is set, ViteHub can emit the R2 bucket binding into generated Cloudflare output.
Vite builds write a generated wrangler.json for the Cloudflare output. The R2 binding is included when Blob resolves a Cloudflare R2 store with bucketName.
You can also provide the bucket name with an environment variable during config resolution:
BLOB_BUCKET_NAME=assets
CLOUDFLARE_R2_BUCKET_NAME is also supported.
Use Hosting Inference
On Cloudflare hosting, Blob resolves cloudflare-r2 automatically when no explicit driver is configured.
blob: {
binding: 'BLOB',
bucketName: 'assets',
}
Cloudflare hosting takes precedence over Vercel Blob environment inference.
Verify the Provider
Call a route that writes a known object:
curl -X PUT http://localhost:3000/api/blob \
-H 'content-type: application/json' \
-d '{"pathname":"notes/cloudflare.txt","value":"stored in r2"}'
A successful response includes the R2 object pathname:
{
"pathname": "notes/cloudflare.txt",
"contentType": "text/plain; charset=utf-8",
"size": 12
}
Common Failures
| Symptom | Cause | Fix |
|---|---|---|
R2 binding "BLOB" not found | The runtime request environment does not include the configured R2 binding. | Add the binding in Cloudflare or set blob.binding to the existing binding name. |
| Generated output has no R2 bucket binding | Blob resolved Cloudflare R2 without bucketName. | Set blob.bucketName, BLOB_BUCKET_NAME, or CLOUDFLARE_R2_BUCKET_NAME. |
Local development writes to .data/blob instead of R2 | Hosting inference did not detect Cloudflare. | Set blob.driver to cloudflare-r2 explicitly. |

