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

@canetoad/usdc-converter

v0.1.5

Published

Browser USDA/USDZ to binary USDC conversion for Canetoad AR exports.

Readme

@canetoad/usdc-converter

Browser-first USDA/USDZ to binary USDC conversion for Canetoad AR exports.

The package wraps the native Rust openusd crate in WebAssembly. It avoids the heavy OpenUSD C++/Emscripten path while still using a real USDC crate writer.

Why this path

  • three/examples/jsm/exporters/USDZExporter writes a USDZ package whose root layer is ASCII USDA.
  • OpenUSD C++ can write USDC, but a browser build means shipping a large custom wasm bundle and dealing with Emscripten integration.
  • TinyUSDZ has useful WASM work, but its USDC writer is still documented as experimental.
  • openusd 0.5.0 is pure Rust and currently advertises read/write support for .usda, .usdc, and .usdz, which makes a compact wasm wrapper feasible.

Install

bun add @canetoad/usdc-converter

The base converter entrypoint has no runtime dependency on Three.js. If you use the @canetoad/usdc-converter/three helper, install Three.js in the consuming app as well:

bun add three

Usage

import { exportThreeSceneToUsdzBlob } from "@canetoad/usdc-converter/three";

const blob = await exportThreeSceneToUsdzBlob(threeScene);
const url = URL.createObjectURL(blob);

On iPhone/iPad, use the blob URL as an AR Quick Look link:

<a rel="ar" href="blob:...">Open in AR</a>

For lower-level control, convert the output of Three's USDZExporter directly:

import { convertUsdzToBinaryUsdz } from "@canetoad/usdc-converter";

const asciiUsdz = await exporter.parseAsync(threeScene);
const binaryUsdz = await convertUsdzToBinaryUsdz(asciiUsdz);

convertUsdzToBinaryUsdz() preserves the first/root USD layer as text and converts non-root ASCII USD layers from .usda or ASCII .usd to .usdc. It rewrites root-layer asset references that point at converted layers and copies non-USD assets unchanged. Keeping the root/material layer as USDA avoids a RealityKit material-resolution failure observed with Rust-written binary root layers, while still shrinking the heavy geometry layers.

Packages that contain existing binary non-root USD layers plus ASCII non-root USD layers that need conversion are rejected for now, because references inside existing binary layers cannot be rewritten safely without a broader authoring pass.

If your bundler does not serve package wasm assets from import.meta.url, pass the wasm bytes or URL explicitly:

await initToadUsdcConverter(wasmBytes);

API

  • initToadUsdcConverter(input?): initializes the wasm module. By default it loads wasm/toad_usdc_converter_wasm_bg.wasm relative to the package module. Pass wasm bytes or a wasm URL when your bundler cannot serve that package asset from import.meta.url.
  • convertUsdaToUsdc(source): converts a USDA string, Blob, or Response to a raw .usdc Uint8Array. Accepts { wasm } as an optional second argument.
  • convertUsdzToBinaryUsdz(source): converts non-root ASCII USD layers in a USDZ archive to binary USDC and returns a compact USDZ Uint8Array. Accepts ArrayBuffer, ArrayBufferView, Blob, Response, or Uint8Array, plus { wasm } as an optional second argument.
  • inspectUsdz(source): returns root-layer metadata for quick verification. Accepts the same byte inputs and optional { wasm } argument as convertUsdzToBinaryUsdz.
  • isUsdc(source): checks for the PXR-USDC magic bytes. Accepts the same byte inputs and optional { wasm } argument as convertUsdzToBinaryUsdz.

The @canetoad/usdc-converter/three entrypoint adds:

  • exportThreeSceneToBinaryUsdz(scene, options?): runs Three's USDZExporter and returns compact USDZ bytes with a USDA root and binary USDC geometry layers. Options are Three USDZExporterOptions plus optional wasm, exporter, and textureUtils.
  • exportThreeSceneToUsdzBlob(scene, options?): same conversion, returned as a model/vnd.usdz+zip Blob for browser links/downloads.

Build

bun install
bun run build
bun run typecheck
bun run test
npm pack --dry-run

The build requires Rust with the wasm32-unknown-unknown target:

rustup target add wasm32-unknown-unknown

bun run typecheck builds the generated WASM TypeScript bindings first. After wasm/ already exists locally, bun run typecheck:ts runs the faster TypeScript-only check.

Validation

The Rust openusd crate is vendored because crates.io 0.5.0 writes SDF child-list token vectors in a way Apple USD tools ignore. That produced USDC layers with valid metadata but no visible prim hierarchy. The vendored patch uses TokenVector for child-list fields such as primChildren and propertyChildren, while leaving authored token[] attributes such as xformOpOrder as normal token arrays.

On macOS, bun run test uses /usr/bin/usdchecker --arkit and /usr/bin/usdcat to verify that generated USDZ files are ARKit-valid and that prims survive the conversion.

The converter also normalizes a Three USDZExporter material quirk before writing USDC: texture shader inputs that Three authors as token are rewritten to the UsdShade types RealityKit follows (string inputs:varname and float2 inputs:in.connect). Apple's usdchecker --arkit can still report success when those fields are left as token, but Quick Look renders the material without its texture after binary conversion.

Runtime And Publishing

@canetoad/usdc-converter is ESM-only and targets modern browsers and bundlers that can load WebAssembly package assets. Releases are published publicly to npm with provenance enabled through GitHub trusted publishing.

License

PolyForm Noncommercial License 1.0.0. See LICENSE for license terms and required notices. The vendored openusd crate keeps its own license under rust/vendor/openusd/LICENSE.