Image CDN Setup: imgix and Cloudinary
Image CDN automatically optimizes images: converts to WebP/AVIF, resizes for device, compresses without quality loss — all via URL parameters without modifying the original.
imgix: Setup and Usage
# imgix works on top of your S3/storage
# Configure Source in dashboard.imgix.com:
# Type: Amazon S3
# S3 Bucket: my-bucket
# S3 Key ID / Secret Key
# Base URL: https://mysite.imgix.net
// TypeScript: imgix URL builder
import ImgixClient from '@imgix/js-core';
const client = new ImgixClient({
domain: 'mysite.imgix.net',
secureURLToken: process.env.IMGIX_TOKEN, // for URL signing
});
// Basic transformation
const url = client.buildURL('/products/shoe.jpg', {
w: 800, // width
h: 600, // height
fit: 'crop', // crop | fill | scale | clip | max | min
crop: 'faces,entropy', // smart crop
auto: 'format,compress', // auto WebP/AVIF + compression
q: 80, // quality
dpr: 2, // device pixel ratio
});
// → https://mysite.imgix.net/products/shoe.jpg?w=800&h=600&fit=crop&auto=format%2Ccompress&q=80&dpr=2&s={signature}
Next.js Integration:
// next.config.ts
const nextConfig = {
images: {
loader: 'custom',
loaderFile: './lib/imgix-loader.ts',
domains: ['mysite.imgix.net'],
},
};
// lib/imgix-loader.ts
import ImgixClient from '@imgix/js-core';
const client = new ImgixClient({ domain: 'mysite.imgix.net' });
export default function imgixLoader({
src,
width,
quality,
}: {
src: string;
width: number;
quality?: number;
}) {
return client.buildURL(src, {
w: width,
auto: 'format,compress',
q: quality ?? 75,
fit: 'max',
});
}
// Usage — standard next/image with automatic imgix
<Image
src="/products/shoe.jpg"
width={800}
height={600}
alt="Running shoe"
sizes="(max-width: 768px) 100vw, 50vw"
/>
Cloudinary: Setup
npm install next-cloudinary
// next.config.ts
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'res.cloudinary.com',
pathname: `/${process.env.CLOUDINARY_CLOUD_NAME}/**`,
},
],
},
};
// next-cloudinary components
import { CldImage, CldUploadWidget } from 'next-cloudinary';
// Optimized image
<CldImage
src="products/shoe" // public_id in Cloudinary
width={800}
height={600}
alt="Running shoe"
crop="fill"
gravity="auto" // smart cropping
format="auto" // auto WebP/AVIF
quality="auto"
sizes="(max-width: 768px) 100vw, 50vw"
/>
// Transformations
<CldImage
src="hero/banner"
width={1200}
height={400}
alt="Hero"
overlays={[{
text: {
color: 'white',
fontFamily: 'Arial',
fontSize: 40,
fontWeight: 'bold',
text: 'Sale 50% Off',
},
position: { gravity: 'south', y: 40 },
}]}
/>
// Upload Widget
<CldUploadWidget
uploadPreset="unsigned_preset"
onUpload={({ info }) => {
console.log('Uploaded:', info.public_id);
setImageId(info.public_id);
}}
>
{({ open }) => <button onClick={() => open()}>Upload photo</button>}
</CldUploadWidget>
imgix vs Cloudinary Comparison
| Parameter | imgix | Cloudinary |
|---|---|---|
| Source | Your storage (S3) | Own storage |
| File uploads | Only via S3 | SDK, widget, API |
| Transformations | URL parameters | URL parameters + SDK |
| ML features | Smart crop | Face detection, background removal, AI |
| Price | By traffic | By storage + transformations |
| Best for | Control over storage | Media management + transformations |
Cloudflare Images: Budget Alternative
# Upload
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1" \
-H "Authorization: Bearer {token}" \
-F [email protected] \
-F metadata='{"productId":"123"}'
# Delivery URL
https://imagedelivery.net/{account_hash}/{image_id}/public
https://imagedelivery.net/{account_hash}/{image_id}/thumbnail # variant
https://imagedelivery.net/{account_hash}/{image_id}/w=800,h=600,fit=scale-down
Cost: $5/month for 100,000 images (significantly cheaper than Cloudinary).
Responsive Images: srcset
<!-- Auto-generated srcset via imgix -->
<img
src="https://mysite.imgix.net/hero.jpg?w=800&auto=format"
srcset="
https://mysite.imgix.net/hero.jpg?w=400&auto=format 400w,
https://mysite.imgix.net/hero.jpg?w=800&auto=format 800w,
https://mysite.imgix.net/hero.jpg?w=1200&auto=format 1200w,
https://mysite.imgix.net/hero.jpg?w=1600&auto=format 1600w
"
sizes="(max-width: 768px) 100vw, 1200px"
alt="Hero image"
loading="lazy"
/>
Setup imgix or Cloudinary with Next.js integration — 1–2 working days. Including loader config, responsive images and upload widget.







