Display Images in your Payload CMS Admin Collection List with Custom Cell Component
Here’s how to write a cell data component in Payload CMS to get images to appear in your Collection List. Displaying Images on your Payload CMS Admin is as easy as setting the server’s URL. This guide uses a custom component to fetch and render the image. Full source code can be found at: aaronksaunders/payload-custom-cell-image-component-1-2025 Setting Server URL The first thing we need to do is make sure our payload.config.ts knows where to find our URL. // payload.config.ts export default buildConfig({ serverURL: process.env.SERVER_URL || 'http://localhost:3000', Make sure that your server knows where to retrieve media from by putting this into your config, be that from local or from another host, this would be how it gets set. If you dont set this, the url for the media will be incorrect and probably not render properly User List Modifications To make your User List modifications, the first step is to create a new avatar field with a relationship to the Media collection. This is defined within your Users.ts collection configuration: // Users.ts { name: 'avatar', type: 'relationship', relationTo: 'media', admin: { components: { Cell: 'src/collections/CustomImageCell', }, }, }, Important to note that with Payload 3, you now need to specify the full path to the custom cell component, you cannot just import the object like in version 2 Custom Component Creation (CustomImageCell.tsx) // src/collections/CustomImageCell.tsx import React from 'react' import Image from 'next/image' import { type DefaultServerCellComponentProps } from 'payload' const MyComponent = async ({ cellData, payload }: DefaultServerCellComponentProps) => { // thanks to Jarrod for the following simplification, payload // is already available in the props so no need to load config // and get payload again const media = await payload.findByID({ collection: 'media', id: cellData, }) console.log(media) return ( ) } export default MyComponent The CustomImageCell component is a server component that asynchronously fetches the Media object using the payload object that is passed in as a component property. Note the use of Next.js's Image component for optimized image delivery. The component receives the id of the media as a prop and utilizes it to retrieve all the image data. Next JS Config Modification (next.config.js) Lastly, because Next JS can generate an error about the specified URL, it would be useful to add to your remote Patterns. In your next.config.js file, you'll need to configure the remotePatterns array to allow the Image component to load images from your Payload CMS instance. // next.config.js const nextConfig = { // ... other config images: { remotePatterns: [ { protocol: 'http', hostname: 'localhost', port: '3000', pathname: '/media/**', }, ], }, }; module.exports = nextConfig; If the localhost is throwing too many errors, can also modify the .env variable. This configuration allows images to be loaded from localhost port 3000, where Payload CMS is running in development. Adapt the protocol, hostname, and pathname to match your specific setup. You may also be able to utilize the variable, depending on your specific version and setup. Summary: Fetching Media Data: The custom component fetches the media data by ID. Rendering the Image: It then utilizes Next.js to render the image. Links Payload Custom Components Next Image URL Error
Here’s how to write a cell data component in Payload CMS to get images to appear in your Collection List. Displaying Images on your Payload CMS Admin is as easy as setting the server’s URL.
This guide uses a custom component to fetch and render the image. Full source code can be found at: aaronksaunders/payload-custom-cell-image-component-1-2025
Setting Server URL
The first thing we need to do is make sure our payload.config.ts
knows where to find our URL.
// payload.config.ts
export default buildConfig({
serverURL: process.env.SERVER_URL || 'http://localhost:3000',
Make sure that your server knows where to retrieve media from by putting this into your config, be that from local or from another host, this would be how it gets set.
If you dont set this, the url for the media will be incorrect and probably not render properly
User List Modifications
To make your User List modifications, the first step is to create a new avatar
field with a relationship to the Media collection. This is defined within your Users.ts
collection configuration:
// Users.ts
{
name: 'avatar',
type: 'relationship',
relationTo: 'media',
admin: {
components: {
Cell: 'src/collections/CustomImageCell',
},
},
},
Important to note that with Payload 3, you now need to specify the full path to the custom cell component, you cannot just import the object like in version 2
Custom Component Creation (CustomImageCell.tsx)
// src/collections/CustomImageCell.tsx
import React from 'react'
import Image from 'next/image'
import { type DefaultServerCellComponentProps } from 'payload'
const MyComponent = async ({ cellData, payload }: DefaultServerCellComponentProps) => {
// thanks to Jarrod for the following simplification, payload
// is already available in the props so no need to load config
// and get payload again
const media = await payload.findByID({
collection: 'media',
id: cellData,
})
console.log(media)
return (
<div
style={{
position: 'relative',
width: '80px',
height: '80px',
}}
>
<Image
src={media.url!}
alt={media.alt}
fill
style={{
objectFit: 'contain',
}}
/>
</div>
)
}
export default MyComponent
The CustomImageCell
component is a server component that asynchronously fetches the Media object using the payload object that is passed in as a component property. Note the use of Next.js's Image
component for optimized image delivery.
The component receives the id of the media as a prop and utilizes it to retrieve all the image data.
Next JS Config Modification (next.config.js)
Lastly, because Next JS can generate an error about the specified URL, it would be useful to add to your remote Patterns.
In your next.config.js
file, you'll need to configure the remotePatterns
array to allow the Image
component to load images from your Payload CMS instance.
// next.config.js
const nextConfig = {
// ... other config
images: {
remotePatterns: [
{
protocol: 'http',
hostname: 'localhost',
port: '3000',
pathname: '/media/**',
},
],
},
};
module.exports = nextConfig;
If the localhost is throwing too many errors, can also modify the .env variable.
This configuration allows images to be loaded from localhost
port 3000, where Payload CMS is running in development. Adapt the protocol, hostname, and pathname to match your specific setup. You may also be able to utilize the variable, depending on your specific version and setup.
Summary:
- Fetching Media Data: The custom component fetches the media data by
ID
. - Rendering the Image: It then utilizes Next.js to render the image.
Links