cloudinary
Manages images and videos with Cloudinary including upload, transformation, and CDN delivery. Use when building media-rich applications requiring resize, crop, format conversion, and optimization.
SKILL.md
Full skill instructions
Cloudinary
Image and video management platform with upload, transformation, optimization, and global CDN delivery.
Quick Start
npm install cloudinary
Configuration
import { v2 as cloudinary } from 'cloudinary';
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
secure: true
});
Upload
Basic Upload
// From local file
const result = await cloudinary.uploader.upload('./image.jpg', {
public_id: 'my-image', // Optional custom ID
folder: 'products', // Optional folder
});
console.log(result.secure_url);
// https://res.cloudinary.com/cloud/image/upload/v1234/products/my-image.jpg
// From URL
const result = await cloudinary.uploader.upload(
'https://example.com/image.jpg',
{ folder: 'external' }
);
// From base64
const result = await cloudinary.uploader.upload(
'data:image/png;base64,iVBORw0KGgo...',
{ folder: 'uploads' }
);
Upload Options
const result = await cloudinary.uploader.upload('./image.jpg', {
public_id: 'my-image',
folder: 'products',
// Transformations on upload
transformation: [
{ width: 1000, height: 1000, crop: 'limit' },
{ quality: 'auto', fetch_format: 'auto' }
],
// Eager transformations (pre-generate)
eager: [
{ width: 200, height: 200, crop: 'thumb', gravity: 'face' },
{ width: 800, crop: 'scale' }
],
// Tags for organization
tags: ['product', 'shoes'],
// Metadata
context: 'caption=Nike Shoes|alt=Running shoes',
// Overwrite existing
overwrite: true,
invalidate: true,
// Resource type
resource_type: 'image', // 'image', 'video', 'raw', 'auto'
// Access control
type: 'upload', // 'upload', 'private', 'authenticated'
});
Upload Large Files
// For files > 100MB
const result = await cloudinary.uploader.upload_large('./large-video.mp4', {
resource_type: 'video',
chunk_size: 6000000, // 6MB chunks
});
URL Transformations
Build URLs with on-the-fly transformations.
// Using cloudinary.url()
const url = cloudinary.url('products/my-image', {
width: 400,
height: 300,
crop: 'fill',
gravity: 'auto',
quality: 'auto',
fetch_format: 'auto',
});
// https://res.cloudinary.com/cloud/image/upload/w_400,h_300,c_fill,g_auto,q_auto,f_auto/products/my-image
// Manual URL construction
const baseUrl = `https://res.cloudinary.com/${cloudName}/image/upload`;
const transformations = 'w_400,h_300,c_fill,g_auto,q_auto,f_auto';
const publicId = 'products/my-image';
const url = `${baseUrl}/${transformations}/${publicId}`;
Transformation Parameters
Resize & Crop
{
width: 400,
height: 300,
crop: 'fill', // fill, fit, scale, thumb, crop, pad
gravity: 'auto', // auto, face, center, north, south, east, west
aspect_ratio: '16:9',
}
Crop Modes
| Mode | Description |
|---|---|
fill | Fill dimensions, crop excess |
fit | Fit within dimensions, maintain ratio |
scale | Scale to dimensions (may distort) |
thumb | Thumbnail with smart crop |
crop | Crop from specified area |
pad | Add padding to fit dimensions |
limit | Like fit, but never upscale |
Quality & Format
{
quality: 'auto', // auto, auto:low, auto:good, auto:best, 1-100
fetch_format: 'auto', // auto, webp, avif, jpg, png
}
Effects
{
effect: 'blur:500',
effect: 'grayscale',
effect: 'sepia',
effect: 'brightness:30',
effect: 'contrast:50',
effect: 'saturation:70',
effect: 'sharpen',
effect: 'vignette',
effect: 'art:athena', // Artistic filters
}
Face Detection
{
crop: 'thumb',
gravity: 'face', // Center on face
width: 200,
height: 200,
}
// Multiple faces
{
crop: 'thumb',
gravity: 'faces',
width: 400,
height: 300,
}
Overlays
// Text overlay
{
overlay: {
font_family: 'Arial',
font_size: 40,
text: 'Hello World'
},
gravity: 'south',
y: 20,
color: 'white',
}
// Image overlay (watermark)
{
overlay: 'logo',
gravity: 'south_east',
x: 10,
y: 10,
width: 100,
opacity: 50,
}
Chained Transformations
const url = cloudinary.url('products/shoe', {
transformation: [
// First: resize
{ width: 800, height: 600, crop: 'fill' },
// Then: apply effect
{ effect: 'improve' },
// Finally: optimize
{ quality: 'auto', fetch_format: 'auto' }
]
});
React SDK
npm install @cloudinary/react @cloudinary/url-gen
import { Cloudinary } from '@cloudinary/url-gen';
import { AdvancedImage } from '@cloudinary/react';
import { fill } from '@cloudinary/url-gen/actions/resize';
import { autoGravity } from '@cloudinary/url-gen/qualifiers/gravity';
import { format, quality } from '@cloudinary/url-gen/actions/delivery';
import { auto } from '@cloudinary/url-gen/qualifiers/format';
// Configure
const cld = new Cloudinary({
cloud: { cloudName: 'your-cloud-name' }
});
function ProductImage({ publicId }) {
const image = cld
.image(publicId)
.resize(fill().width(400).height(300).gravity(autoGravity()))
.delivery(format(auto()))
.delivery(quality('auto'));
return <AdvancedImage cldImg={image} />;
}
With Placeholder & Lazy Loading
import { AdvancedImage, lazyload, placeholder } from '@cloudinary/react';
<AdvancedImage
cldImg={myImage}
plugins={[
lazyload(),
placeholder({ mode: 'blur' }) // blur, pixelate, vectorize
]}
/>
Next.js Integration
With next/image
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'res.cloudinary.com',
},
],
},
};
import Image from 'next/image';
function CloudinaryImage({ publicId, width, height }) {
const cloudName = process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME;
const src = `https://res.cloudinary.com/${cloudName}/image/upload/c_fill,w_${width},h_${height},q_auto,f_auto/${publicId}`;
return (
<Image
src={src}
alt=""
width={width}
height={height}
/>
);
}
next-cloudinary Package
npm install next-cloudinary
import { CldImage, CldUploadWidget } from 'next-cloudinary';
// Display image
<CldImage
src="products/shoe"
width="400"
height="300"
crop="fill"
gravity="auto"
alt="Product"
/>
// Upload widget
<CldUploadWidget
uploadPreset="my_preset"
onUpload={(result) => {
console.log(result.info.secure_url);
}}
>
{({ open }) => (
<button onClick={() => open()}>Upload</button>
)}
</CldUploadWidget>
Video Transformations
// Video URL
const videoUrl = cloudinary.url('videos/sample', {
resource_type: 'video',
width: 640,
height: 360,
crop: 'fill',
quality: 'auto',
format: 'mp4',
});
// Thumbnail from video
const thumbnail = cloudinary.url('videos/sample', {
resource_type: 'video',
format: 'jpg',
start_offset: '5', // 5 seconds in
width: 400,
crop: 'fill',
});
// Animated GIF from video
const gif = cloudinary.url('videos/sample', {
resource_type: 'video',
format: 'gif',
start_offset: '2',
end_offset: '5',
width: 300,
});
Admin API
// List resources
const resources = await cloudinary.api.resources({
type: 'upload',
prefix: 'products/',
max_results: 100,
});
// Get resource details
const resource = await cloudinary.api.resource('products/shoe');
// Delete resource
await cloudinary.uploader.destroy('products/old-shoe');
// Rename resource
await cloudinary.uploader.rename('old-name', 'new-name');
// Create folder
await cloudinary.api.create_folder('new-folder');
Upload Presets
Configure in Cloudinary dashboard for unsigned uploads.
// Unsigned upload (client-side)
const formData = new FormData();
formData.append('file', file);
formData.append('upload_preset', 'my_preset');
const response = await fetch(
`https://api.cloudinary.com/v1_1/${cloudName}/image/upload`,
{ method: 'POST', body: formData }
);
const data = await response.json();
console.log(data.secure_url);
Signed Uploads (Secure)
// Server: Generate signature
const timestamp = Math.round(new Date().getTime() / 1000);
const signature = cloudinary.utils.api_sign_request(
{ timestamp, folder: 'uploads' },
apiSecret
);
// Client: Upload with signature
const formData = new FormData();
formData.append('file', file);
formData.append('api_key', apiKey);
formData.append('timestamp', timestamp);
formData.append('signature', signature);
formData.append('folder', 'uploads');
await fetch(
`https://api.cloudinary.com/v1_1/${cloudName}/image/upload`,
{ method: 'POST', body: formData }
);
Best Practices
- Use auto format and quality -
f_auto,q_autofor best optimization - Generate eager transformations - Pre-generate common sizes
- Use responsive images - Serve appropriately sized images
- Enable lazy loading - With blur placeholder
- Use upload presets - For consistent upload settings
- Tag and organize - Use folders and tags for management
