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

@three-ws/forge

v0.1.0

Published

Text/image/sketch → textured, rig-ready 3D GLB in one call. The three.ws Forge generation SDK — free TRELLIS lane, paid high-detail tiers, and auto-rigging.

Readme


@three-ws/forge is the official client for the three.ws Forge — the generation engine behind three.ws/forge. It turns a prompt, a photo, or a sketch into a watertight, textured GLB, and can auto-rig that GLB into an animation-ready humanoid. It wraps the public, auth-free /api/forge endpoint: a free TRELLIS lane on NVIDIA NIM, paid high-detail tiers billed in USDC over x402, and bring-your-own-key geometry backends (Meshy, Tripo). It pairs with @three-ws/avatar — Forge makes the model, @three-ws/avatar renders it.

Why

Every "text-to-3D" you find is either a closed playground with no API, or a raw model endpoint that hands you an untextured mesh and leaves rigging, polygon budgets, provider fallback, job polling, and billing to you. Forge is the whole pipeline, done once:

  • One call, a real GLB. forge('a chrome robot') resolves to a hosted, durable .glb URL plus a three.ws viewer link.
  • Free first. Text prompts default to the free NVIDIA NIM / TRELLIS lane — no key, no wallet, no card.
  • Scales with the asset. Three quality tiers (draft → standard → high) map to real polygon budgets and PBR texturing. Pay per call in USDC only when you reach for the paid tiers.
  • Rig-ready. One flag chains generation into auto-rigging, so the output drops straight into the three.ws animation runtime — idle, walk, emotes.

This is the SDK twin of the 3D Studio MCP server — the same engine, exposed as plain functions instead of MCP tools.

Install

npm install @three-ws/forge

Zero runtime dependencies. Works in Node 18+ and the browser (uses fetch). For rendering the result, add @three-ws/avatar.

Quick start

The free lane needs no key:

import { forge } from '@three-ws/forge';

const model = await forge('a chrome robot with neon trim');

console.log(model.glbUrl);    // → https://cdn.three.ws/forge/…​.glb (durable)
console.log(model.viewerUrl); // → https://three.ws/forge?share=…​

A fuller run — high tier, geometry-first, then auto-rig:

import { forge, rig } from '@three-ws/forge';

const model = await forge('a stylized fox, full body, T-pose', {
  tier: 'high',        // draft | standard | high
  path: 'geometry',    // image | geometry | sketch
  providerKey: process.env.MESHY_KEY, // BYOK for the geometry path
});

const rigged = await rig(model.glbUrl); // animation-ready humanoid GLB
console.log(rigged.glbUrl);

From an image or a sketch:

// Photo → 3D
await forge({ images: ['https://example.com/sneaker.png'], prompt: 'a sneaker' });

// Drawing + a name → geometry (no textures)
await forge({ images: ['data:image/png;base64,…'], prompt: 'a sword', path: 'sketch' });

API

forge(promptOrInput, options?) → Promise<ForgeResult>

Generate a GLB from text, image(s), or a sketch. Accepts a bare prompt string, or an input object.

Input

| Field | Type | Notes | |---|---|---| | prompt | string | Text description. Required for text + sketch paths. | | images | string[] | One or more image URLs / data URIs. Switches to image→3D. | | aspectRatio | string | Reference-image aspect for the image path, e.g. "1:1". |

Options

| Option | Type | Default | Notes | |---|---|---|---| | path | 'image' \| 'geometry' \| 'sketch' | 'image' | How geometry is produced — see How it works. | | tier | 'draft' \| 'standard' \| 'high' | 'standard' | Polygon budget + texture richness. | | backend | string | auto | Force a generation backend (nvidia, huggingface, meshy, tripo). | | providerKey | string | — | BYOK key for the geometry path (Meshy/Tripo). | | payWith | 'x402' \| 'credits' | 'x402' | Billing lane for paid tiers (see Pricing). | | signal | AbortSignal | — | Cancel an in-flight generation. | | onProgress | (job) => void | — | Called on each poll tick with the latest job state. |

Returns ForgeResult

| Field | Type | Notes | |---|---|---| | glbUrl | string | Durable hosted GLB URL. | | viewerUrl | string | Shareable three.ws viewer link. | | jobId | string \| null | null when the backend returned synchronously. | | status | 'done' | Resolved jobs are always done; failures throw. | | path / tier / backend | string | What actually produced the mesh. | | etaSeconds | number | Backend ETA at submit time. |

forge() submits to POST /api/forge, then polls GET /api/forge?job=<id> until the job is done (the free NVIDIA lane often returns synchronously, with no polling). Failures reject with a typed ForgeError.

rig(glbUrl, options?) → Promise<ForgeResult>

Auto-rig an existing GLB into an animation-ready humanoid. Wraps POST /api/forge?action=rig { glb_url }. Returns the same ForgeResult shape with a rigged glbUrl.

catalog() → Promise<Catalog>

Fetch the live tier / backend / cost matrix (GET /api/forge?catalog) — the single source of truth for prices, ETAs, which backends are configured, and which paths each serves. Use it to render a picker before the user commits.

How it works

Two orthogonal axes describe every request — path (how geometry is produced) and tier (how much budget to spend):

prompt / image / sketch
        │
        ▼
   ┌──────────┐   image     ┌───────────────────────────────┐
   │  path =  ├────────────▶ FLUX/Imagen → TRELLIS·Hunyuan3D │  fast default, free lane
   │          ├─ geometry ─▶ Meshy / Tripo native text→mesh  │  BYOK, higher detail ceiling
   │          ├─ sketch ───▶ TripoSG-scribble                │  drawing + name → raw geometry
   └──────────┘             └───────────────┬───────────────┘
                                            ▼
                                   textured / untextured GLB
                                            │ (action=rig)
                                            ▼
                                   rigged humanoid GLB
  • image (default) — text is painted into a reference image, then reconstructed to a mesh. Fast, and the free lane lives here.
  • geometry — a native 3D model emits mesh geometry directly, so detail isn't capped by a single synthesized view. Bring your own Meshy/Tripo key.
  • sketch — a drawing plus a prompt naming it drives TripoSG-scribble to raw geometry (no textures).

Backends declare which paths they serve and whether they need a key. If a selected backend isn't configured, Forge returns a clean error state — it never fabricates a model.

Pricing

The free lane is genuinely free. Paid tiers are flat per-call prices, quoted in USDC (6-decimal atomics) and settled over x402 or from a prepaid credit balance:

| Tier | Polygons (target) | PBR | Price | Lane | |---|---|---|---|---| | draft | ~12k | — | free on NVIDIA NIM (text) | TRELLIS | | standard | ~30k | — | $0.15 (free on the NIM text lane) | TRELLIS / paid | | high | ~200k | yes | $0.50 | paid |

Set payWith: 'x402' (default) to pay per call with USDC, or payWith: 'credits' to draw from a signed-in prepaid balance. Pair with @three-ws/x402-fetch to automate the 402 settlement. Prices are authoritative in catalog() — read them at runtime rather than hardcoding.

Errors & edge cases

forge() and rig() reject with a typed ForgeError carrying a code:

| code | HTTP | Meaning | Recovery | |---|---|---|---| | needs_key | 501 | The geometry path needs a BYOK Meshy/Tripo key. | Pass providerKey. | | backend_unavailable | 503 | The selected backend isn't configured. | Omit backend to auto-route, or pick another. | | payment_required | 402 | Paid tier with no payment. | Provide an x402 payer or top up credits. | | insufficient_credits | 402 | payWith: 'credits' balance too low. | Top up at /credits. | | unauthorized | 401 | Credit lane needs a signed-in account. | Authenticate, or use payWith: 'x402'. | | rate_limited | 429 | Too many submissions. | Honour retryAfter on the error. | | generation_failed | — | The backend produced no usable mesh. | Retry, or change path/backend. |

Every state is designed: a missing key returns needs_key (not a crash), an unconfigured backend returns 503 (not a fake model). Mirror that in your UI.

Examples

Agent tool (free, zero-config) — the same capability is exposed as the forge_free MCP tool, so an agent can generate 3D with no wallet:

const { glbUrl } = await forge('a low-poly treasure chest', { tier: 'draft' });

Browser → render inline with the sibling viewer:

<script type="module">
  import { forge } from '@three-ws/forge';
  import '@three-ws/avatar/viewer';

  const { glbUrl } = await forge('a friendly robot');
  const el = document.createElement('three-ws-viewer');
  el.setAttribute('src', glbUrl);
  document.body.append(el);
</script>

Generate → rig → animate in one chain, ready for the walk companion:

const base = await forge('a cartoon astronaut, full body', { tier: 'standard' });
const rigged = await rig(base.glbUrl);
// drop rigged.glbUrl into @three-ws/walk or @three-ws/avatar

Related