Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/images/patterns.md
1# Common Patterns23## URL Transform Options45```6width=<PX> height=<PX> fit=scale-down|contain|cover|crop|pad7quality=85 format=auto|webp|avif|jpeg|png dpr=28gravity=auto|face|left|right|top|bottom sharpen=2 blur=109rotate=90|180|270 background=white metadata=none|copyright|keep10```1112## Responsive Images (srcset)1314```html15<img src="https://imagedelivery.net/{hash}/{id}/width=800"16srcset=".../{id}/width=400 400w, .../{id}/width=800 800w, .../{id}/width=1200 1200w"17sizes="(max-width: 600px) 400px, 800px" />18```1920## Format Negotiation2122```typescript23async fetch(request: Request, env: Env): Promise<Response> {24const accept = request.headers.get('Accept') || '';25const format = /image\/avif/.test(accept) ? 'avif' : /image\/webp/.test(accept) ? 'webp' : 'jpeg';26return env.IMAGES.input(buffer).transform({ format, quality: 85 }).output().response();27}28```2930## Direct Creator Upload3132```typescript33// Backend: Generate upload URL34const response = await fetch(35`https://api.cloudflare.com/client/v4/accounts/${env.ACCOUNT_ID}/images/v2/direct_upload`,36{ method: 'POST', headers: { 'Authorization': `Bearer ${env.API_TOKEN}` },37body: JSON.stringify({ requireSignedURLs: false, metadata: { userId } }) }38);3940// Frontend: Upload to returned uploadURL41const formData = new FormData();42formData.append('file', file);43await fetch(result.uploadURL, { method: 'POST', body: formData });44// Use: https://imagedelivery.net/{hash}/${result.id}/public45```4647## Transform & Store to R24849```typescript50async fetch(request: Request, env: Env): Promise<Response> {51const file = (await request.formData()).get('image') as File;52const transformed = await env.IMAGES53.input(await file.arrayBuffer())54.transform({ width: 800, format: 'avif', quality: 80 })55.output();56await env.R2.put(`images/${Date.now()}.avif`, transformed.response().body);57return Response.json({ success: true });58}59```6061## Watermarking6263```typescript64const watermark = await env.ASSETS.fetch(new URL('/watermark.png', request.url));65const result = await env.IMAGES66.input(await image.arrayBuffer())67.draw(env.IMAGES.input(watermark.body).transform({ width: 100 }), { bottom: 20, right: 20, opacity: 0.7 })68.transform({ format: 'avif' })69.output();70return result.response();71```7273## Device-Based Transforms7475```typescript76const ua = request.headers.get('User-Agent') || '';77const isMobile = /Mobile|Android|iPhone/i.test(ua);78return env.IMAGES.input(buffer)79.transform({ width: isMobile ? 400 : 1200, quality: isMobile ? 75 : 85, format: 'avif' })80.output().response();81```8283## Caching Strategy8485```typescript86async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {87const cache = caches.default;88let response = await cache.match(request);89if (!response) {90response = await env.IMAGES.input(buffer).transform({ width: 800, format: 'avif' }).output().response();91response = new Response(response.body, { headers: { ...response.headers, 'Cache-Control': 'public, max-age=86400' } });92ctx.waitUntil(cache.put(request, response.clone()));93}94return response;95}96```9798## Batch Processing99100```typescript101const results = await Promise.all(images.map(buffer =>102env.IMAGES.input(buffer).transform({ width: 800, fit: 'cover', format: 'avif' }).output()103));104```105106## Error Handling107108```typescript109try {110return (await env.IMAGES.input(buffer).transform({ width: 800 }).output()).response();111} catch (error) {112console.error('Transform failed:', error);113return new Response('Image processing failed', { status: 500 });114}115```116