ViteHub

Blob quickstart

Register Blob, write one local object, list stored objects, and verify the JSON result.

This guide creates two routes: one writes notes/example.txt, and one lists stored blobs. It uses the local fs driver so the first setup works without provider credentials.

Files are written under .data/blob. The route code stays the same when you later switch to Cloudflare R2 or Vercel Blob.

Prompt
Set up @vitehub/blob in this app.

- Install @vitehub/blob
- Register hubBlob() for Vite or @vitehub/blob/nitro for Nitro
- Configure blob.driver as fs with base .data/blob
- Add a PUT route that writes notes/example.txt with blob.put()
- Add a GET route that returns blob.list({ limit: 10 })
- Verify the PUT response and GET listing

Docs: /docs/vite/blob/quickstart or /docs/nitro/blob/quickstart

Install Blob

pnpm add @vitehub/blob

Register the Integration

Register the Nitro module and choose the local filesystem driver:

nitro.config.ts
import { defineNitroConfig } from 'nitro/config'

export default defineNitroConfig({
  modules: ['@vitehub/blob/nitro'],
  blob: {
    driver: 'fs',
    base: '.data/blob',
  },
})

Add the Routes

Add a Nitro route that writes one blob:

server/api/blob.put.ts
import { defineEventHandler, readBody } from 'h3'
import { blob } from '@vitehub/blob'

export default defineEventHandler(async (event) => {
  const body = await readBody<{ pathname?: string, value?: string }>(event)

  return await blob.put(
    body.pathname || 'notes/example.txt',
    body.value || 'hello world',
    { contentType: 'text/plain; charset=utf-8' },
  )
})

Add a second route that lists stored blobs:

server/api/blob.get.ts
import { defineEventHandler } from 'h3'
import { blob } from '@vitehub/blob'

export default defineEventHandler(async () => {
  return await blob.list({ limit: 10 })
})

Verify the Write

Start the app, then write a blob:

curl -X PUT http://localhost:3000/api/blob \
  -H 'content-type: application/json' \
  -d '{"pathname":"notes/example.txt","value":"hello world"}'

The route returns stored metadata:

{
  "pathname": "notes/example.txt",
  "contentType": "text/plain; charset=utf-8",
  "size": 11,
  "httpEtag": "\"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed\"",
  "uploadedAt": "2026-04-26T12:00:00.000Z",
  "httpMetadata": {
    "contentType": "text/plain; charset=utf-8"
  },
  "customMetadata": {}
}

Verify the Listing

curl http://localhost:3000/api/blob

The route returns a page of blobs:

{
  "blobs": [
    {
      "pathname": "notes/example.txt",
      "contentType": "text/plain; charset=utf-8",
      "size": 11
    }
  ],
  "hasMore": false
}
Store a blob
Write uploads, JSON bodies, metadata, prefixes, and randomized filenames.
Serve a blob
Return stored objects from H3 routes with content headers.
Cloudflare
Switch the same route code to Cloudflare R2.
Vercel
Switch the same route code to Vercel Blob.
Copyright © 2026