JustFlows

Documentation is English-only for now. The rest of the site follows your language.

Media

Upload and list files, allowed types, where files live, and the media package’s S3 and derivatives.

6 min read

Admin → Media. Uploads go through POST /api/media (multer, memory) as administrator, editor, or author. The defaults are 100 MB per file (JF_MAX_UPLOAD_MB) and 5120 MB per site library (JF_MAX_LIBRARY_MB); oversized files return 413. GET /api/media?limit= lists rows. Files are served from GET /uploads/*.

Allowed types (admin route)

  • Images: JPEG, PNG, GIF, WebP, AVIF.
  • Documents: PDF.
  • Video: MP4, WebM.
  • Audio: MPEG, Ogg.
  • SVG is not on the server allow-list.

Where files go

The live upload path writes {STORAGE_LOCAL_PATH or ./uploads}/{siteId}/{uuid}.ext and a database row. Hooks: media.beforeUpload / media.beforeDelete (gates), media.uploaded / media.deleted (actions), filter media.metadata.

Responsive images and formats

Raster uploads generate a configurable set of width-scaled variants plus WebP (and AVIF when enabled) alongside the untouched original — inline on upload, and backfillable from Admin → Tools → Responsive images with progress and per-file failures (POST /api/media/regenerate, GET /api/media/regenerate/status). Every public surface that renders an uploaded image — core.image, the Gallery block, blog-post-list featured thumbnails, and the Featured Image theme block — goes through one resolver (renderResponsiveImage / renderMediaImage) that emits <picture> / srcset / sizes with format fallback, intrinsic width / height to prevent layout shift, and loading="lazy" / decoding="async" defaults with an eager opt-out.

`.env` keyControls
JF_IMAGE_DERIVATIVESGenerate variants on upload.
JF_IMAGE_RESPONSIVE_MARKUPEmit <picture>/srcset on public pages (off serves originals everywhere without deleting variants).
JF_IMAGE_WIDTHSComma-separated widths to generate, default 320,640,960,1280,1920.
JF_IMAGE_MAX_WIDTHUpper bound for any variant, default 2560.
JF_IMAGE_FORMATSFormats to generate alongside the original, default webp.
JF_IMAGE_QUALITY_WEBP / _AVIF / _JPEGPer-format encode quality.
JF_IMAGE_STRIP_METADATAStrip EXIF/GPS from generated variants.
JF_IMAGE_THUMBThumbnail size, default 400x400.
JF_IMAGE_KEEP_ORIGINALFilename allowlist that skips variant generation.

All of it is configurable from the same admin panel and written to .env with no restart. Each asset carries a focal point — set by clicking the subject in the Media Library — that drives thumbnail crops and object-position. SVGs are never rasterised, and variants live under the same uploads/ path so CDN/S3 offload and static export cover them for free. Migration 0027_media_responsive supports all database dialects.

The Gallery block (justflows.gallery.grid) renders as grid, masonry, carousel, slideshow, or list, each emitting a layout-aware sizes value so the browser downloads the right variant.

Placeholder images

Justflows ships neutral placeholders for a generic image, a featured image, a thumbnail, an avatar, and the social share image. Featured Image and Post List show the placeholder when a post has no image, and an Image block without an image shows the generic one. A page with no share image falls back to the site logo, then the share placeholder; og:image is always an absolute URL.

Settings → Placeholders replaces any placeholder with your own image or turns them all off. Featured Image and Post List can each turn them off per block. Plugins can ship their own kind (Shop adds Product image) — see Plugins.

Package: `@justflows/media`

MediaService supports local and S3 adapters and Sharp derivatives: thumbnail 150², small 400, medium 800, large 1600, as WebP. Configure STORAGE_DRIVER=s3 and the S3_* keys as in Configuration. The CE admin upload route does not yet call this service for every upload — local disk is what the wizard and Media page use today.