# Image CDN API Documentation

The Image CDN provides on-the-fly image optimization via CloudFront + Lambda@Edge. All images served through the CDN are automatically compressed and converted to modern formats (WebP/AVIF) based on browser support.

> **Default Behavior**
Images are returned at **original dimensions** (capped at **2048px max**) with format conversion.
Smaller images are served at original size. Use presets for specific sizes:
- Listings: `?preset=medium` (600×600)
- Thumbnails: `?preset=thumb` (150×150)
- Full size (up to 2048): no params needed



## CDN URLs

| Environment | CDN Base URL |
|  --- | --- |
| Development | `https://d3bznwycx2s7pk.cloudfront.net` |
| Production | `https://d949acbs6mj2e.cloudfront.net` |


## Quick Start


```bash

# CDN URL - original dimensions (max 2048px), WebP if supported
https://d3bznwycx2s7pk.cloudfront.net/images/photo.png

# Listings/galleries (600×600)
https://d3bznwycx2s7pk.cloudfront.net/images/photo.png?preset=medium

# Thumbnail (150×150)
https://d3bznwycx2s7pk.cloudfront.net/images/photo.png?preset=thumb

# High quality large (1200×1200)
https://d3bznwycx2s7pk.cloudfront.net/images/photo.png?preset=large&q=95
```

## Presets

Use presets for consistent image sizes across the application:

| Preset | Dimensions | Use Case |
|  --- | --- | --- |
| `thumb` | 150×150 | List thumbnails, small icons |
| `medium` | 600×600 | Listings, card images |
| `large` | 1200×1200 | Detail views, full-screen galleries |
| `hero` | 1920×800 | Hero banners, headers |
| `avatar` | 200×200 | User avatars, profile pics |
| `card` | 400×300 | Product cards, previews |


> **Note:** Without query params, images keep original dimensions (capped at 2048px max).



```bash
# Usage
https://cdn.example.com/path/image.jpg?preset=thumb
https://cdn.example.com/path/image.jpg?preset=hero
```

## Query Parameters

| Parameter | Type | Default | Description |
|  --- | --- | --- | --- |
| `preset` | string | - | **Only way to resize** - see presets table above |
| `q` | number | 80 | Quality percentage (1-100) |
| `f` | string | `auto` | Output format |
| `fit` | string | `inside` | Resize fit mode (used with presets) |


> **Security:** Custom `w` and `h` parameters are disabled to prevent cache pollution attacks. Use presets only.


### Format Options (`f`)

| Value | Description |
|  --- | --- |
| `auto` | Auto-detect best format (WebP/AVIF if browser supports) |
| `jpeg` | Force JPEG output |
| `webp` | Force WebP output |
| `png` | Force PNG output (preserves transparency) |
| `avif` | Force AVIF output (best compression, newer browsers) |


### Fit Options (`fit`)

| Value | Description |
|  --- | --- |
| `inside` | Resize to fit within dimensions (default, maintains aspect ratio) |
| `cover` | Resize to cover dimensions (crop overflow) |
| `contain` | Same as inside, with padding if needed |
| `outside` | Resize to cover, allowing overhang |
| `fill` | Stretch to exact dimensions (ignores aspect ratio) |


## Examples

### Thumbnails for List View


```bash
# 150x150 thumbnail, high quality
?preset=thumb&q=90

# Custom small square
?w=100&h=100&fit=cover&q=80
```

### Product Cards


```bash
# Standard card size
?preset=card

# Custom card with WebP
?w=400&h=300&f=webp&q=85
```

### Hero Images


```bash
# Full-width hero
?preset=hero

# Custom hero dimensions
?w=1920&h=600&fit=cover&q=85
```

### Avatars


```bash
# Standard avatar
?preset=avatar

# Circular crop
?w=200&h=200&fit=cover&q=80
```

### High-Quality Downloads


```bash
# Large, high-quality (for downloads/printing)
?preset=large&q=95

# Original quality, just format conversion
?q=100&f=webp
```

## API Response Transformation

When `IMAGE_CDN_URL` is configured, the `ImageCdnTransformInterceptor` automatically transforms S3 URLs in API responses to CDN URLs.

> **Note:** Transformed URLs return images at **original dimensions** (max 2048px) with format conversion. Use presets for smaller sizes (e.g., `?preset=medium` for listings).


### Before (S3 URL)


```json
{
  "id": "123",
  "imageUrl": "https://pers.assets.dev.s3.eu-west-1.amazonaws.com/products/photo.jpg"
}
```

### After (CDN URL)


```json
{
  "id": "123",
  "imageUrl": "https://d3bznwycx2s7pk.cloudfront.net/products/photo.jpg"
}
```

### Disabling Transformation

To disable automatic transformation, don't set `IMAGE_CDN_URL` in your environment.

## SDK Integration

### TypeScript/JavaScript


```typescript
import { ImageCdnUrlBuilder } from '@pers/serverless-functions/infrastructure/interceptors';

const cdn = new ImageCdnUrlBuilder('https://d3bznwycx2s7pk.cloudfront.net');

// Using presets
const thumb = cdn.thumbnail('products/photo.jpg');
const large = cdn.large('products/photo.jpg');

// Custom options
const custom = cdn.build('products/photo.jpg', {
  width: 800,
  height: 600,
  quality: 85,
  format: 'webp',
  fit: 'cover',
});
```

### Mobile SDK


```swift
// iOS Example
let cdnUrl = "https://d949acbs6mj2e.cloudfront.net"
let imagePath = "products/photo.jpg"
let thumbnailUrl = "\(cdnUrl)/\(imagePath)?preset=thumb"
```


```kotlin
// Android Example
val cdnUrl = "https://d949acbs6mj2e.cloudfront.net"
val imagePath = "products/photo.jpg"
val thumbnailUrl = "$cdnUrl/$imagePath?preset=thumb"
```

## Environment Configuration

Add to your `.env` file:


```bash
# Enable CDN URL transformation
IMAGE_CDN_URL=https://d3bznwycx2s7pk.cloudfront.net

# Optional: Default preset for transformed URLs
IMAGE_CDN_DEFAULT_PRESET=medium
```

### Environment Variables

| Variable | Description | Example |
|  --- | --- | --- |
| `IMAGE_CDN_URL` | CDN base URL (enables transformation) | `https://d3bznwycx2s7pk.cloudfront.net` |
| `IMAGE_CDN_DEFAULT_PRESET` | Default preset for auto-transformation | `medium` |
| `AWS_S3_BUCKET_NAME` | S3 bucket name (for URL matching) | `pers.assets.dev` |


## Performance

| Metric | Value |
|  --- | --- |
| First request | ~200-500ms (Lambda cold start + processing) |
| Cached requests | ~10-50ms (CloudFront edge cache) |
| Cache duration | 1 year (immutable images) |
| Compression | Up to 90%+ reduction |


### Cache Headers


```
Cache-Control: public, max-age=31536000, immutable
X-Image-Optimized: true
```

## Error Handling

| HTTP Code | Description |
|  --- | --- |
| 200 | Success - optimized image returned |
| 404 | Image not found in S3 |
| 5xx | Processing error - falls back to original image from S3 |


> **Note:** Invalid parameters are automatically clamped to valid ranges (e.g., `w=5` becomes `w=10`, `q=150` becomes `q=100`).


## Architecture


```
┌──────────────┐     ┌─────────────────┐     ┌───────────────┐
│   Client     │────▶│   CloudFront    │────▶│  Lambda@Edge  │
│  (Browser)   │     │   (CDN Edge)    │     │  (us-east-1)  │
└──────────────┘     └─────────────────┘     └───────┬───────┘
                            │ cache                  │
                            ▼                        ▼
                     ┌─────────────────┐     ┌───────────────┐
                     │  Edge Cache     │     │   S3 Bucket   │
                     │  (31536000s)    │     │  (eu-west-1)  │
                     └─────────────────┘     └───────────────┘
```

## Supported Formats

### Input Formats

- JPEG (.jpg, .jpeg)
- PNG (.png)
- WebP (.webp)
- GIF (.gif) - animations preserved
- AVIF (.avif)


### Output Formats

- JPEG (default for photos)
- WebP (auto-detected for Chrome, Edge, Firefox)
- AVIF (auto-detected for Chrome 85+, Firefox 93+)
- PNG (when transparency required)


## Troubleshooting

### Images not optimizing

1. Check `IMAGE_CDN_URL` is set in environment
2. Verify image exists in S3 bucket
3. Check CloudFront distribution is enabled


### Cache not working

1. CloudFront caches by full URL including query params
2. Use consistent query param order
3. Invalidate cache: `aws cloudfront create-invalidation --distribution-id XXXXX --paths "/path/*"`


### Lambda errors

Check CloudWatch logs in us-east-1:


```bash
aws logs tail /aws/lambda/us-east-1.pers-image-optimizer-prod-imageOptimizer --follow
```