# How the CAD Viewer Handles Vercel Blob for Asset Storage in text-to-cad

> Discover how the CAD Viewer leverages Vercel Blob for global CDN asset storage in text-to-cad. Learn about efficient model file delivery.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: how-to-guide
- Published: 2026-08-01

---

**The CAD Viewer serves assets from Vercel Blob by instantiating a specialized backend when `VIEWER_ASSET_BACKEND` is set to `vercel-blob`, enabling global CDN delivery of model files and catalogs.**

The **earthtojake/text-to-cad** repository includes a web-based CAD viewer that supports multiple storage backends for its 3D assets. When configured for **Vercel Blob for asset storage**, the viewer utilizes a dedicated backend implementation that handles reading catalogs, uploading generated files, and caching responses for optimal performance.

## Backend Selection and Configuration

The viewer determines its storage backend through environment variables defined in `viewer/src/server/viewerEnv.mjs`. This module exports `VIEWER_ASSET_BACKENDS`, an object freezing the supported options: `local-fs` for local filesystem storage and `vercel-blob` for cloud object storage.

```js
// viewer/src/server/viewerEnv.mjs
export const VIEWER_ASSET_BACKENDS = Object.freeze({
  LOCAL_FS: "local-fs",
  VERCEL_BLOB: "vercel-blob",
});

```

The helper function `normalizeViewerAssetBackend` validates the `VIEWER_ASSET_BACKEND` environment variable against these constants, throwing an error if an unsupported backend is specified.

When **Vercel Blob** is selected, `vercelBlobConfigFromEnv` extracts configuration from environment variables including:
- `VIEWER_VERCEL_BLOB_PREFIX` – The base URL of the blob store
- `VIEWER_VERCEL_BLOB_CATALOG_PATH` – Path to the catalog JSON (defaults to [`catalog.json`](https://github.com/earthtojake/text-to-cad/blob/main/catalog.json))
- `VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN` – Authentication token for write operations

```js
// viewer/src/server/viewerEnv.mjs
export function vercelBlobConfigFromEnv(env = process.env) {
  const prefix = vercelBlobPrefixFromEnv(env);
  const catalogPath = envValue(env, "VIEWER_VERCEL_BLOB_CATALOG_PATH", "catalog.json") || "catalog.json";
  return {
    prefix,
    catalogPath,
    catalogUrl: vercelBlobCatalogUrlFromPrefix(prefix, catalogPath),
    token: envValue(env, "VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN") || envValue(env, "BLOB_READ_WRITE_TOKEN") || undefined,
  };
}

```

## Vercel Blob Asset Backend Implementation

The core functionality resides in `viewer/src/server/vercelBlobAssetBackend.mjs`, which exports `createVercelBlobAssetBackend`. This factory function accepts a configuration object and returns methods for interacting with the blob store.

### Reading the Catalog

The `fetchCatalog` method retrieves the JSON catalog either via public URL or the Vercel Blob SDK (`blob.get`). The implementation normalizes the response to filter out unwanted Python artifact entries, ensuring only valid CAD model references are exposed to the client.

### Writing Assets

For write-enabled deployments, the `writeAsset` method uses `blob.put` with `access: "public"` and optional `cacheControlMaxAge` headers. This supports uploading generated STEP files, GLB models, and other CAD artifacts directly to the Vercel Blob store.

### Caching Strategy

The backend supports in-memory catalog caching via the `catalogCacheTtlMs` parameter. This prevents repeated fetches during high-traffic periods, which is essential for CDN-friendly, read-only deployments where the catalog changes infrequently.

```js
// viewer/src/server/vercelBlobAssetBackend.mjs (excerpt)
export function createVercelBlobAssetBackend({
  prefix = "",
  catalogPath = "catalog.json",
  catalogUrl = "",
  client = null,
  fetchImpl = globalThis.fetch,
  token = process.env.VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN || process.env.BLOB_READ_WRITE_TOKEN,
  readOnly = false,
  catalogCacheTtlMs = 0,
} = {}) {
  const normalizedPrefix = normalizePrefix(prefix);
  const normalizedCatalogPath = joinBlobPath(normalizedPrefix, catalogPath || "catalog.json");
  const resolvedCatalogUrl = catalogUrl || publicBlobUrlForRef(prefix, catalogPath || "catalog.json");
  // ...
}

```

## Hosted Deployments and API Integration

For production deployments, `viewer/src/server/vercelApi.mjs` provides `createHostedCadBackendFromEnv`, which constructs a read-only Vercel Blob backend optimized for public hosting. This function enforces `readOnly: true` and sets a default cache TTL suitable for hosted environments.

The `handleHostedCadApi` function wraps the generic CAD viewer API middleware with this hosted backend, ensuring all requests are rewritten to `/__cad/*` and served using the cached Vercel Blob catalog.

```js
// viewer/src/server/vercelApi.mjs (excerpt)
export function createHostedCadBackendFromEnv(env = process.env) {
  const assetBackend = normalizeViewerAssetBackend(
    envValue(env, "VIEWER_ASSET_BACKEND"),
    VIEWER_ASSET_BACKENDS.VERCEL_BLOB
  );
  if (assetBackend !== VIEWER_ASSET_BACKENDS.VERCEL_BLOB) {
    throw new Error("Hosted CAD API requires VIEWER_ASSET_BACKEND=vercel-blob");
  }
  return createVercelBlobAssetBackend({
    ...vercelBlobConfigFromEnv(env),
    readOnly: true,
    catalogCacheTtlMs: HOSTED_CATALOG_CACHE_TTL_MS,
  });
}

```

## Configuration Examples

### Environment Variable Setup

To configure the viewer for **Vercel Blob for asset storage**, set the following environment variables before starting the server:

```bash
export VIEWER_ASSET_BACKEND=vercel-blob
export VIEWER_VERCEL_BLOB_PREFIX="https://my-store.public.blob.vercel-storage.com/models"
export VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN="vercel_blob_rw_abcdef12345"
export VIEWER_VERCEL_BLOB_CATALOG_PATH="catalog.json"
npm --prefix viewer run start

```

### Programmatic Backend Creation

For custom server implementations or tooling scripts, import the backend factory directly:

```js
import { createVercelBlobAssetBackend } from "./viewer/src/server/vercelBlobAssetBackend.mjs";

const backend = createVercelBlobAssetBackend({
  prefix: "https://my-store.public.blob.vercel-storage.com/models",
  catalogPath: "catalog.json",
  token: process.env.VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN,
  readOnly: false,
  catalogCacheTtlMs: 60_000,
});

// Upload a new GLB model
await backend.writeAsset({
  fileRef: "example.glb",
  body: glbBuffer,
  contentType: "model/gltf-binary",
});

```

### Hosted Deployment Initialization

For read-only hosted viewers that consume a pre-populated blob store:

```js
import { createHostedCadBackendFromEnv } from "./viewer/src/server/vercelApi.mjs";

(async () => {
  const backend = createHostedCadBackendFromEnv();
  const catalog = await backend.readCatalog();
  console.log("Available models:", catalog.entries.length);
})();

```

## Summary

- **Backend Selection**: The viewer uses `viewer/src/server/viewerEnv.mjs` to validate `VIEWER_ASSET_BACKEND` and parse Vercel Blob configuration from environment variables.
- **Asset Operations**: `createVercelBlobAssetBackend` in `viewer/src/server/vercelBlobAssetBackend.mjs` implements catalog fetching, asset uploading via `blob.put`, and URL generation for public access.
- **Performance Optimization**: The backend supports configurable catalog caching via `catalogCacheTtlMs` to minimize redundant network requests.
- **Hosted Mode**: `viewer/src/server/vercelApi.mjs` provides a read-only wrapper for production deployments, enforcing security constraints while maintaining CDN compatibility.

## Frequently Asked Questions

### What environment variables are required to use Vercel Blob for asset storage?

You must set `VIEWER_ASSET_BACKEND=vercel-blob` to activate the backend. Additionally, `VIEWER_VERCEL_BLOB_PREFIX` specifies the blob store URL, while `VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN` (or `BLOB_READ_WRITE_TOKEN`) is required for write operations. Optional variables include `VIEWER_VERCEL_BLOB_CATALOG_PATH` to customize the catalog location.

### How does the viewer cache catalog data when using Vercel Blob?

The `createVercelBlobAssetBackend` function accepts a `catalogCacheTtlMs` parameter that specifies the cache duration in milliseconds. When set to a positive value, the backend stores the fetched catalog in memory and returns cached results until the TTL expires, reducing latency and API calls to Vercel Blob.

### Can the Vercel Blob backend write assets or is it read-only?

The backend supports both modes depending on the `readOnly` parameter. When `readOnly` is `false`, the `writeAsset` method uses the Vercel Blob SDK to upload files with public access. Hosted deployments via `createHostedCadBackendFromEnv` explicitly force `readOnly: true` for security in public-facing environments.

### What file types does the Vercel Blob backend support?

The backend handles any file type stored in the blob container, including GLB models, STEP files, and JSON catalogs. Content types are preserved during upload via the `contentType` parameter in `writeAsset`, ensuring browsers and CAD viewers interpret the files correctly when served from Vercel Blob's CDN.