DEV Community

Aaron K Saunders
Aaron K Saunders

Posted on

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',
Enter fullscreen mode Exit fullscreen mode

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',
    },
  },
},
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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

Top comments (1)

Collapse
 
dansasser profile image
Daniel T Sasser II

How long have you been working with PayloadCMS?