Collections
The collections the plugin registers, how to extend your own upload collection, and how images seed natively.
The plugin registers three collections under an Assets admin group: one you upload to, one
that caches what gets generated, and — because options.prewarm
is on by default — the hidden render-profile registry (an explicit prewarm: false drops it).
The upload collections accept PNG, JPEG, WebP, and AVIF. collections.images.options.folders is
on by default, so Payload's own hidden payload-folders collection is registered too.
Collections
images
The source upload, and the only one you touch. It stores the original untouched (no pre-generated
sizes) and keeps Payload's native focal point; every rendered size is produced on demand by
the endpoint and recorded in generated-images. Read
is public; writes are logged-in-admin only.
Fields
Prop
Type
The presetManager UI field renders the Presets & variants panel — the admin surface for the
presets, variantLimit, and variants fields above:
The Presets & variants panel on an image doc, showing preset toggles, the cached-variant list, purge controls, and the variant limit
Hooks
Prop
Type
generated-images
The hidden, durable variant cache that you never touch directly. The transform endpoint writes one
upload doc here per (source, settings, focal) combination, keyed by a unique cacheKey and related
back to its source. It's an upload collection, so each generated variant is stored through whatever
storage adapter you've configured. It's surfaced on images via the variants join and purged by that
collection's change/delete hooks.
Fields
Prop
Type
Hooks: none. Variants are derived and disposable, so the collection carries no revalidation hooks (busting cache tags on every cache-miss create would be pure churn).
Variant reads inherit the source's access policy. generated-images read access requires an
authenticated user AND defers to the source collection's read access, re-rooted through the
source relationship — so a tenant-scoped or owner-only images policy scopes the cached
variants (docs and bytes) automatically. Caveat: a source read access that branches on the
individual doc id can't be re-rooted; in that case supply your own
collections: { generatedImages: { overrides: { access: { read: … } } } }. The transform endpoint
itself always gates on the source's read access.
image-render-profiles
Registered only with prewarm on: the hidden
registry of render profiles the transform endpoint has actually served — one doc per distinct
(ratio, fit, quality, format) shape, carrying an approximate hitCount, a lastSeenAt
(profiles unseen for a while stop being warmed), and a capped per-width observation histogram.
Written only by the endpoint's buffered recorder; read by the prewarm job/CLI. Small by
construction: the endpoint's snap grid and quality buckets bound the distinct-profile space. Like
the variant cache, it carries no revalidation hooks.
Reshape it with collections.renderProfiles, same as the other two. options.prewarm is what
decides whether it exists at all — with options: { prewarm: false } there's no collection for the
key to shape.
Renaming a collection, and adding your own fields
Most projects already call their upload collection media. Rename the one the plugin registers and
add your fields to it — slug is a first-class override, and the plugin repoints every internal
reference at the new name:
imagesPlugin({
collections: {
images: {
slug: 'media',
overrides: { fields: [{ name: 'credit', type: 'text' }] },
},
},
})That registers one collection, media, carrying the whole pipeline (the focal UI, the
variants join, the purge hooks, upload.focalPoint) plus your credit field. The transform
endpoint serves /api/img/:id for media docs, the variant cache's source relationship points at
media, and readImagesMarker(config).sourceSlug reads back 'media'.
The variant cache renames the same way:
imagesPlugin({ collections: { generatedImages: { slug: 'image-variants' } } })slug, overrides, and options — one key each. Every collections.<name> splits the same
way: slug renames it, overrides is a plain Partial<CollectionConfig> (upload, access,
admin, custom shallow-merge over the plugin's, fields and hooks append after them,
defaultPopulate and forceSelect merge as selects, everything else replaces), and options is
the plugin's own knobs for the collection. So a collections.images.options.mimeTypes /
maxOriginalSize and a collections.images.overrides.upload both reach upload — set either, and
the explicit overrides.upload wins. (localizeAlt isn't one of them: it localizes the alt
field, not upload.)
Don't redeclare a field the plugin injects. overrides.fields append, so a field of yours
named alt, variants, placeholder, palette, … is a boot error naming the plugin, the
collections key, and the field — rename yours instead.
Seeding
Because images is a plain Payload upload collection, it seeds natively through
@pro-laico/payload-seed: defineSeed('images', …) with each
record carrying its source file on _file, referenced from a page with ref('images', …):
import { defineSeed, seedPlugin } from '@pro-laico/payload-seed'
import { imagesPlugin } from '@pro-laico/payload-images'
// src/seed/images.ts — focal points drive the on-demand crops from the first serve
const images = defineSeed('images', ({ file }) => [
{ _key: 'hero', _file: file('hero.jpg'), alt: 'Hero', focalX: 78, focalY: 32 },
])
// src/seed/pages.ts — reference a seeded image (an upload-field relationship)
const pages = defineSeed('pages', ({ ref }) => [
{ _key: 'home', title: 'Home', heroImage: ref('images', 'hero') },
])
plugins: [
imagesPlugin(),
seedPlugin({ definitions: [images, pages], options: { assetsDir: 'seed-assets' } }),
]alt, focalX, and focalY are ordinary record fields, type-checked against the collection.
Payload's folders are on by default (collections.images.options.folders) and seed the same way — ordinary docs in the
hidden payload-folders collection, each image referencing its folder like any relationship. See
examples/images-sandbox for a full working
setup, and the payload-seed docs for everything else about seeding.