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

@zvid/sdk

v0.2.0

Published

Official TypeScript/JavaScript SDK for the Zvid JSON-to-video/image rendering API

Readme

@zvid/sdk — official TypeScript SDK

Typed TypeScript/JavaScript client for the Zvid JSON-to-video/image rendering API. Fetch-based with zero runtime dependencies, ESM + CJS, strict types derived from the maintained API contract, automatic transient-failure retries, polling helpers, media uploads, and timing-safe webhook signature verification.

npm install @zvid/sdk

Requires Node 18+ (native fetch). The API client itself is runtime-agnostic; the webhook helpers use node:crypto.

Quickstart

import { ZvidClient, outputUrl } from "@zvid/sdk";

const zvid = new ZvidClient(); // reads ZVID_API_KEY; create one at https://app.zvid.io/api-keys

const job = await zvid.renders.createImage({
  payload: {
    type: "image",
    width: 1200,
    height: 630,
    visuals: [{ type: "TEXT", text: "Hello Zvid", position: "center-center" }],
  },
});
const done = await zvid.waitForRender(job.jobId, { timeoutMs: 120_000 });
console.log(outputUrl(done)); // https://cdn.zvid.io/...

Configuration

| Option | Env var | Default | | --- | --- | --- | | apiKey | ZVID_API_KEY | — (required) | | baseUrl | ZVID_BASE_URL | https://api.zvid.io | | fetch | — | global fetch | | maxRetries | — | 3 | | retryBaseDelayMs | — | 1000 | | retryMaxDelayMs | — | 30000 |

Network failures and HTTP 429, 502, 503, and 504 responses are retried with exponential backoff and jitter. Retry-After is honored up to retryMaxDelayMs. Set maxRetries: 0 when the caller must never repeat a request. onRetry can feed application logs or metrics without replacing the retry implementation.

Surface

| Namespace | Methods | | --- | --- | | zvid.account | profile | | zvid.apiKeys | list, create, update, stats, revoke / delete | | zvid.authoring | getSchema, listElements, getElementDocs, getExamples, creativePlan, repair, validate (plan-aware; no render credits) | | zvid.renders | create, createImage, createBulk, createImageBulk, listBulk, getBulk | | zvid.jobs | get, list, wait | | zvid.templates | list, get, create, update, duplicate, preview, archive / delete | | zvid.projects | list, get, create, update, delete | | zvid.uploads | list, create, delete | | zvid.webhooks | list, get, create, update, delete, test, deliveries | | zvid.credits | balance, transactions, usageStats |

Renders are asynchronous: every renders.create* call returns { jobId }. Poll zvid.jobs.get(jobId) yourself, or block with zvid.waitForRender(jobId, { timeoutMs, pollIntervalMs, signal }) — it resolves with the terminal JobStatus (use the outputUrl() / thumbnailUrl() helpers on it), rejects with RenderFailedError on failure and WaitTimeoutError on timeout, and supports AbortSignal.

Every render call takes exactly one of payload (inline project JSON, typed as RenderPayload) or template (stored tpl_… id), plus optional variables, overrides, and a one-off webhookUrl. The authoritative payload schema is published at docs.zvid.io (render-payload.schema.json).

zvid.authoring.validate() always resolves for schema validation: check its valid field. Invalid payloads return { valid: false, errors, warnings }; authentication, network, and other API failures still throw.

Uploads

Upload a browser File or a Blob created in Node.js. The returned CDN URL can be used directly as an image, video, GIF, or audio element source.

import { readFile } from "node:fs/promises";

const bytes = await readFile("./poster.png");
const poster = await zvid.uploads.create(
  new Blob([bytes], { type: "image/png" }),
  { fileName: "poster.png", width: 1200, height: 630 },
);
console.log(poster.url);

Errors

For AI generation, read zvid.authoring.getSchema() and the relevant element docs, start from a validated example, then repair and validate before calling zvid.renders.create*.

All API errors extend ZvidAPIError (with .status, .error, .details, .body):

| Class | When | | --- | --- | | AuthenticationError | 401 | | InsufficientCreditsError | 402 — has .creditsRequired / .creditsAvailable | | NotFoundError | 404 | | RateLimitError | 429 — has .retryAfter (seconds) | | RenderFailedError | thrown by waitForRender when the job fails (.job) | | WaitTimeoutError | thrown by waitForRender on timeout |

Webhooks

Deliveries to registered endpoints are signed: X-Zvid-Signature: sha256=hex(HMAC_SHA256(secret, "<X-Zvid-Timestamp>.<raw body>")).

import { verifyWebhookSignature } from "@zvid/sdk";

// Express example — use the RAW body (express.raw / rawBody), not re-serialized JSON
app.post("/hooks/zvid", express.raw({ type: "application/json" }), (req, res) => {
  if (!verifyWebhookSignature(req.body, req.headers, process.env.ZVID_WEBHOOK_SECRET!)) {
    return res.status(400).end();
  }
  const event = JSON.parse(req.body.toString());
  // event.event === "render.completed" | "render.failed", event.data.url, …
  res.status(200).end();
});

verifyWebhookSignature uses crypto.timingSafeEqual and rejects deliveries older than 5 minutes ({ toleranceSeconds: null } disables the freshness check). It accepts fetch Headers, Node request headers, or plain objects. Per-request webhookUrl deliveries are not signed — only account endpoints are.

Development

npm install
npm run typecheck && npm test && npm run build

Live smoke test against a running orchestrator (spends ~1 credit):

ZVID_API_KEY=zvid_… ZVID_BASE_URL=http://localhost:4000 node examples/e2e.mjs

Publishing (manual)

Not published yet. To release version 0.2.0:

npm run prepublishOnly   # typecheck + tests + build
npm publish              # publish the public `@zvid/sdk` package to npm