Universal image placeholder generation for Node, Bun, Deno, browser, edge, Cloudflare, and WASM runtimes.
blurkit takes an image input and returns a ready-to-use placeholder dataURL plus the underlying hash, dimensions, and source metadata. The goal is to hide the decode, resize, hash, and render pipeline behind one practical API.
- Ready-to-use
dataURLoutput - BlurHash and ThumbHash support
- Explicit runtime entrypoints for Node, Deno, browser, edge, Cloudflare, and WASM runtimes
- Batch encoding with
encodeMany()andencodeManySettled() - CLI support for single images and folder manifests
- Cache interface with Node memory/filesystem helpers and Cloudflare Worker cache helper
- Manifest helpers for build-time and CMS pipelines
pnpm add blurkitFor Node and Bun usage, install sharp alongside the package:
pnpm add sharpFor Deno, install blurkit-wasm-codecs alongside the package since the Deno runtime uses wasm codecs for decode:
pnpm add blurkit-wasm-codecsIf you use blurkit/wasm directly, blurkit/edge fallback in non-native runtimes, or CLI --backend wasm, install wasm codecs companion package:
pnpm add blurkit-wasm-codecsimport { encode } from 'blurkit/node'
const result = await encode('./public/hero.jpg', {
size: 32,
})
console.log(result.dataURL)
console.log(result.hash)
console.log(result.meta.originalWidth, result.meta.originalHeight)Copy these minimal integrations as starting points:
- Next.js:
apps/example-nextjs - Astro:
apps/example-astro
Prefer explicit runtime imports in application code:
import { encode } from 'blurkit/node'
import { encode as encodeBrowser } from 'blurkit/browser'
import { encode as encodeDeno } from 'blurkit/deno'
import { encode as encodeEdge } from 'blurkit/edge'
import { encode as encodeCloudflare } from 'blurkit/cloudflare'
import { encode as encodeWasm } from 'blurkit/wasm'The root import is available as a convenience wrapper:
import { encode } from 'blurkit'Use the root import when convenience matters more than strict runtime control. For libraries and production apps, prefer the explicit runtime entrypoints.
blurkit/node: Node/Bun/server pipelines, local path support, sharp-backed.blurkit/deno: Deno runtime with local path support, wasm-backed decode, canvas render.blurkit/browser: browser/client uploads (File/Blob) with CORS-compatible remote URL support.blurkit/edge: generic worker runtimes; native decode first, wasm fallback second.blurkit/cloudflare: Cloudflare Workers withcf.image; remote URLs only.blurkit/wasm: runtimes without native decode APIs; PNG/JPEG/WebP decode.
Encode a single local image:
npx blurkit encode ./public/hero.jpg --prettyEncode with wasm backend:
npx blurkit encode ./public/hero.jpg --backend wasm --pretty--backend wasm requires blurkit-wasm-codecs.
Encode a remote image:
npx blurkit encode https://example.com/image.jpg --algorithm thumbhash --format jpegGenerate a manifest for a folder:
npx blurkit encode ./public \
--glob "**/*.{jpg,jpeg,png,webp}" \
--out blur-manifest.json \
--prettySingle-image input prints a BlurResult or writes that JSON directly with --out. Directory input produces a BlurManifest.
{
"version": 1,
"algorithm": "blurhash",
"generatedAt": "2026-05-12T00:00:00.000Z",
"images": {
"/images/hero.jpg": {
"dataURL": "data:image/png;base64,...",
"hash": "L9TSUA~qfQ~q~qoffQoffQfQfQfQ",
"algorithm": "blurhash",
"width": 32,
"height": 18,
"meta": {
"originalWidth": 1920,
"originalHeight": 1080,
"format": "jpeg",
"hasAlpha": false
}
}
}
}import { encode } from 'blurkit/node'
const result = await encode('./public/hero.jpg', {
algorithm: 'blurhash',
size: 32,
outputFormat: 'png',
})import { encodeMany } from 'blurkit/node'
const results = await encodeMany([
'./public/hero.jpg',
'./public/poster.jpg',
])encodeMany() is intentionally fail-fast and mirrors Promise.all().
import { encodeManySettled } from 'blurkit/node'
const settled = await encodeManySettled([
'./public/hero.jpg',
'./public/missing.jpg',
])encodeManySettled() returns ordered fulfilled/rejected results for partial success workflows.
import { createMemoryCache, encode } from 'blurkit/node'
const cache = createMemoryCache({ max: 500 })
const result = await encode('./public/hero.jpg', { cache })import { createManifest, writeManifest } from 'blurkit'
const manifest = createManifest({
'/images/hero.jpg': result,
})
await writeManifest('./blur-manifest.json', manifest, { pretty: true })- Node and Bun use the
blurkit/nodeentrypoint and rely onsharpfor image decoding and rendering. - Deno uses the
blurkit/denoentrypoint with wasm codecs for decode and nativeOffscreenCanvasfor rendering. Requiresblurkit-wasm-codecs. - The browser runtime supports
File,Blob,ArrayBuffer, and remote URLs that permit CORS. - The edge runtime uses native
ImageDecoder+OffscreenCanvaswhen available, then falls back to the wasm runtime. - Edge fallback,
blurkit/wasm, andblurkit/denorequireblurkit-wasm-codecs. - The Cloudflare runtime is optimized for Worker image transforms.
- The wasm runtime supports PNG/JPEG/WebP decode in runtimes without native decoding APIs.
- The root import auto-selects a runtime, but explicit runtime imports are safer for bundlers and framework apps.
These are intentionally not documented as current support:
- Framework-specific adapters such as Next.js convenience helpers
- Additional manifest output formats and tighter build-tool integrations
See PUBLISHING.md for details on library releases, website deployments, and library size reports.