ive routing. The architecture below demonstrates a TypeScript-based pipeline that handles metadata extraction, format routing, multi-format generation, and HTML markup construction.
Architecture Decisions & Rationale
- Pipeline Pattern over Monolithic Functions: Image processing involves distinct phases (validation, routing, encoding, markup generation). A pipeline isolates concerns, making each stage testable and replaceable.
- Heuristic Format Routing: Rather than hardcoding format rules, the router evaluates asset metadata (content type, dimensions, transparency requirement) to select the optimal primary and fallback formats.
- Edge-First Fallback Chain: Modern browsers negotiate format support via
Accept headers or <picture> elements. The pipeline generates a progressive fallback chain (AVIF β WebP β JPG) to ensure universal compatibility without sacrificing modern efficiency.
- Security-First SVG Handling: Vector formats execute as markup. The pipeline enforces sanitization before inclusion to prevent XSS vectors.
Implementation
// Interfaces for type-safe pipeline configuration
interface AssetMetadata {
originalWidth: number;
originalHeight: number;
hasTransparency: boolean;
isVector: boolean;
contentType: 'photo' | 'graphic' | 'icon' | 'animation';
}
interface FormatStrategy {
primary: string;
fallbacks: string[];
quality: number;
maxWidths: number[];
}
interface DeliveryManifest {
html: string;
srcset: string;
fallbackChain: string[];
dimensions: { width: number; height: number };
}
// Core routing logic
class FormatRouter {
resolveStrategy(metadata: AssetMetadata): FormatStrategy {
if (metadata.isVector) {
return { primary: 'svg', fallbacks: [], quality: 100, maxWidths: [] };
}
if (metadata.contentType === 'animation') {
return { primary: 'webp', fallbacks: ['gif'], quality: 85, maxWidths: [480, 768, 1024] };
}
if (metadata.hasTransparency) {
return { primary: 'webp', fallbacks: ['png'], quality: 90, maxWidths: [480, 768, 1024, 1440] };
}
// Default photo/graphic routing
return { primary: 'avif', fallbacks: ['webp', 'jpg'], quality: 80, maxWidths: [480, 768, 1024, 1440] };
}
}
// Pipeline orchestrator
class MediaDeliveryPipeline {
private router: FormatRouter;
constructor() {
this.router = new FormatRouter();
}
generateManifest(metadata: AssetMetadata, baseFilename: string): DeliveryManifest {
const strategy = this.router.resolveStrategy(metadata);
const { primary, fallbacks, quality, maxWidths } = strategy;
// Generate responsive srcset entries
const srcsetEntries = maxWidths.map((width) => {
const filename = `${baseFilename}-${width}.${primary}`;
return `${filename} ${width}w`;
}).join(', ');
// Construct fallback chain for <picture> element
const fallbackSources = fallbacks.map((fmt) => {
const fallbackSrcset = maxWidths.map((width) => {
return `${baseFilename}-${width}.${fmt} ${width}w`;
}).join(', ');
return `<source srcset="${fallbackSrcset}" type="image/${fmt}">`;
}).join('\n');
const primarySrc = `${baseFilename}-${maxWidths[maxWidths.length - 1]}.${primary}`;
const imgTag = `<img src="${primarySrc}" alt="optimized-media" loading="lazy" decoding="async" width="${metadata.originalWidth}" height="${metadata.originalHeight}">`;
const html = fallbacks.length > 0
? `<picture>\n${fallbackSources}\n${imgTag}\n</picture>`
: imgTag;
return {
html,
srcset: srcsetEntries,
fallbackChain: [primary, ...fallbacks],
dimensions: { width: metadata.originalWidth, height: metadata.originalHeight }
};
}
}
Why This Architecture Works
- Deterministic Routing: The
FormatRouter eliminates guesswork. Transparency triggers WebP/PNG fallbacks. Photos route to AVIF with WebP/JPG fallbacks. Animations default to WebP. This matches browser capability matrices while preserving legacy compatibility.
- Progressive Enhancement: The
<picture> element generation ensures modern clients receive the smallest payload, while older clients gracefully degrade to supported formats without broken images.
- Explicit Dimension Reservation: The pipeline injects
width and height attributes directly into the <img> tag. This reserves layout space before network fetches complete, neutralizing CLS caused by late-loading media.
- Lazy & Async Decoding:
loading="lazy" defers off-screen fetches. decoding="async" prevents main-thread blocking during rasterization. These attributes are non-negotiable for performance-critical deployments.
Pitfall Guide
1. The Transparency Fallacy
Explanation: Developers default to PNG for any image requiring transparency, ignoring that PNG uses lossless compression and balloons file size for photographic content.
Fix: Route transparent assets to WebP or AVIF. Both support alpha channels with significantly better compression ratios. Reserve PNG only for pixel-perfect UI elements where lossless fidelity is mandatory.
2. Raw Sensor Uploads
Explanation: Uploading camera or phone exports at native resolution (often 3000β6000px) forces browsers to download and downscale massive files, even when CSS restricts display width.
Fix: Enforce dimension validation at ingestion. Resize assets to the maximum display breakpoint plus a 1.5x density buffer for high-DPI screens. Never deliver native sensor output directly to production.
3. The CLS Blind Spot
Explanation: Omitting explicit width/height attributes or CSS aspect-ratio reserves causes layout shifts when images load asynchronously. This directly impacts Core Web Vitals scores.
Fix: Always inject intrinsic dimensions into markup. Use aspect-ratio: width / height; in CSS as a fallback. The pipeline above automates this by reading metadata and applying attributes during manifest generation.
4. SVG Injection Vectors
Explanation: SVG files are XML-based and can contain <script>, <foreignObject>, or event handlers. Uploading untrusted vectors introduces XSS vulnerabilities.
Fix: Run all SVGs through a sanitization library (e.g., DOMPurify or svgo with security plugins) before storage. Strip executable content, restrict external references, and validate against a strict schema.
5. AVIF Isolation
Explanation: Deploying AVIF as the sole format breaks rendering on Safari versions prior to 16.4 and older Android WebViews.
Fix: Always generate a fallback chain. The <picture> element with WebP and JPG fallbacks ensures universal coverage while allowing modern browsers to negotiate the most efficient format.
6. GIF Bloat for Motion
Explanation: GIF uses an 8-bit color palette and lacks inter-frame compression. Short videos or complex animations encoded as GIFs can exceed 10MB, destroying LCP.
Fix: Replace GIFs with <video> elements or animated WebP. Use muted autoplay loop playsinline for silent motion content. Reserve GIF only for tiny, legacy-compatible decorative elements.
7. Ignoring Network Context
Explanation: Delivering identical assets to 5G and 3G connections wastes bandwidth and increases abandonment rates on constrained networks.
Fix: Implement adaptive delivery via CDN or service workers. Detect Save-Data headers or navigator.connection.effectiveType to serve lower-resolution variants or defer non-critical media on metered connections.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| High-traffic e-commerce catalog | AVIF primary, WebP fallback, aggressive srcset | Maximizes LCP improvement across modern browsers while maintaining compatibility | Reduces CDN egress by 30β50%, lowers bounce rate |
| Marketing landing page with hero visuals | WebP default, JPG fallback, lazy loading + async decode | Balances encoding speed with payload reduction; ensures fast first paint | Moderate build-time cost, significant network savings |
| Internal dashboard / admin panel | PNG for UI elements, JPG for photos, no AVIF | Internal tools prioritize compatibility and tooling simplicity over marginal size gains | Low optimization overhead, acceptable payload size |
| Legacy browser support required (>5% IE11/old Safari) | JPG/PNG baseline, WebP progressive enhancement | Guarantees rendering across all clients while allowing modern upgrades | Higher baseline payload, zero compatibility risk |
| Real-time user-generated content | Edge-compute resizing + WebP conversion on upload | Prevents raw uploads from bloating storage and delivery | Increases edge compute cost, drastically reduces storage/CDN fees |
Configuration Template
// delivery.config.ts
export const MediaDeliveryConfig = {
breakpoints: [480, 768, 1024, 1440],
densityMultiplier: 1.5,
formats: {
photo: { primary: 'avif', fallbacks: ['webp', 'jpg'], quality: 80 },
graphic: { primary: 'webp', fallbacks: ['png'], quality: 90 },
icon: { primary: 'svg', fallbacks: [], sanitize: true },
animation: { primary: 'webp', fallbacks: ['mp4', 'gif'], quality: 85 }
},
delivery: {
lazyThreshold: 0.1,
decodeMode: 'async',
reserveLayout: true,
respectSaveData: true
},
security: {
svgMaxSizeKB: 50,
stripMetadata: true,
allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/svg+xml']
}
};
Quick Start Guide
- Install Dependencies: Add
sharp (or libvips bindings) for encoding, dompurify for SVG sanitization, and a build plugin for manifest generation.
- Configure Routing: Import
MediaDeliveryConfig and map upload handlers to extract metadata before storage.
- Generate Variants: Run the pipeline during CI/CD or edge deployment to produce breakpoint-aligned variants and fallback chains.
- Inject Markup: Replace static
<img> tags with pipeline-generated <picture> elements. Verify width/height attributes and loading="lazy" are present.
- Validate Performance: Run Lighthouse or WebPageTest. Confirm LCP improves, CLS remains at 0, and total image payload drops by 30%+. Adjust quality thresholds if perceptual degradation occurs.
Implementing a structured image delivery pipeline transforms media from an unpredictable network cost into a controlled performance lever. By routing formats programmatically, reserving layout space, and enforcing fallback chains, engineering teams can consistently meet Core Web Vitals targets while reducing infrastructure spend.