@spronta/images — URL builder, signing, blurhash decode, srcset generation.

Core SDK (@spronta/images)

npm · GitHub

Zero-dependency TypeScript library for building Spronta CDN URLs, generating responsive srcsets, signing URLs, and decoding blurhash placeholders.

Works in any JavaScript runtime: browser, Node.js, Deno, Bun, Cloudflare Workers.

Install

npm install @spronta/images

Quick start

import { Spronta } from "@spronta/images";

const spronta = new Spronta({
  baseUrl: "https://cdn.spronta.com",
  project: "my-project",
  defaults: { format: "auto", quality: "medium" },
});

// Simple URL
spronta.url("photo.jpg", { width: 800 });
// → https://cdn.spronta.com/my-project/photo.jpg?w=800&f=auto&q=medium

// Responsive srcset
const props = spronta.srcset("hero.jpg", { widths: [640, 1280, 1920] });
// → { src: "...?w=1920", srcset: "...?w=640 640w, ...?w=1280 1280w, ...", sizes: "100vw" }

Client class

new Spronta(config)

ConfigTypeRequiredDescription
baseUrlstringYesCDN base URL
projectstringYesProject slug
signingSecretstringNoFor signed URLs
defaultsTransformOptionsNoDefault transforms for all URLs

spronta.url(path, options?)

Build a CDN URL with query parameters.

spronta.url("photo.jpg", { width: 800, gravity: "face", format: "webp" });

spronta.pathUrl(path, options?)

Build a Cloudinary-style path-based URL.

spronta.pathUrl("photo.jpg", { width: 800, format: "webp" });
// → https://cdn.spronta.com/my-project/w_800,f_webp/photo.jpg

spronta.srcset(path, options?)

Generate responsive src, srcset, and sizes attributes.

const props = spronta.srcset("hero.jpg", {
  widths: [640, 1280, 1920],
  sizes: "(max-width: 768px) 100vw, 1280px",
  format: "webp",
  quality: "medium",
});

// Use in HTML:
// <img src={props.src} srcset={props.srcset} sizes={props.sizes} />

spronta.signedUrl(path, options?, expiresIn?)

Generate an HMAC-SHA256 signed URL. Async (uses Web Crypto).

const url = await spronta.signedUrl("photo.jpg", { width: 800 }, 3600);
// Expires in 1 hour

spronta.withDefaults(defaults)

Create a new client with merged defaults. Useful for preset-like patterns:

const thumbnails = spronta.withDefaults({ width: 200, height: 200, fit: "cover", gravity: "face" });
thumbnails.url("photo.jpg"); // → ...?w=200&h=200&fit=cover&g=face

Blurhash utilities

decodeBlurhash(hash, width, height)

Decode a blurhash string to RGBA pixel data.

import { decodeBlurhash } from "@spronta/images";

const pixels = decodeBlurhash("LEHV6nWB2yk8pyo0adR*.7kCMdnj", 32, 32);
// → Uint8ClampedArray(4096) — 32x32 RGBA

blurhashToColor(hash)

Extract the average (DC) color as a hex string.

import { blurhashToColor } from "@spronta/images";

blurhashToColor("LEHV6nWB2yk8pyo0adR*.7kCMdnj");
// → "#8a7b6a"

blurhashToCssUrl(hash, width?, height?)

Decode to a canvas data URL (browser) or solid color fallback (SSR).

import { blurhashToCssUrl } from "@spronta/images";

const dataUrl = blurhashToCssUrl("LEHV6nWB2yk8pyo0adR*.7kCMdnj");
// → "data:image/png;base64,..." (browser)
// → "#8a7b6a" (SSR)

TransformOptions

All transform parameters as a TypeScript type:

type TransformOptions = {
  width?: number;
  height?: number;
  fit?: "cover" | "contain" | "fill" | "scale-down" | "crop" | "pad";
  format?: "webp" | "avif" | "jpeg" | "png" | "jxl" | "auto";
  quality?: number | "high" | "medium" | "low";
  dpr?: number;
  blur?: number;
  sharpen?: number;
  gravity?: "auto" | "face" | "center" | "top" | "bottom" | ...;
  radius?: number | "max";
  grayscale?: boolean;
  brightness?: number;
  contrast?: number;
  saturation?: number;
  sepia?: boolean;
  bg?: string;
  rotate?: 90 | 180 | 270;
  flip?: "h" | "v";
  preset?: string;
};