image-url

A chainable builder that turns Sanity image records into cropped, resized, hotspot-aware image URLs.

Library
npm
v2.1.1
93stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
49/100Fair
Development Activity48
Maintenance20
Community48
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture78
Code Quality85
Innovation72
Learning Curve55

@sanity/image-url is the official helper for generating image URLs from content stored in Sanity’s structured content platform. Rather than hand-building query strings against Sanity’s image CDN, developers chain a fluent builder — width(), height(), blur(), crop(), format() and dozens of other methods — that ends in url() or toString() to produce a fully-formed, optimized image URL.

The builder respects any crop and hotspot metadata a content editor set in Sanity Studio by default, so front-end code gets correctly framed images without re-implementing cropping logic. It also auto-configures itself from an existing @sanity/client instance, and ships a separate /signed entry point for generating cryptographically signed, time-limited CDN URLs for Media Library assets on Enterprise accounts.

What You Get

  • A fluent, immutable builder API (image().width().height().url()) for constructing Sanity CDN image URLs
  • Automatic respect for content-editor-specified crops and hotspots, with explicit overrides when needed
  • Auto-configuration from a passed-in @sanity/client instance (project ID, dataset, API host) via withClient()
  • A dedicated /signed submodule for generating expiring, cryptographically signed URLs for Media Library assets
  • Support for custom CDN base domains on accounts with white-labeled asset delivery
  • Full TypeScript types for every builder option, source shape, and transformation parameter

Common Use Cases

  • Rendering responsive, correctly cropped images in a Sanity-backed blog or marketing site
  • Serving modern image formats (WebP/AVIF) automatically via auto(‘format’) to cut page weight
  • Generating device-pixel-ratio-aware thumbnails for retina displays with dpr()
  • Producing signed, expiring URLs to prevent hotlinking of private Media Library assets

Under The Hood

Architecture The package centers on an immutable builder pattern: ImageUrlBuilderImpl in src/builder.ts stores an options object, and every chainable method (width, height, crop, blur, and roughly twenty others) calls withOptions() to merge in a new key and return a fresh instance rather than mutating in place, so intermediate builders can be safely reused or branched. createImageUrlBuilder() normalizes three possible inputs — a raw options object, a legacy Sanity client (clientConfig), or a modern client (config()) — through getOptions()/clientConfigToOptions(), which also understands resource-scoped clients (media-library, canvas, dataset). Final serialization is delegated to urlForImage() in src/urlForImage.ts, which maps builder option keys to their URL query-parameter equivalents via SPEC_NAME_TO_URL_NAME_MAPPINGS, while parseSource.ts and parseAssetId.ts normalize the various shapes an “image” reference can take (full image document, asset document, or bare asset ID string) into a single internal representation. The src/signed/ submodule composes over the same builder rather than duplicating it, adding signingKey()/expiry()/signedUrl() as an additive layer — a clean example of extending a small core rather than branching it.

Tech Stack The project is 100% TypeScript, built with @sanity/pkg-utils (pkg build --strict) into dual ESM output under lib/, and versioned/released through Changesets with an automated GitHub Actions release PR flow. Its only runtime dependency is @sanity/signed-urls, used solely by the signed submodule so consumers who never import it avoid pulling in signing logic. Tests run on Vitest with coverage via @vitest/coverage-v8, and formatting/linting are enforced with Prettier and legacy TSLint. CI (.github/workflows) runs the test suite across three Node.js version tracks (current, latest LTS, previous LTS) on every pull request.

Code Quality The test/ directory has dedicated suites for the builder, custom-domain behavior, asset/source parsing, hotspot image URLs, client-derived config, and the signed-URL path, including snapshot fixtures (test/snapshots) and a declaration-type check (check:declaration) that compiles against the emitted .d.ts files. tsconfig.json extends @sanity/pkg-utils’ “strictest” preset, and invalid enum-like inputs (fit, crop, auto, frame) throw explicit, descriptive errors rather than failing silently or producing a malformed URL. There is no CONTRIBUTING.md or docs/ directory, but public methods carry short inline comments explaining intent, and a dedicated MIGRATE-v1-to-v2.md documents breaking changes for upgraders.

API Design The chainable, order-independent builder mirrors patterns developers already know from query builders and date libraries, and calling .url() last is the only ordering constraint. Passing a configured Sanity client directly into createImageUrlBuilder() removes an entire class of manual configuration, and withClient() lets a single builder chain be retargeted at a different project/dataset mid-chain while preserving already-applied transforms — a small but genuinely useful ergonomic touch for multi-tenant or multi-dataset apps. The deprecated default export is kept working via a documented wrapper (compat.ts) rather than being silently dropped, and the separate /signed entry point keeps the common case free of signing-related bundle weight.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search