image-url
A chainable builder that turns Sanity image records into cropped, resized, hotspot-aware image URLs.
Repository Health
Technical Analysis
@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.
Used by 2 apps in this directory
Plasmic
CMS · Low Code Platforms · No Code Platforms
The open-source visual builder that lets teams design React apps and websites with drag-and-drop while integrating seamlessly with your codebase.
Sanity
CMS
Open-source headless CMS with a fully customizable React Studio, real-time collaborative editing, structured content modeling, and GROQ query language