Atomic Payload
Features

Images & Video

On-demand image transforms with focal-point cropping and low-res placeholders, plus Mux video upload and streaming.

Overview

Media in Atomic Payload is split by how files are served. Images are static uploads handled by @pro-laico/images: files live in Payload upload collections and render as optimized images. Video is Mux-backed streaming handled by @pro-laico/mux-video: uploads stream through Mux's API and play back from Mux on the front end. Reach for the images plugin for anything you would render as a picture (photos, graphics, favicons), and for the Mux plugin for anything that plays, instead of uploading video files as static media.

Images arrive as a general-purpose upload collection that stores only the original and generates every rendered size on demand, cropped to a focal point, with built-in low-res placeholders. A separate favicons collection keeps favicons out of your main image library. Both plugins also ship child blocks, so editors can drop an image or a video straight into Atomic content.

How it works

Images

@pro-laico/images registers two upload collections, a variant cache, and a field helper:

  • Images: the source collection. An upload stores only the original (there's no fixed size ladder). Every rendered size is generated the first time a page requests it, resized and cropped to the focal point you set in the admin, then cached.
  • generatedImages: a hidden collection that caches those generated sizes, one row per size. Replacing a file or moving its focal point purges the stale ones so they regenerate.
  • Favicons: a separate collection for favicons specifically. They have different size and format requirements, and mixing them with content images would pollute the main image library.
  • FaviconField: a reusable favicon-picker field config for selecting a favicon from Favicons (used in the SiteMetaData global).

You render images with the bundled <ResponsiveImage> component: a plain <img> whose srcset points at the transform endpoint, so the browser downloads only the size that fits where the image renders. It is not next/image, and it works in server and client trees.

Low-res placeholders are built in and on by default, with nothing stored on the document. <ResponsiveImage> paints the smallest transform variant (a tiny, low-quality crop) as the wrapper background and the browser upscales it to a soft blur while the full image loads. Turn it off per render with the component's blur prop (no extra plugin, dependency, or upload work).

The plugin also ships the ImageChild block, which lets editors drop an image into Atomic blocks. It's exposed from the @pro-laico/images/blocks/imageChild subpath as the createImageBlock factory and the prebuilt Image block (not from the package root), and renders through @pro-laico/atomic/children as a <ResponsiveImage>.

Use ImageChild when an editor places an image inside page content: the block points at an upload in Images and adds per-placement display options like an alt override, an aspect ratio, sizes, quality, fit, and lazy or eager loading. When you need an image in your own schema, reference the collection directly instead, with an upload field whose relationTo is images on your collection or global, the same pattern the bundled FaviconField uses for favicons.

Video

@pro-laico/mux-video is a thin wrapper around @oversightstudio/mux-video that:

  1. Registers a local mux-video extension collection: the slug the upstream plugin attaches its fields to via extendCollection: 'mux-video'. This is where your Mux upload metadata lives.
  2. Composes the upstream plugin with Atomic Payload defaults: admin thumbnail mode, a CORS origin derived from NEXT_PUBLIC_SERVER_URL, and env-driven Mux credentials.
  3. Ships a VideoChild block so editors can drop a Mux video into Atomic content. Its renderer mounts the @mux/mux-video-react player and pulls playback from Mux via @pro-laico/atomic/children.

Mux requires a collection it can extend, so this package ships one with the mux-video slug and fills in the upstream plugin's setup around it: it reads your Mux API tokens and webhook signing secret from MUX_TOKEN_ID, MUX_TOKEN_SECRET, and MUX_WEBHOOK_SIGNING_SECRET (and warns at startup if the tokens are missing), derives the upload CORS origin from NEXT_PUBLIC_SERVER_URL, and turns on image thumbnails in the admin list view by default.

Using it

In the admin, upload images to the Images collection and favicons to the Favicons collection. Pick a favicon for the site through the FaviconField in the SiteMetaData global. Upload video to the mux-video collection: uploads are pushed to Mux, and the admin list view shows a thumbnail (image, gif, or none, per the adminThumbnail option).

To place media inside Atomic content, editors drop the ImageChild and VideoChild blocks into Atomic blocks. Both render on the front end via @pro-laico/atomic/children: the image child renders a responsive <img> with its low-res placeholder, and the video child streams playback from Mux.

Configuration

Add both plugins to your Payload config:

import { buildConfig } from 'payload'
import { imagesPlugin } from '@pro-laico/images'
import { muxVideoPlugin } from '@pro-laico/mux-video'

export default buildConfig({
  plugins: [imagesPlugin({ enabled: true }), muxVideoPlugin()],
})

Use the favicon picker in a global:

import { FaviconField } from '@pro-laico/images'

const SiteMetaData = {
  slug: 'siteMetaData',
  fields: [
    FaviconField(),
    // ...
  ],
}

imagesPlugin(options?) accepts enabled (no-op the plugin), includeFavicons (register the bundled Favicons collection, default true), transform (configure or disable the on-demand endpoint), focalUI (the focal-point picker, default true), and per-collection overrides (imagesOptions / faviconsOptions / generatedImagesOptions). See the plugin reference for the full list.

muxVideoPlugin(options?) accepts enabled (no-op the plugin), includeCollection (register the bundled mux-video extension collection; disable if you supply your own with the same slug), collectionOptions (override the bundled collection, where top-level keys replace but access/admin are deep-merged, fields are appended, and hooks are merged per phase), adminThumbnail ('image' | 'gif' | 'none', default 'image'), uploadSettings, and initSettings.

Mux credentials and the upload origin are picked up automatically from the environment:

EnvPurpose
NEXT_PUBLIC_SERVER_URLUsed as the cors_origin for Mux uploads. Falls back to http://localhost:3000.
MUX_TOKEN_IDMux API token ID.
MUX_TOKEN_SECRETMux API token secret.
MUX_WEBHOOK_SIGNING_SECRETMux webhook signing secret.

For the full set of options, subpaths, and exports, see the plugin references below.

Provided by

On this page