Object Storage
R2 buckets through a typed store: upload, download, and list with folder semantics.
Object storage holds files: uploads, generated assets, exports. Base wraps R2 in a typed ObjectStore with the same declare-bind-inject shape as every other resource.
Declare the bucket
In wrangler.toml — note R2 has two names, the bucket and its binding:
In settings.ts, mirror both, and declare visibility:
A public bucket requires its domains map (environment → public hostname). A private bucket declares privateBucket: true instead, and the types then forbid domains entirely, so the "private bucket with a public URL" mistake doesn't compile.
Inject and use
The surface:
put(key, data, options?): data as string, Blob, ArrayBuffer, or ReadableStream (streams pass through unbuffered); options carryhttpMetadata(content type etc.),customMetadata, andstorageClass.get(key)→ object data + metadata, readable asbody(stream),text(),json<T>(),arrayBuffer(), orblob();head(key)for metadata only.delete(key | key[]): accepts an array for bulk deletion.list(options?)—prefix+cursorpaging, plusdelimiterfor folder-style browsing: withdelimiter: '/', the result'sdelimitedPrefixesare the "subfolders" at that level.
Choosing a store
Objects are for payloads — things with a size and a content type. Keep the reference (key, size, owner) in the database, the bytes in the bucket, and hand public files out via the bucket's domain rather than proxying them through your worker.