npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vite-hub/blob

v0.0.3

Published

Vite-first blob storage primitives and deployment integration for ViteHub.

Downloads

3,063

Readme

@vite-hub/blob

@vite-hub/blob gives server code one object-storage API across local files and hosted blob providers.

Install

pnpm add @vite-hub/blob

Add the SDK required by the driver you configure.

Minimal API

// server/api/files.post.ts
import { blob } from "@vite-hub/blob"
import { defineEventHandler, readBody } from "h3"

export default defineEventHandler(async (event) => {
  const body = await readBody<{ path: string, text: string }>(event)

  const [writeError] = await blob.put(body.path, body.text, { contentType: "text/plain" })
  if (writeError) throw writeError

  const [readError, file] = await blob.get(body.path)
  if (readError) throw readError
  return file
})
// vite.config.ts
import { hubBlob } from "@vite-hub/blob/vite"
import { defineConfig } from "vite"

export default defineConfig({
  blob: {
    driver: "fs",
    base: ".data/blob",
  },
  plugins: [hubBlob()],
})

Vite Integration

Use hubBlob() in Vite to resolve blob config and expose the blob runtime helper to server code.

Core drivers include local fs, Vercel Blob, Cloudflare R2, S3-compatible stores, and files-sdk. At config time, the fs driver uses BLOB_FS_BASE when blob.base is omitted, then defaults to .data/blob.

Set blob.serve to generate a Nitro route for serving Blob-backed assets. serve: true uses /api/_vitehub/blob as a safe namespaced API route. Use serve.route for product-facing paths such as /assets. Objects from the served store receive an absolute URL when serve.publicBaseUrl is configured, or a route-relative URL otherwise. Use serve.headers for static cache and security headers. Blob metadata remains authoritative for content headers such as Content-Type, Content-Length, and ETag.

Use detectContentType() when an application needs to classify leading bytes before storage. It returns a detected MIME type for common images and PDFs, or undefined when the signature is unknown. Storage contentType remains caller-provided metadata, and recognizing a signature does not prove that a complete file is valid or safe.

import { detectContentType } from "@vite-hub/blob/content-type"

const detected = detectContentType(new Uint8Array(await file.arrayBuffer()))
if (detected !== file.type) throw new Error("File content does not match its declared type")
// vite.config.ts
export default defineConfig({
  blob: {
    driver: "fs",
    serve: {
      route: "/assets",
      headers: {
        "Cache-Control": "public, max-age=300",
        "X-Content-Type-Options": "nosniff",
      },
    },
  },
  plugins: [hubBlob()],
})

Blob stores binary objects and small object metadata. Keep catalogs, indexes, permissions, search records, domain records, and richer metadata queries in KV, Database, or another NoSQL/catalog store next to Blob.

Signed requests

Use blob.sign() to grant short-lived access to one private object without routing its body through your server.

const [downloadError, download] = await blob.sign("private/audio.mp3", {
  method: "GET",
  expiresIn: 60 * 60,
})
if (downloadError) throw downloadError

const [uploadError, upload] = await blob.sign("private/audio.mp3", {
  method: "PUT",
  expiresIn: 15 * 60,
  contentType: "audio/mpeg",
  createOnly: true,
})
if (uploadError) throw uploadError

await fetch(upload.url, {
  method: upload.method,
  headers: upload.headers,
  body: file,
})

Blob operations return [error, value]. Provider and storage failures use ViteHubError with a stable BLOB_* code, operation/store details, and the provider failure in cause. Invalid arguments, unknown stores, and unsupported signing capabilities still throw because they are configuration or API misuse rather than an operational result.

The returned headers are part of the request contract and must be sent unchanged. createOnly prevents overwriting an existing object when the driver can enforce a conditional upload.

S3-compatible storage

Use driver: "s3" for production S3-compatible object storage. Use driver: "minio" for local or Docker Compose object storage, and use driver: "cloudflare-r2" for Cloudflare R2.

pnpm add files-sdk @aws-sdk/client-s3 @aws-sdk/s3-presigned-post @aws-sdk/s3-request-presigner

Cloudflare R2 HTTP fallback also requires:

pnpm add @aws-sdk/lib-storage
// vite.config.ts
export default defineConfig({
  blob: {
    driver: "s3",
    bucket: "app-assets",
    endpoint: process.env.S3_ENDPOINT,
    region: process.env.S3_REGION,
    publicBaseUrl: "https://assets.example.com",
  },
  plugins: [hubBlob()],
})

Store S3 credentials in Server Env or the provider credential chain used by the S3 SDK.

MinIO

MinIO is the Docker-friendly S3-compatible path. Select it explicitly:

pnpm add files-sdk @aws-sdk/client-s3 @aws-sdk/s3-presigned-post @aws-sdk/s3-request-presigner
// vite.config.ts
export default defineConfig({
  blob: {
    driver: "minio",
  },
  plugins: [hubBlob()],
})

ViteHub reads common Docker Compose env names:

MINIO_ENDPOINT=http://minio:9000
MINIO_ROOT_USER=minio
MINIO_ROOT_PASSWORD=password
BLOB_BUCKET_NAME=vitehub-blob

The Files SDK native MINIO_ACCESS_KEY_ID and MINIO_SECRET_ACCESS_KEY env names are also accepted.

You can also keep the config self-contained:

blob: {
  driver: "minio",
  accessKeyId: process.env.MINIO_ROOT_USER,
  bucket: "vitehub-blob",
  endpoint: "http://minio:9000",
  forcePathStyle: true,
  secretAccessKey: process.env.MINIO_ROOT_PASSWORD,
}

Learn more at vitehub.dev.