Blob runtime API
Use this page when you need exact names, signatures, and option fields. For a guided setup, start with Quickstart.
Imports
Most application code imports from @vitehub/blob:
import { blob, ensureBlob } from '@vitehub/blob'
Vite config imports the plugin from @vitehub/blob/vite:
import { hubBlob } from '@vitehub/blob/vite'
Runtime API
blob.list(options?)
Lists stored blobs.
const page = await blob.list({
folded: true,
limit: 20,
prefix: 'avatars/',
})
BlobListOptions supports:
| Option | Type | Description |
|---|---|---|
cursor | string | Resume a paginated listing. |
folded | boolean | Return folder-style listings with folders. |
limit | number | Maximum number of blobs to return. Defaults to provider behavior or 1000 in built-in drivers. |
prefix | string | Scope the listing to pathnames that start with this prefix. |
BlobListResult contains:
| Field | Type | Description |
|---|---|---|
blobs | BlobObject[] | Objects returned for the current page. |
cursor | `string | undefined` |
folders | `string | undefined` |
hasMore | boolean | Whether another page is available. |
blob.put(pathname, body, options?)
Writes one blob and returns its metadata.
const object = await blob.put('avatars/user-1.png', file, {
contentType: 'image/png',
customMetadata: { owner: 'user-1' },
})
body accepts:
| Type |
|---|
string |
Blob |
ArrayBuffer |
ArrayBufferView |
ReadableStream |
BlobPutOptions supports:
| Option | Type | Description |
|---|---|---|
access | `'private' | 'public'` |
addRandomSuffix | boolean | Add a short random suffix to the final filename. |
contentLength | string | Explicit content length hint for drivers that need it. |
contentType | string | Override the inferred content type. |
customMetadata | Record<string, string> | Driver-specific custom metadata. |
prefix | string | Prefix prepended to the normalized pathname before writing. |
When contentType is omitted, Blob uses the input Blob.type when present, then guesses from the final pathname extension.
blob.get(pathname)
Returns a Blob or null when the pathname does not exist.
const file = await blob.get('avatars/user-1.png')
const text = file ? await file.text() : null
blob.head(pathname)
Returns one BlobObject. Missing pathnames throw an H3 404 error.
const meta = await blob.head('avatars/user-1.png')
blob.del(pathname | pathnames[])
Deletes one blob or many blobs.
await blob.del('avatars/user-1.png')
await blob.del(['avatars/user-2.png', 'avatars/user-3.png'])
blob.serve(event, pathname)
Loads one blob body and returns a ReadableStream.
return await blob.serve(event, 'avatars/user-1.png')
serve() sets:
| Header | Description |
|---|---|
Content-Length | Byte length of the stored object body. |
Content-Type | Stored content type or inferred pathname content type. |
etag | Stored ETag when the active driver provides one. |
Missing pathnames throw an H3 404 error with File not found.
blob.store(name)
Selects a named Blob Store from runtime config and returns the same Blob API for that store.
const assets = blob.store('assets')
await assets.put('logo.png', file, {
contentType: 'image/png',
})
Validation API
ensureBlob(blob, options)
Validates one input Blob before storage.
ensureBlob(file, {
maxSize: '1MB',
types: ['image', 'application/pdf'],
})
BlobEnsureOptions supports:
| Option | Type | Description |
|---|---|---|
maxSize | BlobSize | Maximum accepted size such as 1MB, 8KB, or 256B. |
types | BlobType[] | Accepted broad type groups or exact MIME types. |
types supports audio, blob, image, pdf, text, video, and exact MIME strings like image/png.
Set at least one option. Failing validation throws an H3 400 error.
Core Types
BlobObject
| Field | Type | Description |
|---|---|---|
pathname | string | Stored object key. |
contentType | `string | undefined` |
size | `number | undefined` |
httpEtag | `string | undefined` |
uploadedAt | Date | Upload timestamp. |
httpMetadata | Record<string, string> | Driver HTTP metadata. |
customMetadata | Record<string, string> | Driver custom metadata. |
url | `string | undefined` |
BlobDriver
type BlobDriver =
| 'akamai'
| 'azure'
| 'box'
| 'cloudflare-r2'
| 'digitalocean-spaces'
| 'dropbox'
| 'fs'
| 'gcs'
| 'google-drive'
| 'hetzner'
| 'minio'
| 'netlify-blobs'
| 'onedrive'
| 's3'
| 'storj'
| 'supabase'
| 'uploadthing'
| 'vercel-blob'
Config API
The top-level config key is blob.
blob: {
driver: 'fs',
base: '.data/blob',
}
blob: {
driver: 'cloudflare-r2',
binding: 'BLOB',
bucketName: 'assets',
}
blob: {
driver: 'vercel-blob',
access: 'public',
token: process.env.BLOB_READ_WRITE_TOKEN,
}
BlobModuleOptions
Blob accepts:
| Shape | Description |
|---|---|
false | Disable Blob runtime setup. |
{ stores: { default: BlobStoreConfig, ... } } | Configure multiple named Blob Stores. |
{ driver: 'fs', base? } | Local filesystem storage. Defaults to .data/blob. |
{ driver: 'cloudflare-r2', binding?, bucketName? } | Cloudflare R2 storage. binding defaults to BLOB. |
{ driver: 'vercel-blob', access?, token? } | Vercel Blob storage. access defaults to public. |
{ driver: 's3', bucket, region?, endpoint? } | Amazon S3-compatible storage. |
{ driver: 'gcs', bucket, projectId? } | Google Cloud Storage. |
{ driver: 'azure', container, accountName? } | Azure Blob Storage. |
{ driver: 'supabase', bucket, url?, key? } | Supabase Storage. |
{ driver: 'netlify-blobs', name, siteID?, token? } | Netlify Blobs. |
| `{ driver: 'minio' | 'digitalocean-spaces' |
{ driver: 'uploadthing', token?, slug? } | UploadThing. |
| `{ driver: 'google-drive' | 'onedrive' |
On Cloudflare hosting, you can omit driver and pass binding or bucketName. Blob resolves those as Cloudflare R2 options.
Use stores.default when configuring multiple stores:
blob: {
stores: {
default: { driver: 'fs', base: '.data/blob' },
assets: { driver: 'fs', base: '.data/assets' },
},
}
Vite Config Import
Vite server code can read the resolved config from the stable import path:
import config, { blob, hosting } from '#vitehub/blob/config'
The generated config surface exposes:
| Export | Type |
|---|---|
hosting | `string |
blob | `false |
default | { hosting, blob } |

