ViteHub

Blob

Store, list, read, serve, and delete files from Vite and Nitro server code with one provider-neutral Blob API.

@vitehub/blob gives Vite and Nitro apps one server-side Blob API for local files, Cloudflare R2, and Vercel Blob.

Use Blob when routes need to accept user files, write generated assets, list stored objects, or stream a stored file back through the application.

import { createError, defineEventHandler, readFormData } from 'h3'
import { blob, ensureBlob } from '@vitehub/blob'

export default defineEventHandler(async (event) => {
  const form = await readFormData(event)
  const file = form.get('file')

  if (!(file instanceof Blob)) {
    throw createError({ statusCode: 400, statusMessage: 'Expected a file upload.' })
  }

  ensureBlob(file, { maxSize: '1MB', types: ['image'] })

  return await blob.put('avatar.png', file, {
    addRandomSuffix: true,
    prefix: 'avatars',
  })
})

What Blob Solves

Object storage APIs differ by platform. Blob keeps route code focused on pathnames, bodies, metadata, and streams while the active driver handles provider details.

Portable writes

Store strings, Blobs, ArrayBuffers, typed arrays, or streams with the same blob.put() call.

Listings and metadata

Page through objects with prefix, limit, cursor, and folded folder-style listings.

Route streaming

Serve stored files from H3 routes with content headers set by blob.serve().

Upload checks

Reject files by MIME type or size before they reach storage with ensureBlob().
Storage Providers
Configure S3, GCS, Azure, Supabase, Netlify Blobs, and app storage drivers.

One Portable Flow

The same shape works across supported runtimes:

  1. Install @vitehub/blob.
  2. Register hubBlob() for Vite or @vitehub/blob/nitro for Nitro.
  3. Choose a storage driver or let hosting inference pick one.
  4. Use blob.put(), blob.list(), blob.get(), blob.head(), blob.del(), and blob.serve() from server routes.
  5. Move provider-specific tokens, bindings, and bucket names into config or environment.
Blob is a server-side API. Import blob from server routes, handlers, or build-generated server entries, not from browser code.

Storage Resolution

ViteHub resolves Blob storage in this order:

  1. Explicit blob.driver config wins.
  2. Cloudflare hosting resolves cloudflare-r2.
  3. BLOB_READ_WRITE_TOKEN resolves vercel-blob.
  4. Vercel hosting resolves vercel-blob.
  5. Everything else falls back to fs at .data/blob.

Supported Storage Paths

Local filesystem
Use the fs driver for local development and non-hosted server storage.
Cloudflare R2
Store blobs through an R2 binding on Cloudflare Workers or Pages.
Vercel Blob
Store blobs through Vercel Blob with BLOB_READ_WRITE_TOKEN.

Start Here

Start with Quickstart for a local fs setup. Use the primitive comparison when you are choosing between Blob, KV, Queue, Sandbox, and inline response data.

Next Steps

Quickstart
Register Blob, write one object, list it, and verify the JSON result.
Usage
Use pathnames, metadata, pagination, serving, deletes, and upload validation.
Store a blob
Accept an upload or JSON body and write it through the portable runtime API.
Serve a blob
Stream stored files from routes with provider-neutral headers.
Runtime API
Review exports, method signatures, option fields, and config types.
Troubleshooting
Fix disabled runtime config, missing R2 bindings, Vercel tokens, and failed lookups.
Copyright © 2026