Skip to content

yoeven/next-image-processing-api

Repository files navigation

Next Image Processing API

Blazing fast image processing/transformations and CDN running on Vercel edge functions using Rust and WebAssembly.

Image processing powered by Photon

Features

  • ⚡ Blazing fast image processing
  • ☁️ Fully serverless, runs on Vercel Edge functions
  • 🏞️ Resize, crop, compress, tint, rotate, format and more
  • 🌏 Global distribution with Edge functions
  • 💾 Automated CDN cache with Edge functions
  • 🔁 Replacement for next/image processing on Vercel
  • 🔗 Local and remote image processing
  • 🧩 Fully managed API coming soon to JigsawStack

Usage

The image processing API can be hosted on your own Vercel project which would also work on Cloudflare Pages/Workers, as long there is support for Edge functions. This API is on the Next.js, hosted on Vercel.

API

Base path: /api/image

All image processing is done by sending a GET request to the API with the following query parameters

Zod object schema for the query parameters:

z.object({
  url: z.string(),
  format: z.enum(["webp", "jpeg", "png"]).optional(),
  jpeg_quality: z.string().transform((v) => parseInt(v)).pipe(z.number().min(1).max(100)).optional(),
  width: z
    .string().transform((v) => parseInt(v)).pipe(z.number().min(1)).optional(),
  height: z.string().transform((v) => parseInt(v)).pipe(z.number().min(1)).optional(),
  fit: z.enum(["contain", "cover", "fill"]).optional(),
  fit_cover_letterbox_color: z.string().optional(),
  fliph: z.string().transform((v) => v && v.toLowerCase() === "true").optional(),
  flipv: z
    .string().transform((v) => v && v.toLowerCase() === "true").optional(),
  padding: z.string().optional(),
  padding_color: z.string().optional(),
  rotate: z.string().transform((v) => parseInt(v)).optional(),
  crop: z.string().optional(),
  blur: z.enum(["gaussian", "box"]).optional(),
  blur_radius: z.string().transform((v) => parseInt(v)).optional(),
  sharpen: z.string().transform((v) => v && v.toLowerCase() === "true").optional(),
  noise_reduction: z.string().transform((v) => v && v.toLowerCase() === "true").optional(),
  brightness: z.string().transform((v) => parseInt(v)).optional(),
  hue: z.string().transform((v) => parseInt(v)).optional(),
  saturation: z.string().transform((v) => parseInt(v)).optional(),
  tint: z.string().optional(),
  grayscale: z.string().transform((v) => parseInt(v)).optional(),
});

Helpers

You can use the transformImage helper function in src/client to form the query parameters and URL.

Example usage with client image:

<img
    src={transformImage({
        url: "/testimage.jpg",
        width: 500,
        format: "webp",
        fit: "contain",
    })}
/>

Remote vs Local images:

  • For remote images, you can pass the full URL to the url param. https://example.com/image.jpg
  • For local images, you can pass the relative path to the url param. The API will fetch the image from the same domain. /image.jpg

Caching

Caching is handled by the Edge function which utilizes Vercel's CDN based on the cache control headers set in the API which is currently set to 30 days. You can learn more here about the requirements and configurations and adjust the caching accordingly.

return new NextResponse(outputBuffer, {
    status: 200,
    headers: {
        "cache-control": "public, s-maxage=2592000",
    },
});

Usage in your own project

  1. Install @cf-wasm/photon
  2. Copy the API layer from pages/api/image or use it as a reference to write your own layer.

Running Locally

1. Clone the repository
2. Install dependencies: `yarn`
3. Start the development server: `yarn dev`
4. Make requests to the API: http://localhost:3000/api/image?url=/image.jpg&width=500&format=webp

Credits

Releases

No releases published

Packages

No packages published

Languages