Image Optimization

Image Optimization

Chronicle automatically optimizes content images via an on-demand /api/image endpoint. Images are resized, converted to modern formats (WebP/AVIF), and cached on disk.

How It Works

  1. The remark plugin rewrites all image URLs to route through /api/image
  2. On first request, the image is resized and converted based on browser support
  3. The result is cached — subsequent requests are served instantly
  4. On server start, all content images are pre-cached (warmup)

Format Negotiation

The endpoint reads the browser's Accept header and serves the best format:

Browser sendsFormat served
Accept: image/avifAVIF
Accept: image/webpWebP
NeitherOriginal (resized only)

SVG images are passed through unchanged.

Query Parameters

Control image output directly in markdown using query parameters:

![Screenshot](screenshot.png?w=640&q=90)

Width (w)

Sets the output width in pixels. The image is resized proportionally (height auto-calculated). Images are never enlarged beyond their original size.

Allowed values:

WidthUse case
320Small thumbnails, mobile icons
640Mobile content images
768Tablet content images
1024Default — desktop content
1280Wide content areas
1536Large displays
1920Full-width hero images

Default: 1024

Quality (q)

Sets the compression quality. Lower values produce smaller files with more compression artifacts.

Allowed values:

QualityFile sizeUse case
60SmallestThumbnails, previews
75BalancedDefault — content images
90High qualityScreenshots with text
100MaximumLossless-like output

Default: 75

Examples

<!-- Default: 1024w, quality 75 -->
![Overview](overview.png)

<!-- Small thumbnail -->
![Thumb](thumb.png?w=320&q=60)

<!-- High quality screenshot -->
![UI](dashboard.png?w=1280&q=90)

<!-- Width only, default quality -->
![Photo](photo.png?w=640)

<!-- Quality only, default width -->
![Chart](chart.png?q=90)

API Endpoint

GET /api/image?url=/_content/docs/photo.png&w=640&q=75
ParameterRequiredDescription
urlYesContent image path (must start with /_content/)
wYesOutput width (must be an allowed value)
qNoQuality 1-100 (snapped to nearest allowed value)

Response Headers

Content-Type: image/webp (or image/avif, or original mime)
Cache-Control: public, max-age=31536000, immutable
Vary: Accept

Cache

Optimized images are cached using Nitro storage with the fs driver at .cache/images/. Cache persists across server restarts.

The warmup process pre-caches all content images as WebP at default width (1024) and quality (75) when the server starts.