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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@cf-kit/images

v0.1.1

Published

Image optimization library for Cloudflare Workers with intelligent format negotiation (AVIF, WebP), smart R2 caching, and automatic variant selection

Readme

@cf-kit/images

A high-performance image processing library for Cloudflare Workers that provides intelligent format negotiation, smart caching, and automatic variant selection using R2 storage and the Images Binding.

Features

🎯 Smart Format Negotiation

Automatically serves the optimal image format based on client browser support:

  • AVIF for modern browsers (best compression)
  • WebP for browsers that support it
  • Falls back to original format for compatibility

Intelligent Caching

  • R2-based caching with automatic cache key generation
  • Immutable cache headers for optimal CDN performance
  • Background cache warming to minimize latency

🔧 Automatic Variant Selection

  • Picks the best image size from your predefined variants
  • Intelligent upscaling/downscaling logic
  • Quality optimization based on available variants

🛡️ Robust Error Handling

  • Comprehensive input validation
  • Graceful error responses with detailed messages
  • Type-safe error handling with custom error types

📝 Full TypeScript Support

  • Complete type definitions for all interfaces
  • Runtime type validation
  • IntelliSense support for better developer experience

Installation

npm install @cf-kit/images
# or
pnpm add @cf-kit/images
# or
yarn add @cf-kit/images

Quick Start

import { optimizeImage } from "@cf-kit/images";

export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
    const url = new URL(request.url);
    const w = parseInt(url.searchParams.get("w") || "800");
    const q = parseInt(url.searchParams.get("q") || "75");

    return optimizeImage(
      {
        ctx,
        R2: env.IMAGES_BUCKET,
        Images: env.IMAGES_API,
        originKey: "photos/landscape.jpg",
        headers: request.headers,
        variants: [
          { w: 400, q: 80 },
          { w: 800, q: 75 },
          { w: 1200, q: 70 },
          { w: 1600, q: 65 },
        ],
      },
      { w, q }
    );
  },
};

API Reference

optimizeImage(params, options)

Processes and optimizes an image with automatic format negotiation and caching.

Parameters

params: ImageProcessingParams

| Property | Type | Description | | ----------- | -------------------------------- | -------------------------------------------------------- | | ctx | ExecutionContext | Cloudflare execution context for background tasks | | R2 | R2Bucket | R2 bucket instance for image storage and caching | | Images | ImagesBinding | Cloudflare Images API binding for transformations | | originKey | string | Key/path of the original image in R2 storage | | headers | Headers | Request headers for format negotiation | | variants | Array<{w: number, q?: number}> | Available image variants with width and optional quality |

options: ImageTransformOptions

| Property | Type | Description | | -------- | --------------------- | ---------------------------------- | | w | number | Desired width (1-10000 pixels) | | q | number (optional) | Quality level (1-100, default: 75) |

Returns

Promise<Response> - Optimized image response or error response

Example Response Headers

Content-Type: image/avif
Cache-Control: public, max-age=31536000, immutable

Variant Selection Logic

The library uses intelligent logic to select the best variant:

  1. Preferred Strategy: Finds the smallest variant width that's ≥ the requested width
  2. Fallback Strategy: If no variants are large enough, uses the largest available variant
  3. Quality Matching: When multiple variants have the same width, picks the one with quality closest to the requested quality

Example Variant Selection

const variants = [
  { w: 400, q: 80 },
  { w: 800, q: 75 },
  { w: 1200, q: 70 },
];

// Request: w=600, q=75
// Selected: { w: 800, q: 75 } (smallest width ≥ 600)

// Request: w=1500, q=75
// Selected: { w: 1200, q: 70 } (largest available, closest quality)

Supported Image Formats

| Format | MIME Type | Browser Support | Compression | | -------- | ------------ | --------------- | --------------- | | AVIF | image/avif | Modern browsers | Excellent | | WebP | image/webp | Most browsers | Very good | | JPEG | image/jpeg | Universal | Good | | PNG | image/png | Universal | Good (lossless) | | GIF | image/gif | Universal | Basic |

Error Handling

All errors are returned as JSON responses with appropriate HTTP status codes:

Common Error Responses

// 400 Bad Request
{
  "error": "Width must be a positive integer between 1 and 10000",
  "statusCode": 400
}

// 404 Not Found
{
  "error": "Image not found",
  "statusCode": 404
}

// 400 Bad Request
{
  "error": "Unsupported image format: bmp",
  "statusCode": 400
}

Error Types

The library exports a custom error type for better error handling:

import { ProcessImageError } from "@cf-kit/images";

try {
  const response = await optimizeImage(params, options);
} catch (error) {
  if (error instanceof ProcessImageError) {
    console.error(`Error ${error.statusCode}: ${error.message}`);
  }
}

Type Definitions

export interface ImageProcessingParams {
  ctx: ExecutionContext;
  R2: R2Bucket;
  Images: ImagesBinding;
  originKey: string;
  headers: Headers;
  variants: {
    w: number;
    q?: number;
  }[];
}

export interface ImageTransformOptions {
  w: number;
  q?: number;
}

export interface CacheOptions {
  maxAge?: number;
  immutable?: boolean;
}

export interface ProcessImageError extends Error {
  statusCode: number;
  message: string;
}

export type Format = "avif" | "webp" | "jpeg" | "png" | "gif";

Advanced Usage

Custom Cache Configuration

// The library automatically handles caching, but you can customize
// cache behavior by configuring your R2 bucket settings

Format Override

// The library automatically negotiates format based on Accept headers
// No manual format specification needed - it's handled intelligently

Performance Tips

  1. Pre-generate Variants: Define variants that match your common use cases
  2. Quality Settings: Use appropriate quality levels (65-80 for most images)
  3. Cache Headers: The library sets optimal cache headers automatically
  4. Background Processing: Cache warming happens in the background for better performance

License

MIT