Media Pipeline
Adonis EOS includes a built-in media pipeline:
uploads to storage (local or S3-compatible)
derivative generation (thumb/small/medium/large) via
sharpanimation support for Lottie (JSON) and SVG
optional optimization to webp
category tagging + metadata for discovery
Key files
Controller:
app/controllers/media_controller.tsService:
app/services/media_service.tsStorage:
app/services/storage_service.tsVariant generation action:
app/actions/generate_media_variants_action.tsMedia field type (module props/custom fields):
app/fields/media.tsFrontend 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
.jsonand.lottiefiles. 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:
thumb:200x200_crop,small:400x,medium:800x,large:1600x
Notes:
_cropusesfit: 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:
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:
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_imageMCP 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
providerMediaandmodelMediain 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.