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

@snowcone-app/sdk

v0.19.0

Published

Snowcone SDK for product mockups and print-on-demand

Readme

@snowcone-app/sdk

Building with an AI agent? Read the complete agent-facing docs in one fetch — https://developers.snowcone.app/llms-full.txt — before integrating. It's the source of truth; grep it before assuming a field or behavior is undocumented.

JavaScript/TypeScript SDK for product mockups and print-on-demand

A small, isomorphic SDK for fetching product data and building real-time merchandise mockup URLs. Use it to visualize artwork on t-shirts, posters, mugs, and more — in the browser or on the server.

📖 Full documentation: developers.snowcone.app/sdk

Installation

npm install @snowcone-app/sdk
# or
yarn add @snowcone-app/sdk
# or
pnpm add @snowcone-app/sdk

Quick Start

import { getProduct, listProducts, getMockupUrl } from '@snowcone-app/sdk';

// 1. Find a product (public catalog read — no key needed)
const products = await listProducts({ limit: 10 });
const product = await getProduct('BEEB77'); // by id or slug

// 2. Build a mockup URL. A mockup is a PUBLIC image URL — getMockupUrl is a
//    pure, synchronous builder (no await, no fetch, no secret). The result
//    drops straight into an <img>. Code-first: productCode, then options.
const url = getMockupUrl('hoodie-black', {
  shop: shop.id,                       // your Shop ID (publishable, = shop.id)
  asset: 'https://example.com/art.png' // your artwork
});
// <img src={url} />

The shop ID is your publishable token — public and safe to expose (like Cloudinary's cloud name). It defaults to your shop.id. See Public or signed below if you want to lock things down.

Core Functions

Product Data

// Get a single product
const product = await getProduct(productId: string, options?: {
  endpoint?: string;
  mode?: 'mock' | 'live' | 'meilisearch';
});

// List products
const products = await listProducts(options?: {
  limit?: number;
  offset?: number;
  endpoint?: string;
  mode?: 'mock' | 'live' | 'meilisearch';
});

Product Object Structure:

{
  id: string;              // Product ID (e.g., "BEEB77")
  name: string;            // Product name
  description?: string;    // Product description
  basePrice: number;       // Base price in cents
  variants: Variant[];     // Color/size variants
  placements: Placement[]; // Print areas (Front, Back, etc.)
  mockup: {
    blankUrl: string;      // Blank product image URL
  };
}

Mockup URLs

A mockup is a public image URL on img.snowcone.app:

https://img.snowcone.app/{productCode}?asset={assetUrl}&shop={shopId}

You can hand-write it, or use getMockupUrl — a pure, synchronous, isomorphic builder (browser + server, no await). It never hand-rolls the query string; it delegates to @snowcone-app/mockup-url's buildPublicMockupUrl (the single source of truth shared byte-for-byte with the edge resolver).

import { getMockupUrl } from '@snowcone-app/sdk';

// Code-first form: productCode, then options.
const url = getMockupUrl(productCode: string, opts: {
  shop: string;           // Required: your Shop ID (publishable, = shop.id)
  asset?: string;         // Single default-placement image (get-started shorthand)
  design?: Design;        // Multi-placement: { [placementKey]: Fill } — takes precedence over `asset`
  options?: Record<string, string>; // Variant picks: { size: "m" } → opt.size=m
  secret?: string;        // Optional: per-shop secret → appends a signed &signature (server only)
  base?: string;          // Optional: override the host (default img.snowcone.app)
  width?: number;         // Optional: display width
  view?: string;          // Optional: camera view / mockup scene (alias: `mockup`)
  variant?: string;       // Optional: specific resolved variant (gvid)
  placement?: string;     // Optional: specific print area (single-asset only)
  aspect?: '16:9' | '2:3';// Optional: canvas aspect ratio
}): string;

Fill (re-exported from the SDK) is what fills one placement:

type Fill =
  | string                                       // image URL (shorthand for { src })
  | { src: string; align?: ImageAlignment; tile?: 0.25 | 0.5 | 1 | 2 | 4 }
  | { color: string };                           // a color placement (e.g. a cap's Crown)
type Design = Record<string, Fill>;              // placement key → fill

Multi-placement + variant options

// A front + back tee, size M.
const url = getMockupUrl('KMYKUK', {
  shop: shop.id,
  options: { size: 'm' },
  design: {
    front: 'https://cdn.example.com/front.png',
    back: { src: 'https://cdn.example.com/back.png', tile: 2, align: 'top' },
  },
});
// → …/KMYKUK?shop=…&asset.back=…&tile.back=2&align.back=top&asset.front=…&opt.size=m

// A cap with a printed front + chosen Crown/Strap colors (color placements).
const cap = getMockupUrl('RQNU68', {
  shop: shop.id,
  design: { front: 'https://cdn.example.com/logo.png', crown: { color: '#001f3f' } },
});
// → …/RQNU68?shop=…&color.crown=%23001f3f&asset.front=…

A legacy positional form getMockupUrl(assetUrl, productCode, opts) is also accepted (it builds the same URL as getMockupUrl(productCode, { asset, … })). Prefer the code-first form above for new code.

Public or signed

The default is open and frictionless. There's one decision to make up front:

  • Public — the Shop ID alone, safe to expose. Lock it to your asset origins so a stolen ID can only re-render your own catalog.
  • Signed — your server appends an &signature (HMAC of a per-shop secret), so only you can mint valid URLs. The secret stays server-side.

To sign, pass secret (server-side only) and getMockupUrl appends the verified &signature:

// On your server/BFF — the secret never ships to the browser.
const url = getMockupUrl('hoodie-black', {
  shop: shop.id,
  asset: assetUrl,
  secret: process.env.SNOWCONE_SHOP_SECRET,
});

See Public or signed for the full picture.

Realtime: render a saved canvas, no pixel upload

getMockupUrl composites one artwork onto a product. For a full multi-layer design — the kind the Snowcone canvas editor produces — use a RenderSession: the browser sends a ~1 KB description of the canvas (or just a saved design's id) over a WebSocket, and the server renders the mockup and fetches the referenced assets itself. No per-placement PNG is ever uploaded, so it's fast on thin/mobile clients. This is exactly how the Snowcone PDP renders mockups.

Authorize the session with a short-lived grant. Mint it server-side with a secret API key (sk_…, scope mockups:realtime) so the key never reaches the browser. Create the key — and find your publishable shop.id — on the API keys page:

// YOUR backend route, e.g. POST /api/realtime/grant
import { mintRealtimeGrant } from '@snowcone-app/sdk';

export async function POST(req: Request) {
  const { shop } = await req.json();
  const grant = await mintRealtimeGrant({
    apiKey: process.env.SNOWCONE_API_KEY!, // secret — server only
    shop,                                  // = shop.id (publishable)
  });
  return Response.json(grant); // { token, expiresAt }
}

In the browser, point a RenderSession at that proxy and render. Render a saved design by id (no canvas JSON needed) or a live serializeStateForServer(...) state:

import { RenderSession } from '@snowcone-app/sdk';

const session = new RenderSession({
  shop: 'YOUR_SHOP_ID',            // publishable, like Stripe pk_
  grantUrl: '/api/realtime/grant', // your proxy above
  // mockupIds are catalog SCENE CODES (product.mockups[].id) — not placement
  // names. variantId is required for products with a color/size option.
  product: { productId: 'BEEB77', mockupIds: ['FV1qjO'], variantId: 'Pv1sLC' },
});

session.onMockups((results) => { img.src = results[0].imageUrl; });

// (a) render a SAVED canvas by id — ideal for fulfillment / agents
await session.renderSavedState('Front', 'design-state-id');

// (b) or render a live canvas state from @snowcone-app/canvas
// import { serializeStateForServer } from '@snowcone-app/canvas';
// await session.renderState('Front', serializeStateForServer(canvasState));

React apps can use the lower-level useRealtimeMockup({ getToken }) hook from @snowcone-app/sdk/react instead. Full walkthrough: Realtime server-side render.

TypeScript Support

Full TypeScript definitions are included. Import types:

import type {
  CatalogProduct,
  Variant,
  Placement,
  ImageAlignment
} from '@snowcone-app/sdk';

API Reference

See full API documentation at: https://developers.snowcone.app/sdk

React Components

For pre-built React components, install @snowcone-app/ui:

npm install @snowcone-app/ui

See: @snowcone-app/ui on npm

Examples

Support

License

MIT © Snowcone


Built for developers. Optimized for LLMs. 🤖

This SDK is designed to work seamlessly with AI coding assistants like Claude, GitHub Copilot, and Cursor. Clear types, explicit examples, and predictable patterns make it easy for LLMs to generate correct code.