/** * Cloudflare Images - Transform via URL * * Transform images using the special URL format: * /cdn-cgi/image// * * Works on ANY publicly accessible image (not just Cloudflare Images storage). */ /** * URL Transformation Examples */ // Basic resize const thumbnailURL = '/cdn-cgi/image/width=300,height=300,fit=cover/uploads/photo.jpg'; // Responsive with auto format (WebP/AVIF) const responsiveURL = '/cdn-cgi/image/width=800,quality=85,format=auto/uploads/hero.jpg'; // Smart crop to face const avatarURL = '/cdn-cgi/image/width=200,height=200,gravity=face,fit=cover/uploads/profile.jpg'; // Blur effect const blurredURL = '/cdn-cgi/image/blur=20,quality=50/uploads/background.jpg'; // Sharpen const sharpenedURL = '/cdn-cgi/image/sharpen=3,quality=90/uploads/product.jpg'; // Rotate and flip const rotatedURL = '/cdn-cgi/image/rotate=90,flip=h/uploads/document.jpg'; /** * All available options (comma-separated) */ interface TransformOptions { // Sizing width?: number; // Max width in pixels (alias: w) height?: number; // Max height in pixels (alias: h) dpr?: number; // Device pixel ratio (1-3) // Fit modes fit?: 'scale-down' | 'contain' | 'cover' | 'crop' | 'pad'; // Quality quality?: number; // 1-100 (alias: q) compression?: 'fast' | 'lossless'; // WebP only // Format format?: 'auto' | 'avif' | 'webp' | 'jpeg' | 'baseline-jpeg' | 'json'; // 'auto' serves AVIF → WebP → original based on browser support // Cropping gravity?: 'auto' | 'face' | 'left' | 'right' | 'top' | 'bottom' | string; // Or 'XxY' coordinates zoom?: number; // 0-1 for face cropping trim?: number; // Remove border (pixels) // Effects blur?: number; // 1-250 sharpen?: number; // 0-10 brightness?: number; // 0-2 (1 = no change) contrast?: number; // 0-2 (1 = no change) gamma?: number; // 0-2 (1 = no change) // Rotation rotate?: 0 | 90 | 180 | 270; flip?: 'h' | 'v' | 'hv'; // Horizontal, vertical, both // Other background?: string; // CSS color for transparency/padding metadata?: 'none' | 'copyright' | 'keep'; // EXIF handling anim?: boolean; // Preserve GIF/WebP animation (default: true) } /** * Build transformation URL */ export function buildTransformURL( imagePath: string, options: Partial ): string { const params: string[] = []; // Sizing if (options.width) params.push(`width=${options.width}`); if (options.height) params.push(`height=${options.height}`); if (options.dpr) params.push(`dpr=${options.dpr}`); // Fit if (options.fit) params.push(`fit=${options.fit}`); // Quality if (options.quality) params.push(`quality=${options.quality}`); if (options.compression) params.push(`compression=${options.compression}`); // Format if (options.format) params.push(`format=${options.format}`); // Cropping if (options.gravity) params.push(`gravity=${options.gravity}`); if (options.zoom) params.push(`zoom=${options.zoom}`); if (options.trim) params.push(`trim=${options.trim}`); // Effects if (options.blur) params.push(`blur=${options.blur}`); if (options.sharpen) params.push(`sharpen=${options.sharpen}`); if (options.brightness) params.push(`brightness=${options.brightness}`); if (options.contrast) params.push(`contrast=${options.contrast}`); if (options.gamma) params.push(`gamma=${options.gamma}`); // Rotation if (options.rotate) params.push(`rotate=${options.rotate}`); if (options.flip) params.push(`flip=${options.flip}`); // Other if (options.background) params.push(`background=${encodeURIComponent(options.background)}`); if (options.metadata) params.push(`metadata=${options.metadata}`); if (options.anim === false) params.push('anim=false'); return `/cdn-cgi/image/${params.join(',')}/${imagePath}`; } /** * Example HTML generation */ export function generateResponsiveHTML(imagePath: string, alt: string): string { return ` ${alt} `.trim(); } /** * Common presets */ export const presets = { thumbnail: (path: string) => buildTransformURL(path, { width: 300, height: 300, fit: 'cover', quality: 85, format: 'auto' }), avatar: (path: string) => buildTransformURL(path, { width: 200, height: 200, fit: 'cover', gravity: 'face', quality: 90, format: 'auto' }), hero: (path: string) => buildTransformURL(path, { width: 1920, height: 1080, fit: 'cover', quality: 85, format: 'auto' }), blurPlaceholder: (path: string) => buildTransformURL(path, { width: 50, quality: 10, blur: 20, format: 'webp' }), productImage: (path: string) => buildTransformURL(path, { width: 800, height: 800, fit: 'contain', quality: 90, sharpen: 2, format: 'auto' }) }; /** * Usage examples: * * ```html * * * * * * * * * * * * ``` * * With helper functions: * ```typescript * const url = buildTransformURL('uploads/photo.jpg', { * width: 800, * quality: 85, * format: 'auto' * }); * * const html = generateResponsiveHTML('uploads/hero.jpg', 'Hero image'); * * const thumbURL = presets.thumbnail('uploads/photo.jpg'); * ``` * * IMPORTANT: * - Must enable transformations on zone first (Dashboard → Images → Transformations) * - Works on any publicly accessible image (not just Cloudflare Images storage) * - Source image must use HTTPS (HTTP not supported) * - URL-encode special characters in paths */