Media Pipeline

Adonis EOS includes a built-in media pipeline:

  • uploads to storage (local or S3-compatible)

  • derivative generation (thumb/small/medium/large) via sharp

  • animation support for Lottie (JSON) and SVG

  • optional optimization to webp

  • category tagging + metadata for discovery

Key files

  • Controller: app/controllers/media_controller.ts

  • Service: app/services/media_service.ts

  • Storage: app/services/storage_service.ts

  • Variant generation action: app/actions/generate_media_variants_action.ts

  • Media field type (module props/custom fields): app/fields/media.ts

  • Frontend Renderer: inertia/components/MediaRenderer.tsx

Supported Formats & Processing

Raster Images

JPG, PNG, WebP, GIF, AVIF are processed via sharp to generate size variants and optimized WebP versions.

Vector & Animations

  • SVG: Uploaded and served as-is. Supports dark-mode variant overrides.

  • Lottie: Supports .json and .lottie files. Rendered on the frontend using @lottiefiles/lottie-player.

Video

MP4 and WebM support. Playback modes (autoplay, inline, modal) are stored in the media asset metadata.

Derivatives configuration

Derivatives are configured with env:

  • MEDIA_DERIVATIVES

Default (if unset) in media_service.ts:

typescript
thumb:200x200_crop,small:400x,medium:800x,large:1600x

Notes:

  • _crop uses fit: cover (square crops, etc.)

  • non-crop uses fit: inside

Dark mode variants

When generating dark variants, media_service.ts can apply a tunable transform:

  • MEDIA_DARK_BRIGHTNESS (default ~0.55)

  • MEDIA_DARK_SATURATION (default ~0.75)

Optimized webp

media_service.optimizeToWebp() can generate a webp derivative:

  • MEDIA_WEBP_QUALITY (default ~82)

How media is referenced by modules

Modules commonly use a prop schema like:

ts
image: { type: 'media', storeAs: 'id' }

This means editors store a media asset id in props; renderers resolve it through the media API/service.

Storage Configuration

The media pipeline supports local and S3-compatible (specifically Cloudflare R2) storage. This is controlled by the STORAGE_DRIVER environment variable.

For detailed configuration instructions, see the Deployment Guide: Persistent Storage.

Migrating Storage Backends

If you are switching from local storage to Cloudflare R2, you can use the built-in migration command to sync your existing assets and update database references:

bash
node ace migrate:media:r2

See the Deployment Guide for full details on the migration process.

AI-Generated Media

The media pipeline is integrated with AI agents for automated image generation:

  • Tools: Agents use the generate_image MCP tool to create new assets.

  • Providers: Supports OpenAI (DALL-E) and Google (Imagen).

  • Staging: Generated images are automatically downloaded, optimized, and saved to the CMS media library before being staged in the post's review draft.

  • Config: Providers and models are configured at the agent level (see providerMedia and modelMedia in the AI Agents documentation).

Operational notes

  • If you add new derivative specs, consider a backfill job to regenerate variants for existing assets.

  • If you change storage backends, ensure existing URLs remain valid or provide redirect/migration logic.