JSTAcademy
0 XP
Dashboard
Crash Courses
Media & Uploads
10 min
PhD+200 XP
Crash Courses · PhD

Media & Uploads

Configure Payload media uploads with transformations and storage adapters.
10 min read+200 XP on completionCert: Payload CMS Crash Course
Tap any word in the text below to start reading from there.

Media & Uploads

Payload handles media uploads, image optimization, and multiple size generation automatically.

Media Collection

// collections/Media.ts
import type { CollectionConfig } from 'payload'

export const Media: CollectionConfig = {
  slug: 'media',
  upload: {
    staticDir: 'public/media',
    staticURL: '/media',
    imageSizes: [
      { name: 'thumbnail', width: 400, height: 300, crop: 'center' },
      { name: 'card', width: 800, height: 500 },
      { name: 'hero', width: 1920, height: 1080 },
    ],
    adminThumbnail: 'thumbnail',
    mimeTypes: ['image/*', 'video/*'],
  },
  fields: [
    {
      name: 'alt',
      type: 'text',
      required: true,
    },
    {
      name: 'caption',
      type: 'text',
    },
  ],
}

S3 Storage Adapter (Vercel)

// payload.config.ts
import { s3Storage } from '@payloadcms/storage-s3'

export default buildConfig({
  plugins: [
    s3Storage({
      collections: { media: true },
      bucket: process.env.S3_BUCKET!,
      config: {
        region: process.env.S3_REGION!,
        credentials: {
          accessKeyId: process.env.S3_ACCESS_KEY!,
          secretAccessKey: process.env.S3_SECRET_KEY!,
        },
      },
    }),
  ],
})

Using Media in Next.js

import Image from 'next/image'
import type { Media } from '@/payload-types'

function MediaImage({ media, size = 'card' }: { media: Media; size?: string }) {
  const url = media.sizes?.[size]?.url ?? media.url!
  const width = media.sizes?.[size]?.width ?? media.width!
  const height = media.sizes?.[size]?.height ?? media.height!

  return (
    <Image
      src={url}
      alt={media.alt}
      width={width}
      height={height}
      className="w-full h-auto rounded-lg"
    />
  )
}
0%