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

@vizbl/node

v0.1.0

Published

Official Node.js SDK for the Vizbl Developer API

Readme

Vizbl Node.js SDK

Official Node.js SDK for the Vizbl Developer API.

Installation

npm install @vizbl/node

Quick Start

import Vizbl from '@vizbl/node';

const vizbl = new Vizbl();

const result = await vizbl.objects.importModel({
  file: './chair.glb',
  name: 'Chair',
  wait: true,
});

console.log(result.tinuuid, result.url);

By default the SDK reads VIZBL_API_KEY from the environment and sends requests to https://api.vizbl.com.

Configuration

const vizbl = new Vizbl({
  apiKey: process.env.VIZBL_API_KEY,
  baseURL: 'https://api-dev.vizbl.com',
  timeoutMs: 30_000,
});

| Option | Description | | --- | --- | | apiKey | Developer API secret key. Defaults to process.env.VIZBL_API_KEY. | | baseURL | Developer API base URL. Defaults to process.env.VIZBL_BASE_URL, or https://api.vizbl.com. | | timeoutMs | Optional timeout in milliseconds for API requests and direct uploads. | | fetch | Optional custom Fetch API implementation. | | defaultHeaders | Additional headers sent with Developer API requests. |

API Reference

vizbl.objects.importModel(options)

Uploads one local model file or ordered model variants, creates an import job, and optionally waits for completion.

const job = await vizbl.objects.importModel({
  file: './chair.glb',
  name: 'Chair',
  wait: true,
});

| Option | Description | | --- | --- | | file | Local path, Blob, ArrayBuffer, Uint8Array, or { path | data, fileName, fileType } for a single-variant import. Use either file or variants. | | variants | Ordered source variants for multi-variant imports. The first variant is the main/default variant. Use either variants or file. | | name | Public object name. Defaults to the first file name without extension. | | description | Optional public object description. | | tags | Optional public object tags. | | category | Optional Vizbl category id. | | mechanic | Optional placement mechanic: all, floor, wall, or ceiling. | | ai_generate | Requests best-effort AI preview generation when supported. | | idempotencyKey | Optional key for safely retrying import job creation. | | uploadConcurrency | Maximum number of variant files uploaded in parallel. Defaults to 2. | | signal | Optional AbortSignal cancelling file resolution, presign, upload, and import job creation. Also cancels polling when wait is used without its own signal. | | wait | Pass true to wait for completion, false/omit to return the queued job, or pass { pollIntervalMs, maxWaitMs, signal }. |

When wait: true is used, the returned job includes tinuuid and url after a successful import.

const result = await vizbl.objects.importModel({
  name: 'Chair',
  variants: [
    { file: './chair-oak.glb', name: 'Oak' },
    { file: './chair-walnut.glb', name: 'Walnut' },
  ],
  wait: true,
});

console.log(result.tinuuid, result.url);

vizbl.objects.imports.create(request, options?)

Creates an import job from already uploaded source model variants. Use this when you want manual control over presign and direct upload.

const presign = await vizbl.uploads.presign({
  type: 'model_source',
  fileName: 'chair.glb',
  fileSize: 123456,
  fileType: 'model/gltf-binary',
});

// Upload the file to presign.uploadUrl with presign.uploadFields first.

const job = await vizbl.objects.imports.create({
  name: 'Chair',
  variants: [{ name: 'Default', uploadId: presign.uploadId }],
});

options.idempotencyKey sends the x-idempotency-key header.

vizbl.objects.imports.get(jobId)

Gets the current import job status, stage, warnings, error, tinuuid, and url when available.

const job = await vizbl.objects.imports.get('job-id');

vizbl.objects.imports.wait(jobId, options?)

Polls an import job until it succeeds, fails, times out, or is aborted.

const result = await vizbl.objects.imports.wait('job-id', {
  pollIntervalMs: 2_000,
  maxWaitMs: 15 * 60_000,
});

vizbl.objects.delete(tinuuid)

Deletes a published Vizbl object by public tinuuid.

await vizbl.objects.delete('tin_123');

vizbl.uploads.presign(request)

Creates a presigned upload session for a source model file. Most applications should use objects.importModel, which handles presign and upload internally.

const presign = await vizbl.uploads.presign({
  type: 'model_source',
  fileName: 'chair.glb',
  fileSize: 123456,
  fileType: 'model/gltf-binary',
});

Errors

The SDK throws VizblApiError for API, validation, auth, upload, and timeout failures. High-level import polling throws VizblImportError when a job fails or times out.

import { VizblApiError } from '@vizbl/node';

try {
  await vizbl.objects.importModel({ file: './chair.glb', wait: true });
} catch (error) {
  if (error instanceof VizblApiError && error.isAuthError()) {
    console.error('Check VIZBL_API_KEY');
  }
}

Development

pnpm install
pnpm generate
pnpm typecheck
pnpm test
pnpm build
pnpm validate

pnpm validate checks both @vizbl/node and @vizbl/mcp.

To refresh the OpenAPI schema from a deployed Developer API:

pnpm fetch-openapi
# or
VIZBL_OPENAPI_URL=https://api-dev.vizbl.com/developer-api/docs-json pnpm fetch-openapi

Local MCP Server

This repository also publishes @vizbl/mcp, a local stdio MCP server for agents like Codex and Claude Desktop. It uses @vizbl/node under the hood.

Codex:

codex mcp add vizbl \
  --env VIZBL_API_KEY=your_api_key \
  -- npx -y @vizbl/mcp

Claude Desktop:

{
  "mcpServers": {
    "vizbl": {
      "command": "npx",
      "args": ["-y", "@vizbl/mcp"],
      "env": {
        "VIZBL_API_KEY": "your_api_key"
      }
    }
  }
}

Available tools:

  • vizbl_import_model
  • vizbl_get_import
  • vizbl_wait_import
  • vizbl_delete_object

Note: vizbl_import_model defaults wait to true, the opposite of the SDK's objects.importModel default (false/omit), since agent workflows generally want the final result rather than a queued job id.

Architecture documentation

The cross-repository Remote MCP architecture, implementation plan, and team backlogs are documented in docs/remote-mcp/README.md.