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

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.

// 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)
  • VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN – Authentication token for write operations
// 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.

// 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.

// 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:

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:

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:

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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →