Інтеграція CMS Payload CMS для управління контентом

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Інтеграція CMS Payload CMS для управління контентом
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція CMS Payload CMS для управління контентом

Payload — headless CMS на Node.js з відкритим вихідним кодом. Відрізняється від конкурентів тим, що сам є частиною програми: конфіг пишеться на TypeScript та живе в репозиторії. Жодних зовнішніх дашбордів, жодного vendor lock-in. Це не сервіс — це бібліотека, яку монтуєш в Express або Next.js.

Коли Payload має смисл

Продукт підходить, коли потрібен повний контроль над схемою даних, кастомна аутентифікація, або CMS потрібно вбудувати в наявний backend. Payload не вимагає окремого хостингу — він піднімається там же, де живе API.

Не варто використовувати, якщо команда контент-менеджерів велика та звикла до хмарних CMS з гарантованим аптаймом — тоді Contentful або Prismic простіше.

Структура проекту

my-project/
├── src/
│   ├── payload.config.ts   # головний конфіг
│   ├── collections/        # типи контенту
│   │   ├── Posts.ts
│   │   ├── Users.ts
│   │   └── Media.ts
│   ├── globals/            # singleton-документи
│   │   └── SiteSettings.ts
│   └── server.ts

Конфігурація колекції

// src/collections/Posts.ts
import { CollectionConfig } from 'payload/types'

const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
    defaultColumns: ['title', 'status', 'publishedAt'],
  },
  access: {
    read: ({ req: { user } }) => {
      if (user) return true
      return { status: { equals: 'published' } }
    },
    create: ({ req: { user } }) => Boolean(user?.roles?.includes('editor')),
    update: ({ req: { user } }) => Boolean(user?.roles?.includes('editor')),
  },
  versions: {
    drafts: { autosave: true },
    maxPerDoc: 20,
  },
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'text', unique: true, admin: { position: 'sidebar' } },
    {
      name: 'content',
      type: 'richText',
      editor: lexicalEditor({
        features: ({ defaultFeatures }) => [
          ...defaultFeatures,
          HTMLConverterFeature({}),
        ],
      }),
    },
    {
      name: 'featuredImage',
      type: 'upload',
      relationTo: 'media',
    },
    {
      name: 'status',
      type: 'select',
      options: ['draft', 'published'],
      defaultValue: 'draft',
      admin: { position: 'sidebar' },
    },
    {
      name: 'publishedAt',
      type: 'date',
      admin: { position: 'sidebar', date: { pickerAppearance: 'dayAndTime' } },
    },
  ],
}

export default Posts

Головний конфіг

// src/payload.config.ts
import { buildConfig } from 'payload/config'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import Posts from './collections/Posts'
import Users from './collections/Users'
import Media from './collections/Media'

export default buildConfig({
  serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL,
  admin: {
    user: Users.slug,
    bundler: webpackBundler(),
  },
  editor: lexicalEditor({}),
  collections: [Posts, Users, Media],
  db: mongooseAdapter({ url: process.env.DATABASE_URI! }),
  // або PostgreSQL:
  // db: postgresAdapter({ pool: { connectionString: process.env.DATABASE_URI } }),
  upload: {
    limits: { fileSize: 10_000_000 },
  },
  localization: {
    locales: ['uk', 'en'],
    defaultLocale: 'uk',
    fallback: true,
  },
})

Payload підтримує MongoDB та PostgreSQL через офіційні адаптери. Для PostgreSQL міграції генеруються автоматично:

npx payload migrate:create
npx payload migrate

Інтеграція з Next.js 14

Починаючи з Payload 2.x підтримується монтування в Next.js App Router:

// app/(payload)/admin/[[...segments]]/page.tsx
import { RootPage } from '@payloadcms/next/views'
import config from '@payload-config'

export default RootPage.bind(null, { config })
// app/(payload)/api/[...slug]/route.ts
import { REST_DELETE, REST_GET, REST_PATCH, REST_POST } from '@payloadcms/next/routes'
import config from '@payload-config'

export const GET = REST_GET.bind(null, config)
export const POST = REST_POST.bind(null, config)
export const PATCH = REST_PATCH.bind(null, config)
export const DELETE = REST_DELETE.bind(null, config)

Це означає — один next start, один процес, один деплой.

Запити через Local API

Payload надає Local API для серверного коду — без HTTP-оверхеда:

import payload from 'payload'
import config from '@payload-config'

await payload.init({ config })

const posts = await payload.find({
  collection: 'posts',
  where: {
    status: { equals: 'published' },
    publishedAt: { less_than_equal: new Date().toISOString() },
  },
  sort: '-publishedAt',
  limit: 10,
  depth: 2, // populate пов'язаних документів
})

REST API працює паралельно та доступен зовнішнім клієнтам:

GET /api/posts?where[status][equals]=published&sort=-publishedAt&limit=10

Хуки та розширення

Payload підтримує хуки на рівні колекцій — до/після операцій:

{
  slug: 'posts',
  hooks: {
    beforeChange: [
      async ({ data, operation }) => {
        if (operation === 'create') {
          data.slug = slugify(data.title)
        }
        return data
      },
    ],
    afterChange: [
      async ({ doc }) => {
        await revalidatePath(`/blog/${doc.slug}`)
      },
    ],
  },
}

Кастомні endpoints додаються прямо в колекцію:

endpoints: [
  {
    path: '/:id/publish',
    method: 'post',
    handler: async (req, res) => {
      await payload.update({
        collection: 'posts',
        id: req.params.id,
        data: { status: 'published', publishedAt: new Date() },
      })
      res.json({ message: 'Published' })
    },
  },
],

Медіа та загрузка файлів

const Media: CollectionConfig = {
  slug: 'media',
  upload: {
    staticURL: '/media',
    staticDir: 'media',
    imageSizes: [
      { name: 'thumbnail', width: 400, height: 300, crop: 'centre' },
      { name: 'card', width: 768, height: 1024 },
      { name: 'hero', width: 1920, height: undefined },
    ],
    adminThumbnail: 'thumbnail',
    mimeTypes: ['image/*', 'application/pdf'],
  },
  fields: [{ name: 'alt', type: 'text' }],
}

Для S3 — офіційний плагін @payloadcms/plugin-cloud-storage з адаптером під S3, GCS або Azure.

Терміни

Базова установа з 3–4 колекціями, локалізацією та інтеграцією в Next.js: 5–7 днів. Якщо потрібна кастомна аутентифікація, RBAC, складні хуки — від 2 тижнів.