ابزارها و تکنولوژی‌ها, برنامه‌نویسی وب

Payload CMS چیست؟ آموزش کامل معرفی، نصب و راه‌اندازی Payload CMS

در سال‌های اخیر، معماری توسعه وب به‌سرعت از CMSهای سنتی به سمت Headless CMS و Backendهای API محور حرکت کرده است. در این معماری، بخش مدیریت محتوا از رابط کاربری جدا می‌شود و یک Backend می‌تواند هم‌زمان به وب‌سایت، اپلیکیشن موبایل و سایر سرویس‌ها داده ارائه کند.

در میان ابزارهای جدید این حوزه، Payload CMS به دلیل متن‌باز بودن، استفاده از TypeScript، انعطاف‌پذیری بالا و سازگاری با اکوسیستم مدرن Node.js و Next.js، توجه بسیاری از توسعه‌دهندگان را به خود جلب کرده است.

Payload فقط یک سیستم برای انتشار مقاله و مدیریت محتوا نیست؛ بلکه می‌توان از آن به‌عنوان یک Backend کامل و قابل توسعه برای پروژه‌های مختلف استفاده کرد. مدیریت کاربران، احراز هویت، کنترل سطح دسترسی، ساخت API، مدیریت فایل‌ها، تعریف مدل‌های داده و ایجاد پنل مدیریت تنها بخشی از امکاناتی هستند که Payload در اختیار توسعه‌دهنده قرار می‌دهد.

برای مثال، تصور کنید قصد دارید یک پلتفرم آموزشی ایجاد کنید. در این پروژه می‌توانید دوره‌ها، درس‌ها، مدرس‌ها، کاربران، مقالات، تصاویر و سایر اطلاعات را در Payload مدیریت کنید و سپس همان Backend را در اختیار وب‌سایت Next.js و اپلیکیشن‌های Android و iOS یا Flutter قرار دهید.

در این مقاله از آموزنگار، Payload CMS را از پایه بررسی می‌کنیم؛ ابتدا با مفهوم Headless CMS و قابلیت‌های Payload آشنا می‌شویم، سپس نحوه نصب و راه‌اندازی آن را یاد می‌گیریم و در ادامه به سراغ ساخت Collection، اتصال PostgreSQL، ایجاد API، مدیریت کاربران و فایل‌ها، کنترل دسترسی و در نهایت اجرای Payload در محیط Production می‌رویم.

Payload CMS چیست؟

Payload CMS یک سیستم مدیریت محتوای مدرن، متن‌باز و Headless است که با تمرکز بر نیازهای توسعه‌دهندگان ساخته شده است. این CMS بر پایه TypeScript، Node.js، React و Next.js توسعه یافته و به شما اجازه می‌دهد علاوه بر مدیریت محتوا، یک Backend قابل توسعه برای پروژه‌های مختلف ایجاد کنید. در Payload می‌توانید ساختار داده‌های خود را به‌صورت کاملاً سفارشی تعریف کنید و برای بخش‌هایی مانند مقالات، کاربران، محصولات، دوره‌های آموزشی، دسته‌بندی‌ها و فایل‌های رسانه‌ای Collection ایجاد کنید.

برخلاف CMSهای سنتی که معمولاً مدیریت محتوا و رابط کاربری وب‌سایت به یکدیگر وابسته هستند، Payload رویکرد Headless CMS دارد؛ یعنی Backend و Frontend از یکدیگر جدا هستند. به همین دلیل یک پروژه Payload می‌تواند داده‌ها را از طریق API در اختیار وب‌سایت، اپلیکیشن Android، iOS، Flutter یا سایر سرویس‌ها قرار دهد. این ویژگی Payload را برای پروژه‌هایی که قرار است روی چند پلتفرم اجرا شوند، بسیار کاربردی می‌کند.

Payload CMS

Payload CMS

یکی از نقاط قوت Payload، انعطاف‌پذیری بالای آن است. توسعه‌دهنده می‌تواند با استفاده از TypeScript مدل‌های داده، API، احراز هویت، سطح دسترسی کاربران، مدیریت فایل‌ها، ارتباط بین موجودیت‌ها و منطق اختصاصی پروژه را کنترل کند. به همین دلیل Payload را می‌توان تنها یک CMS ساده در نظر نگرفت؛ بلکه می‌توان از آن به‌عنوان یک Backend و پنل مدیریت کامل برای ساخت پروژه‌های مدرن استفاده کرد.

برای مثال، در یک پلتفرم آموزشی می‌توان اطلاعات دوره‌ها، درس‌ها، مدرس‌ها، کاربران، مقالات، دسته‌بندی‌ها و فایل‌های آموزشی را در Payload مدیریت کرد و سپس همین اطلاعات را از طریق API در اختیار وب‌سایت Next.js و اپلیکیشن‌های موبایل قرار داد. این معماری باعث می‌شود مدیریت محتوا از رابط کاربری مستقل باشد و توسعه هر Client بدون نیاز به تغییر اساسی در Backend انجام شود.

به عنوان مثال می‌توان معماری زیر را در نظر گرفت:

                Payload CMS
                     │
          ┌──────────┼──────────┐
          │          │          │
        REST       GraphQL      API
          │          │          │
          └──────────┼──────────┘
                     │
              Frontend / Apps
          ┌──────────┼──────────┐
          │          │          │
       Next.js     Flutter    Android

در این معماری Payload وظیفه مدیریت داده‌ها و API را بر عهده دارد و Frontend می‌تواند با استفاده از API اطلاعات مورد نیاز خود را دریافت کند.

چرا Payload CMS اهمیت دارد؟

اهمیت Payload CMS در این است که نیازهای CMS و Backend مدرن را در یک پلتفرم انعطاف‌پذیر و قابل توسعه ترکیب می‌کند. در بسیاری از پروژه‌های امروزی، دیگر یک وب‌سایت تنها Client سیستم نیست و ممکن است هم‌زمان یک وب‌سایت، اپلیکیشن موبایل، پنل مدیریتی و سرویس‌های مختلف به یک Backend مشترک متصل باشند. Payload با معماری Headless خود این امکان را فراهم می‌کند که محتوا و داده‌ها در یک Backend مرکزی مدیریت شده و از طریق API در اختیار Clientهای مختلف قرار بگیرند.

از طرف دیگر، Payload برای توسعه‌دهندگانی که با JavaScript و TypeScript کار می‌کنند، تجربه توسعه مناسبی فراهم می‌کند. ساختار پروژه، تعریف Collectionها، مدیریت کاربران، کنترل دسترسی، Hooks و بسیاری از تنظیمات سیستم را می‌توان با TypeScript انجام داد. این موضوع باعث می‌شود توسعه‌دهنده برخلاف CMSهای سنتی، کنترل بیشتری روی معماری و منطق Backend داشته باشد و بتواند سیستم را متناسب با نیازهای پروژه سفارشی کند.

Payload همچنین به دلیل سازگاری با اکوسیستم Node.js، React و Next.js برای ساخت پروژه‌های Full-stack مدرن گزینه جذابی است. می‌توان یک Backend را ایجاد کرد که هم برای یک وب‌سایت Next.js و هم برای اپلیکیشن‌های Android، iOS یا Flutter مورد استفاده قرار گیرد. بنابراین به جای ساخت چند Backend جداگانه برای پلتفرم‌های مختلف، می‌توان یک لایه مرکزی برای مدیریت داده‌ها و محتوا ایجاد کرد.

برخی از مهم‌ترین ویژگی‌های آن عبارت‌اند از:

  • متن‌باز بودن
  • استفاده از TypeScript
  • پنل مدیریت قدرتمند
  • پشتیبانی از REST API
  • پشتیبانی از GraphQL
  • مدیریت کاربران
  • احراز هویت
  • کنترل سطح دسترسی
  • مدیریت فایل و Media
  • قابلیت تعریف Collection
  • قابلیت تعریف رابطه بین داده‌ها
  • Hooks
  • امکان سفارشی‌سازی Admin Panel
  • پشتیبانی از دیتابیس‌های مدرن
  • مناسب برای پروژه‌های Full-stack
  • قابلیت استفاده در کنار Next.js

Headless CMS چیست؟

Headless CMS یا «سیستم مدیریت محتوای بدون سر» نوعی سیستم مدیریت محتوا است که بخش مدیریت محتوا و Backend را از بخش نمایش محتوا یا Frontend جدا می‌کند. در یک CMS سنتی، معمولاً سیستم مدیریت محتوا، دیتابیس و رابط کاربری وب‌سایت به یکدیگر وابسته هستند؛ اما در معماری Headless، CMS بیشتر نقش یک Backend را ایفا می‌کند و محتوا را از طریق API در اختیار Frontendهای مختلف قرار می‌دهد.

برای مثال، فرض کنید یک سایت آموزشی دارید و اطلاعات دوره‌ها، درس‌ها، مقالات و کاربران در یک Headless CMS ذخیره شده‌اند. وب‌سایت می‌تواند این اطلاعات را از طریق API دریافت کند، اما همین API می‌تواند هم‌زمان در اختیار اپلیکیشن Android، اپلیکیشن iOS یا اپلیکیشن Flutter نیز قرار بگیرد. در نتیجه، یک منبع مرکزی برای مدیریت محتوا خواهید داشت و لازم نیست برای هر پلتفرم یک سیستم مدیریت محتوای جداگانه ایجاد کنید.

در یک CMS سنتی معماری معمولاً به شکل زیر است:

CMS
 │
 ├── Database
 ├── Admin Panel
 └── Frontend

اما در Headless CMS ساختار متفاوت است:

             Headless CMS
                  │
              Database
                  │
                  ▼
                 API
                  │
        ┌─────────┼─────────┐
        │         │         │
     Website    Android   Flutter

این جداسازی باعث می‌شود توسعه‌دهنده آزادی بیشتری در انتخاب تکنولوژی Frontend داشته باشد. برای مثال می‌توان از Next.js، React، Vue، Angular یا Flutter استفاده کرد، بدون اینکه Backend مجبور باشد به یک تکنولوژی خاص برای نمایش محتوا وابسته باشد.

یکی از مهم‌ترین مزایای Headless CMS همین انعطاف‌پذیری و قابلیت استفاده مجدد از محتوا است. برای مثال یک مقاله آموزشی که در Payload CMS ایجاد شده است، می‌تواند هم در وب‌سایت نمایش داده شود و هم در اپلیکیشن موبایل یا سایر سرویس‌های متصل به API مورد استفاده قرار گیرد.

در واقع می‌توان گفت در معماری Headless، CMS مسئول مدیریت و ارائه محتوا است و Frontend مسئول نمایش و تجربه کاربری. همین جداسازی، Headless CMS را به گزینه‌ای مناسب برای پروژه‌های مدرن، چندپلتفرمی و قابل توسعه تبدیل کرده است.

Payload CMS با چه تکنولوژی‌هایی ساخته شده است؟

Payload CMS بر پایه تکنولوژی‌های مدرن وب و اکوسیستم JavaScript و TypeScript ساخته شده است و همین موضوع یکی از دلایل محبوبیت آن در میان توسعه‌دهندگان است. هسته اصلی Payload با TypeScript توسعه داده شده و روی محیط اجرای Node.js اجرا می‌شود. استفاده از TypeScript باعث می‌شود توسعه‌دهنده هنگام تعریف ساختار داده‌ها، Collectionها، دسترسی‌ها و منطق برنامه از قابلیت‌هایی مانند Type Safety و تکمیل خودکار کد بهره‌مند شود.

Payload همچنین ارتباط نزدیکی با React و Next.js دارد. پنل مدیریت Payload با React ساخته شده و Payload می‌تواند در کنار Next.js برای ایجاد پروژه‌های Full-stack مورد استفاده قرار بگیرد. این ترکیب به توسعه‌دهنده اجازه می‌دهد Backend، CMS، API و رابط کاربری پروژه را در یک اکوسیستم مدرن و مبتنی بر TypeScript توسعه دهد.

از طرف دیگر، Payload از دیتابیس‌های رابطه‌ای و سایر گزینه‌های ذخیره‌سازی پشتیبانی می‌کند و می‌توان آن را به دیتابیس‌هایی مانند PostgreSQL متصل کرد. PostgreSQL برای پروژه‌های Production و سیستم‌هایی که داده‌های ساختاریافته و ارتباط بین موجودیت‌های مختلف دارند، انتخاب مناسبی است.

به‌صورت خلاصه، تکنولوژی‌های اصلی مورد استفاده در اکوسیستم Payload را می‌توان به شکل زیر در نظر گرفت:

Payload CMS
     │
     ├── TypeScript
     ├── Node.js
     ├── React
     ├── Next.js
     ├── PostgreSQL
     └── REST / GraphQL API

این ترکیب باعث شده Payload برای توسعه‌دهندگانی که با TypeScript، Node.js، React و Next.js کار می‌کنند، تجربه‌ای یکپارچه ایجاد کند و بتوان از آن برای ساخت CMS، Backend اختصاصی، API و پلتفرم‌های چندپلتفرمی استفاده کرد.

Collection در Payload چیست؟

Collection یکی از مفاهیم اصلی در Payload CMS است و برای تعریف و مدیریت مجموعه‌ای از داده‌های مرتبط با یک موجودیت مشخص استفاده می‌شود. اگر بخواهیم ساده توضیح دهیم، Collection در Payload تقریباً نقش یک مدل داده یا Entity را در پروژه ایفا می‌کند. برای مثال، در یک سایت آموزشی می‌توان برای کاربران، دوره‌ها، درس‌ها، مقالات، مدرس‌ها و دسته‌بندی‌ها Collectionهای جداگانه ایجاد کرد.

هر Collection مشخص می‌کند که داده‌های آن موجودیت چه ساختاری داشته باشند، چه فیلدهایی در آنها وجود داشته باشد، چه اطلاعاتی اجباری باشند، چه کاربرانی بتوانند آنها را مشاهده یا ویرایش کنند و چه ارتباطی با سایر Collectionها داشته باشند. به همین دلیل Collection تنها یک جدول ساده در دیتابیس نیست و می‌تواند بخشی از منطق و قوانین مربوط به مدیریت داده را نیز در خود تعریف کند.

برای مثال، فرض کنید می‌خواهیم برای مقالات یک سایت آموزشی Collection ایجاد کنیم. این Collection می‌تواند شامل فیلدهایی مانند عنوان، Slug، خلاصه، متن مقاله، تصویر، نویسنده و دسته‌بندی باشد:

Posts
│
├── title
├── slug
├── excerpt
├── content
├── image
├── author
└── category

در Payload، این ساختار را می‌توان با TypeScript تعریف کرد:

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',

  admin: {
    useAsTitle: 'title',
  },

  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'slug',
      type: 'text',
      required: true,
      unique: true,
    },
    {
      name: 'content',
      type: 'richText',
    },
  ],
}

بعد از تعریف Collection، Payload به‌صورت خودکار امکانات لازم برای مدیریت این داده‌ها را در اختیار شما قرار می‌دهد. برای مثال می‌توانید از طریق پنل مدیریت، رکوردهای جدید ایجاد کنید، آنها را ویرایش یا حذف کنید و از طریق API به اطلاعات آنها دسترسی داشته باشید.

یکی از قابلیت‌های مهم Collectionها، امکان ایجاد Relationship بین داده‌هاست. برای مثال هر مقاله می‌تواند به یک دسته‌بندی و یک نویسنده متصل باشد و هر دوره آموزشی نیز می‌تواند شامل چندین درس باشد:

Course
 │
 ├── Category
 ├── Teacher
 └── Lessons
       │
       ├── Lesson 1
       ├── Lesson 2
       └── Lesson 3

بنابراین می‌توان گفت Collectionها ستون اصلی مدل‌سازی داده در Payload هستند. با استفاده از آنها می‌توان ساختار یک پروژه را از یک CMS ساده تا یک پلتفرم آموزشی، فروشگاه اینترنتی، سیستم SaaS یا Backend یک اپلیکیشن موبایل طراحی و توسعه داد.

پیش‌نیازهای نصب Payload CMS

برای نصب و راه‌اندازی Payload CMS به محیطی نیاز دارید که بتواند برنامه‌های مبتنی بر Node.js و TypeScript را اجرا کند. خوشبختانه برای شروع کار، پیش‌نیازهای Payload پیچیده نیستند و می‌توانید ابتدا آن را روی سیستم شخصی خود نصب و آزمایش کنید و پس از آماده شدن پروژه، آن را روی یک سرور Production مستقر کنید.

مهم‌ترین پیش‌نیاز، نصب Node.js است؛ زیرا Payload روی Node.js اجرا می‌شود. در کنار Node.js به یک Package Manager مانند npm، pnpm یا Yarn نیز نیاز دارید. همچنین داشتن Git برای مدیریت نسخه‌های پروژه و یک ویرایشگر کد مانند Visual Studio Code توصیه می‌شود.

برای توسعه محلی، در ساده‌ترین حالت می‌توانید پروژه را بدون نصب جداگانه دیتابیس نیز شروع کنید و از تنظیمات دیتابیس متناسب با Template پروژه استفاده کنید. اما برای یک پروژه واقعی و محیط Production، بهتر است از یک دیتابیس پایدار مانند PostgreSQL استفاده کنید. در این حالت باید PostgreSQL روی سیستم یا سرور شما نصب و یک Database و User مناسب برای پروژه ایجاد شده باشد.

به‌صورت کلی، محیط توسعه شما می‌تواند شامل موارد زیر باشد:

Development Environment
│
├── Node.js
├── npm / pnpm
├── Git
├── VS Code
└── Database
     └── PostgreSQL

اگر قصد دارید Payload CMS را روی سرور اجرا کنید، علاوه بر موارد بالا معمولاً به ابزارهای دیگری مانند Nginx، PM2، SSL و یک دامنه نیز نیاز خواهید داشت. همچنین برای پروژه‌های Production بهتر است از ابتدا برای Backup دیتابیس، ذخیره‌سازی فایل‌ها، امنیت سرور و مدیریت Environment Variables برنامه‌ریزی کنید.

قبل از شروع نصب نیز پیشنهاد می‌شود نسخه Node.js مورد نیاز نسخه Payload مورد استفاده را بررسی کنید؛ زیرا حداقل نسخه‌های مورد نیاز ممکن است با انتشار نسخه‌های جدید Payload تغییر کنند.

نصب Payload CMS

نصب Payload CMS در نسخه‌های جدید بسیار ساده شده است و می‌توان یک پروژه جدید را با استفاده از ابزار رسمی ایجاد پروژه راه‌اندازی کرد. برای شروع، ابتدا مطمئن شوید که Node.js و یکی از Package Managerهای مورد نیاز مانند npm یا pnpm روی سیستم شما نصب است. سپس با استفاده از Terminal یا Command Prompt می‌توانید پروژه جدید Payload را ایجاد کنید.

ساده‌ترین روش برای ایجاد پروژه جدید استفاده از دستور زیر است:

npx create-payload-app

پس از اجرای دستور، ابزار ایجاد پروژه از شما اطلاعاتی مانند نام پروژه، Template و تنظیمات مربوط به دیتابیس را دریافت می‌کند. می‌توانید بر اساس نیاز پروژه گزینه‌های موردنظر خود را انتخاب کنید. برای مثال، اگر قصد دارید یک CMS برای یک پروژه آموزشی ایجاد کنید، می‌توانید نامی مانند education-cms برای پروژه انتخاب کنید.

پس از پایان فرآیند ایجاد پروژه، وارد پوشه پروژه شوید:

cd education-cms

در صورتی که وابستگی‌ها به‌صورت خودکار نصب نشده باشند، آنها را با دستور زیر نصب کنید:

npm install

سپس برای اجرای پروژه در محیط Development از دستور زیر استفاده کنید:

npm run dev

پس از اجرای موفق پروژه، Payload در محیط توسعه اجرا می‌شود و می‌توانید پنل مدیریت آن را از طریق آدرس محلی پروژه در مرورگر باز کنید. در این مرحله معمولاً می‌توانید اولین کاربر Admin را ایجاد کرده و وارد پنل مدیریت شوید.

ساختار کلی فرآیند نصب به شکل زیر است:

Node.js
   │
   ▼
create-payload-app
   │
   ▼
Create Project
   │
   ▼
Install Dependencies
   │
   ▼
Configure Database
   │
   ▼
npm run dev
   │
   ▼
Payload Admin Panel

ایجاد پروژه با نام مشخص

در صورت پشتیبانی نسخه مورد استفاده از ایجاد نام پروژه به‌صورت مستقیم، می‌توانید نام پروژه را نیز در دستور وارد کنید:

npx create-payload-app education-cms

با این حال، گزینه‌ها و Syntax دستور ایجاد پروژه ممکن است در نسخه‌های مختلف Payload تغییر کند؛ بنابراین بهتر است هنگام نصب، راهنمای نسخه‌ای که استفاده می‌کنید را نیز بررسی کنید.

نصب Payload در یک پروژه موجود

اگر از قبل یک پروژه Next.js یا یک پروژه Node.js دارید، می‌توانید Payload را به همان پروژه اضافه کنید. در این روش برخلاف create-payload-app، وابستگی‌های موردنیاز را به‌صورت دستی نصب و سپس Configuration مربوط به Payload را به پروژه اضافه می‌کنید.

این روش زمانی کاربرد دارد که بخواهید Payload را در معماری موجود پروژه خود ادغام کنید؛ برای مثال یک پروژه Next.js + Payload + PostgreSQL که در آن Frontend، CMS و Backend در یک معماری یکپارچه قرار دارند.

در ادامه مقاله، ساختار پروژه Payload، فایل Configuration، اتصال به PostgreSQL و نحوه ایجاد اولین Collection را بررسی خواهیم کرد.

ساختار پروژه Payload

بعد از ایجاد یک پروژه Payload CMS، با یک ساختار پروژه مبتنی بر TypeScript و Next.js روبه‌رو می‌شوید. محل دقیق برخی فایل‌ها و پوشه‌ها ممکن است بر اساس نسخه Payload و Template انتخاب‌شده متفاوت باشد، اما بخش‌های اصلی پروژه معمولاً مسئولیت‌های مشخصی دارند. آشنایی با این ساختار به شما کمک می‌کند بدانید Configuration، Collectionها، صفحات Admin، API و منطق اختصاصی پروژه را در کدام قسمت قرار دهید.

یک ساختار معمول می‌تواند به شکل زیر باشد:

my-payload-app/
│
├── src/
│   ├── app/
│   │   ├── (frontend)/
│   │   └── (payload)/
│   │
│   ├── collections/
│   │   ├── Users.ts
│   │   ├── Posts.ts
│   │   └── Media.ts
│   │
│   ├── access/
│   ├── hooks/
│   ├── components/
│   └── payload.config.ts
│
├── public/
├── package.json
├── tsconfig.json
├── next.config.mjs
└── .env

پوشه src معمولاً محل اصلی کدهای پروژه است. Collectionهای پروژه را می‌توان در پوشه‌ای مانند collections قرار داد. برای مثال در یک سایت آموزشی می‌توان Collectionهای Users، Courses، Lessons، Posts و Media را در این بخش تعریف کرد. هر Collection ساختار داده، فیلدها، تنظیمات Admin، سطح دسترسی و در صورت نیاز Hookهای مربوط به خود را مشخص می‌کند.

فایل payload.config.ts یکی از مهم‌ترین فایل‌های پروژه است و Configuration اصلی Payload در آن قرار می‌گیرد. در این فایل می‌توانید Collectionها، دیتابیس، Admin Panel، Pluginها، Localization و سایر تنظیمات اصلی سیستم را تعریف کنید. به همین دلیل می‌توان آن را یکی از فایل‌های مرکزی پروژه Payload دانست.

برای مثال، یک Configuration ساده می‌تواند چیزی شبیه این باشد:

import { buildConfig } from 'payload'

export default buildConfig({
  collections: [],
})

پوشه app مربوط به ساختار Next.js است و در پروژه‌های جدید Payload معمولاً بخش‌هایی از مسیرهای مربوط به پنل مدیریت و Frontend در آن قرار می‌گیرند. این موضوع یکی از تفاوت‌های مهم Payload با CMSهای سنتی است؛ زیرا Payload می‌تواند در کنار Next.js قرار بگیرد و بخش CMS و Frontend را در یک پروژه مدیریت کند.

پوشه access معمولاً برای نگهداری توابع مربوط به Access Control استفاده می‌شود. برای مثال می‌توان مشخص کرد که چه کاربری اجازه ایجاد، مشاهده، ویرایش یا حذف یک رکورد را داشته باشد. این جداسازی باعث می‌شود قوانین دسترسی پروژه مرتب‌تر و قابل استفاده مجدد باشند.

پوشه hooks نیز می‌تواند محل نگهداری Hooks اختصاصی پروژه باشد. Hooks به شما اجازه می‌دهند در مراحل مختلف عملیات روی داده‌ها، منطق دلخواه خود را اجرا کنید؛ برای مثال قبل یا بعد از ایجاد، ویرایش یا حذف یک رکورد.

فایل .env نیز برای نگهداری اطلاعات حساس و تنظیمات محیطی استفاده می‌شود. اطلاعاتی مانند Connection String دیتابیس و Secret مربوط به Payload نباید مستقیماً داخل کد پروژه قرار بگیرند.

برای مثال:

DATABASE_URL=postgresql://username:password@localhost:5432/mydatabase
PAYLOAD_SECRET=your-secret

در نهایت فایل package.json وابستگی‌های پروژه و Scriptهای مربوط به اجرای آن را مشخص می‌کند. برای مثال می‌توان Scriptهایی مانند dev، build و start را در آن مشاهده کرد.

فایل payload.config.ts چیست؟

فایل payload.config.ts یکی از مهم‌ترین فایل‌های هر پروژه Payload CMS است و تنظیمات اصلی سیستم در آن تعریف می‌شود. این فایل با استفاده از TypeScript نوشته می‌شود و به Payload می‌گوید پروژه چگونه پیکربندی شود؛ از جمله اینکه چه Collectionهایی وجود دارند، از چه دیتابیسی استفاده شود، پنل مدیریت چگونه تنظیم شود، چه Pluginهایی فعال باشند و چه قابلیت‌هایی در اختیار سیستم قرار بگیرد.

به بیان ساده، می‌توان payload.config.ts را مرکز تنظیمات Payload CMS در نظر گرفت. هر زمان که بخواهید ساختار اصلی CMS را تغییر دهید، معمولاً یکی از اولین فایل‌هایی که باید بررسی کنید همین فایل است.

یک Configuration ساده می‌تواند به شکل زیر باشد:

import { buildConfig } from 'payload'

export default buildConfig({
  collections: [],
})

در این مثال، تابع buildConfig Configuration اصلی Payload را ایجاد می‌کند. یکی از مهم‌ترین بخش‌های این Configuration، تعریف Collectionهاست. برای مثال اگر Collectionهای کاربران، مقالات و فایل‌های رسانه‌ای را در پروژه داشته باشیم، می‌توان آنها را در Configuration معرفی کرد:

import { buildConfig } from 'payload'

import { Users } from './collections/Users'
import { Posts } from './collections/Posts'
import { Media } from './collections/Media'

export default buildConfig({
  collections: [
    Users,
    Posts,
    Media,
  ],
})

یکی دیگر از بخش‌های مهم payload.config.ts تنظیم Database است. برای مثال اگر پروژه از PostgreSQL استفاده کند، Adapter مربوط به PostgreSQL در همین Configuration تنظیم می‌شود:

import { buildConfig } from 'payload'
import { postgresAdapter } from '@payloadcms/db-postgres'

export default buildConfig({
  db: postgresAdapter({
    pool: {
      connectionString: process.env.DATABASE_URL,
    },
  }),

  collections: [],
})

علاوه بر Collection و Database، تنظیمات دیگری مانند Admin Panel، Authentication، Access Control، Plugins، Localization، Editor و Upload نیز می‌توانند در Configuration پروژه قرار بگیرند.

برای مثال، ساختار کلی یک Configuration می‌تواند چیزی شبیه این باشد:

payload.config.ts
│
├── Admin Panel
├── Collections
├── Database
├── Authentication
├── Access Control
├── Plugins
├── Localization
├── Editor
└── Upload

نکته مهم این است که payload.config.ts نباید به محلی برای قرار دادن تمام منطق برنامه تبدیل شود. بهتر است Collectionها، Access Controlها و Hooks در فایل‌های جداگانه تعریف شوند و سپس در Configuration اصلی وارد شوند. این روش باعث می‌شود پروژه با افزایش تعداد Collectionها و قابلیت‌ها همچنان منظم، قابل نگهداری و قابل توسعه باقی بماند.

راه‌اندازی PostgreSQL

برای پروژه‌های واقعی Payload CMS، انتخاب یک دیتابیس مناسب اهمیت زیادی دارد. PostgreSQL یکی از گزینه‌های مناسب برای Payload است و می‌توان از آن برای ذخیره اطلاعات کاربران، مقالات، دوره‌ها، محصولات، دسته‌بندی‌ها و سایر داده‌های ساختاریافته استفاده کرد. در این معماری، Payload وظیفه مدیریت داده‌ها و ارائه API را بر عهده دارد و PostgreSQL داده‌های پروژه را ذخیره می‌کند.

معماری کلی سیستم به این شکل است:

                    Payload CMS
                         │
                         ▼
                    PostgreSQL
                         │
        ┌────────────────┼────────────────┐
        │                │                │
      Users            Posts           Courses

نصب PostgreSQL

اگر PostgreSQL را روی سیستم توسعه نصب نکرده‌اید، ابتدا باید آن را نصب کنید. روش نصب بسته به سیستم‌عامل متفاوت است. برای مثال در توزیع‌های Linux مبتنی بر RHEL مانند AlmaLinux و Rocky Linux می‌توانید از Package Manager سیستم استفاده کنید:

sudo dnf install postgresql-server postgresql

سپس دیتابیس را مقداردهی اولیه کنید:

sudo postgresql-setup --initdb

سرویس PostgreSQL را فعال و اجرا کنید:

sudo systemctl enable --now postgresql

برای بررسی وضعیت سرویس:

sudo systemctl status postgresql

دستورات نصب ممکن است با توجه به نسخه PostgreSQL و توزیع Linux متفاوت باشند. در محیط Production بهتر است نسخه‌ای را انتخاب کنید که با نسخه Payload و Adapter مورد استفاده شما سازگار باشد.

ایجاد Database و User

پس از نصب PostgreSQL بهتر است برای پروژه Payload یک Database و User اختصاصی ایجاد کنید. وارد محیط PostgreSQL شوید:

sudo -u postgres psql

سپس یک کاربر ایجاد کنید:

CREATE USER payloaduser WITH PASSWORD 'strong-password';

یک Database برای پروژه بسازید:

CREATE DATABASE payloaddb OWNER payloaduser;

در نهایت می‌توانید از PostgreSQL خارج شوید:

\q

اکنون ساختار دیتابیس شما می‌تواند به شکل زیر باشد:

PostgreSQL
│
└── payloaddb
     │
     ├── Users
     ├── Posts
     ├── Categories
     ├── Courses
     └── Media

نصب PostgreSQL Adapter در Payload

برای اتصال Payload به PostgreSQL باید Adapter مربوط به PostgreSQL را به پروژه اضافه کنید:

npm install @payloadcms/db-postgres

سپس در payload.config.ts آن را تنظیم کنید:

import { buildConfig } from 'payload'
import { postgresAdapter } from '@payloadcms/db-postgres'

export default buildConfig({
  db: postgresAdapter({
    pool: {
      connectionString: process.env.DATABASE_URL,
    },
  }),

  collections: [],
})

در این Configuration، مقدار DATABASE_URL از Environment Variable خوانده می‌شود. بنابراین اطلاعات اتصال دیتابیس را مستقیماً داخل کد پروژه قرار نمی‌دهیم.

تنظیم فایل .env

در فایل .env پروژه، Connection String مربوط به PostgreSQL را قرار دهید:

DATABASE_URL=postgresql://payloaduser:strong-password@localhost:5432/payloaddb

ساختار این Connection String به شکل زیر است:

postgresql://USER:PASSWORD@HOST:PORT/DATABASE

بنابراین در مثال بالا:

User:     payloaduser
Password: strong-password
Host:     localhost
Port:     5432
Database: payloaddb

بعد از تنظیم دیتابیس و Configuration، پروژه Payload را اجرا کنید:

npm run dev

Payload می‌تواند با استفاده از Connection String به PostgreSQL متصل شود و ساختار مورد نیاز دیتابیس را مدیریت کند.

PostgreSQL در محیط Production

در محیط Production بهتر است PostgreSQL را با ملاحظات امنیتی بیشتری راه‌اندازی کنید. دیتابیس نباید بدون دلیل روی اینترنت عمومی در دسترس باشد و بهتر است دسترسی آن فقط از سرور یا سرویس‌هایی که واقعاً به دیتابیس نیاز دارند امکان‌پذیر باشد.

همچنین توصیه می‌شود برای PostgreSQL موارد زیر را از ابتدا در نظر بگیرید:

  • Backup منظم
  • مدیریت صحیح کاربران و دسترسی‌ها
  • استفاده از Password قوی
  • محدود کردن دسترسی شبکه
  • Monitoring
  • نگهداری امن اطلاعات اتصال
  • تست فرآیند Restore

در یک معماری Production معمولی، PostgreSQL می‌تواند روی همان سرور Payload یا روی یک سرور/سرویس دیتابیس جداگانه قرار داشته باشد:

                   Internet
                       │
                       ▼
                 Nginx / Cloudflare
                       │
                       ▼
                  Payload CMS
                       │
                       ▼
                  PostgreSQL

برای پروژه‌های بزرگ‌تر نیز می‌توان دیتابیس را از سرور Application جدا کرد تا مدیریت، مقیاس‌پذیری و نگهداری زیرساخت ساده‌تر شود.

ساخت اولین Collection

فرض کنید قصد داریم یک CMS برای یک سایت آموزشی ایجاد کنیم.

ابتدا Collection مربوط به مقاله را ایجاد می‌کنیم.

مثلاً:

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',

  admin: {
    useAsTitle: 'title',
  },

  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'slug',
      type: 'text',
      required: true,
      unique: true,
    },
    {
      name: 'excerpt',
      type: 'textarea',
    },
    {
      name: 'content',
      type: 'richText',
    },
  ],
}

حالا Collection مقاله دارای فیلدهای زیر خواهد بود:

title
slug
excerpt
content

ایجاد Category

برای مدیریت دسته‌بندی مقالات می‌توانیم Collection دیگری ایجاد کنیم.

export const Categories: CollectionConfig = {
  slug: 'categories',

  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'slug',
      type: 'text',
      required: true,
      unique: true,
    },
  ],
}

ایجاد رابطه بین Collection ها

یکی از قابلیت‌های مهم Payload امکان ایجاد Relationship بین داده‌هاست.

برای مثال هر مقاله می‌تواند به یک دسته‌بندی متصل باشد.

{
  name: 'category',
  type: 'relationship',
  relationTo: 'categories',
  required: true,
}

در نتیجه ساختار داده می‌تواند به شکل زیر باشد:

Post
 │
 ├── title
 ├── content
 └── category
          │
          ▼
      Category

این قابلیت برای پروژه‌های پیچیده بسیار کاربردی است.

مدیریت کاربران

Payload می‌تواند برای مدیریت کاربران نیز استفاده شود.

برای این کار Collection مربوط به User را به عنوان Auth Collection تعریف می‌کنیم.

نمونه:

export const Users: CollectionConfig = {
  slug: 'users',

  auth: true,

  fields: [
    {
      name: 'name',
      type: 'text',
    },
  ],
}

با فعال کردن Authentication، Payload امکانات مرتبط با ورود و مدیریت کاربران را در اختیار پروژه قرار می‌دهد.

پنل مدیریت Payload

یکی از مهم‌ترین قابلیت‌های Payload CMS، پنل مدیریت یا Admin Panel آن است. این پنل یک رابط کاربری تحت وب در اختیار مدیران و کاربران مجاز سیستم قرار می‌دهد تا بتوانند بدون نیاز به کار مستقیم با دیتابیس، محتوا و داده‌های پروژه را مدیریت کنند. برخلاف بسیاری از CMSهای سنتی، پنل مدیریت Payload به ساختار Collectionهایی که در پروژه تعریف کرده‌اید متصل است و با تغییر مدل داده‌ها، امکانات مدیریتی متناسب با آنها در اختیار شما قرار می‌گیرد.

پنل مدیریت Payload

پنل مدیریت Payload

پس از راه‌اندازی پروژه و اجرای آن در محیط Development، می‌توانید مسیر Admin Panel را در مرورگر باز کنید. در پروژه‌های استاندارد Payload این مسیر معمولاً به شکل زیر است:

http://localhost:3000/admin

در اولین ورود، در صورتی که Collection مربوط به کاربران با قابلیت Authentication تنظیم شده باشد، می‌توانید حساب کاربری مدیر را ایجاد کرده و وارد پنل شوید.

پس از ورود، بسته به Collectionهای تعریف‌شده در پروژه، پنل مدیریت می‌تواند بخش‌هایی مانند موارد زیر را نمایش دهد:

Payload Admin
│
├── Users
├── Posts
├── Categories
├── Courses
├── Lessons
├── Media
└── Settings

برای مثال اگر Collection مربوط به مقالات را ایجاد کرده باشید، می‌توانید از داخل پنل یک مقاله جدید ایجاد کنید، عنوان و محتوای آن را وارد کنید، تصویر شاخص انتخاب کنید، دسته‌بندی را مشخص کنید و در نهایت اطلاعات را ذخیره کنید.

یکی از مزیت‌های مهم پنل Payload این است که فرم‌های مدیریتی بر اساس Fields تعریف‌شده در Collection ساخته می‌شوند. برای مثال اگر Collection مقاله دارای فیلدهای زیر باشد:

title
slug
excerpt
content
image
author
category
publishedAt

پنل مدیریت نیز رابط کاربری لازم برای مدیریت همین اطلاعات را در اختیار شما قرار می‌دهد. بنابراین توسعه‌دهنده مجبور نیست برای هر مدل داده یک پنل مدیریتی کاملاً جداگانه از ابتدا طراحی کند.

مدیریت کاربران

اگر یک Collection با قابلیت Authentication ایجاد کرده باشید، پنل Payload می‌تواند برای مدیریت کاربران نیز استفاده شود. مدیر سیستم می‌تواند کاربران را مشاهده و بر اساس Access Control تعریف‌شده، اطلاعات آنها را مدیریت کند.

در پروژه‌های حرفه‌ای می‌توان نقش‌های مختلفی مانند:

Super Admin
Editor
Author
User

تعریف کرد و مشخص کرد هر نقش به کدام بخش‌های پنل دسترسی داشته باشد.

مدیریت Media

پنل Payload همچنین می‌تواند برای مدیریت فایل‌ها و Media مورد استفاده قرار گیرد. برای مثال در یک سایت آموزشی می‌توان فایل‌های زیر را مدیریت کرد:

Images
Videos
Documents
Course Files
Avatars

البته در پروژه‌های بزرگ بهتر است فایل‌های حجیم را روی Object Storage قرار دهید و از CDN برای ارائه آنها استفاده کنید.

جست‌وجو و مدیریت داده‌ها

وقتی تعداد رکوردهای یک Collection افزایش پیدا می‌کند، امکانات مدیریتی Payload به مدیر سیستم اجازه می‌دهد داده‌ها را راحت‌تر پیدا و مدیریت کند. بسته به ساختار Collection و تنظیمات پروژه می‌توان از قابلیت‌هایی مانند جست‌وجو، فیلتر، مرتب‌سازی و Pagination استفاده کرد.

سفارشی‌سازی پنل مدیریت

یکی از ویژگی‌های مهم Payload این است که Admin Panel صرفاً یک رابط کاربری ثابت نیست. توسعه‌دهندگان می‌توانند بخش‌هایی از پنل را متناسب با نیاز پروژه سفارشی کنند و Components یا رفتارهای اختصاصی خود را به آن اضافه کنند.

برای مثال در یک پلتفرم آموزشی می‌توان پنل مدیریت را به شکلی طراحی کرد که مدیر بتواند ساختار زیر را مدیریت کند:

Dashboard
│
├── Courses
│   ├── Lessons
│   ├── Teachers
│   └── Students
│
├── Content
│   ├── Posts
│   └── Categories
│
├── Media
├── Users
└── Orders

ساخت API در Payload

یکی از مهم‌ترین قابلیت‌های Payload CMS، امکان ارائه اطلاعات از طریق API است. از آنجا که Payload یک Headless CMS است، محتوای ذخیره‌شده در Collectionها می‌تواند از طریق API در اختیار وب‌سایت‌ها، اپلیکیشن‌های موبایل و سایر سرویس‌ها قرار بگیرد. به همین دلیل می‌توان Payload را علاوه بر یک CMS، به‌عنوان بخشی از Backend یک پروژه مدرن نیز استفاده کرد.

نکته مهم این است که در Payload معمولاً برای عملیات CRUD مربوط به Collectionها نیازی نیست برای هر مدل داده یک API جداگانه از ابتدا طراحی کنید. زمانی که یک Collection تعریف می‌کنید، Payload APIهای لازم برای دسترسی به آن داده‌ها را در اختیار پروژه قرار می‌دهد.

برای مثال اگر Collection زیر را داشته باشیم:

Posts
├── title
├── slug
├── excerpt
└── content

می‌توان از API مربوط به آن برای دریافت مقالات استفاده کرد. در حالت REST، Endpoint مربوط به Collection معمولاً بر اساس slug آن ساخته می‌شود:

GET /api/posts

برای مثال اگر Payload روی سیستم محلی و پورت 3000 اجرا شده باشد:

http://localhost:3000/api/posts

درخواست بالا می‌تواند فهرستی از مقالات را برگرداند.

یک پاسخ نمونه می‌تواند ساختاری مشابه زیر داشته باشد:

{
  "docs": [
    {
      "id": "1",
      "title": "آموزش TypeScript",
      "slug": "typescript-tutorial",
      "excerpt": "آموزش مقدماتی TypeScript"
    }
  ],
  "totalDocs": 1
}

ساختار دقیق Response به نسخه Payload، تنظیمات Collection و Query مورد استفاده بستگی دارد.

دریافت یک رکورد مشخص

برای دریافت یک رکورد مشخص می‌توان از شناسه آن استفاده کرد:

GET /api/posts/1

به این ترتیب اطلاعات همان مقاله درخواست می‌شود.

ایجاد یک رکورد جدید

برای ایجاد یک مقاله جدید می‌توان از درخواست POST استفاده کرد:

POST /api/posts

و داده‌ها را در Body درخواست ارسال کرد:

{
  "title": "آموزش Payload CMS",
  "slug": "payload-cms-tutorial",
  "excerpt": "آموزش کامل Payload CMS",
  "content": "..."
}

در صورتی که Collection و Access Control اجازه ایجاد رکورد را بدهند، Payload اطلاعات را در دیتابیس ذخیره می‌کند.

ویرایش اطلاعات

برای ویرایش یک رکورد نیز می‌توان از درخواست‌های HTTP مناسب مانند PATCH استفاده کرد:

PATCH /api/posts/1

برای مثال:

{
  "title": "آموزش کامل Payload CMS"
}

حذف یک رکورد

برای حذف یک رکورد می‌توان از DELETE استفاده کرد:

DELETE /api/posts/1

البته انجام عملیات ایجاد، ویرایش و حذف به Access Control و سطح دسترسی کاربر وابسته است. بنابراین داشتن Endpoint به معنی آن نیست که هر کاربری بتواند اطلاعات را تغییر دهد.

Query و فیلتر کردن اطلاعات

یکی از قابلیت‌های کاربردی API Payload امکان ارسال Query برای فیلتر کردن و مرتب‌سازی داده‌هاست. برای مثال می‌توان درخواست‌هایی برای جست‌وجو یا فیلتر مقالات بر اساس فیلدهای مختلف ایجاد کرد.

برای نمونه، یک درخواست می‌تواند به شکل مفهومی زیر باشد:

GET /api/posts?where[status][equals]=published

یا برای محدود کردن تعداد نتایج:

GET /api/posts?limit=10

این قابلیت در پروژه‌هایی که تعداد داده‌ها زیاد است اهمیت زیادی دارد، زیرا Client مجبور نیست تمام اطلاعات دیتابیس را دریافت کند.

استفاده از API در اپلیکیشن موبایل

یکی از مهم‌ترین کاربردهای API Payload، اتصال آن به اپلیکیشن‌های موبایل است. برای مثال فرض کنید یک اپلیکیشن Flutter داریم:

                Payload CMS
                     │
                  REST API
                     │
          ┌──────────┼──────────┐
          │          │          │
        Next.js    Flutter    Android

اپلیکیشن Flutter می‌تواند درخواست زیر را ارسال کند:

GET https://cms.example.com/api/courses

و اطلاعات دوره‌ها را دریافت کند.

در سمت Flutter نیز می‌توان با کتابخانه‌هایی مانند Dio یا http این API را مصرف کرد و داده‌های دریافت‌شده را به Modelهای Dart تبدیل کرد.

Authentication در API

برای APIهای عمومی مانند فهرست مقالات ممکن است نیازی به احراز هویت وجود نداشته باشد، اما Endpointهای حساس باید به Authentication و Access Control مجهز باشند.

برای مثال:

Public API
     │
     └── GET Posts

Authenticated API
     │
     ├── Create Post
     ├── Update Post
     └── Delete Post

در Payload می‌توان برای هر Collection مشخص کرد چه کسی اجازه ایجاد، مشاهده، ویرایش یا حذف اطلاعات را داشته باشد.

REST API و GraphQL

Payload علاوه بر REST، امکان استفاده از GraphQL را نیز فراهم می‌کند. بنابراین بسته به معماری پروژه می‌توانید از REST یا GraphQL استفاده کنید.

برای بسیاری از پروژه‌های معمول، REST API انتخاب ساده و مناسبی است؛ اما در پروژه‌هایی که Queryهای پیچیده یا نیازهای خاصی برای دریافت داده وجود دارد، GraphQL نیز می‌تواند گزینه مناسبی باشد.

API اختصاصی در Payload

گاهی APIهای پیش‌فرض Collectionها برای نیاز پروژه کافی نیستند. برای مثال ممکن است بخواهید Endpoint اختصاصی مانند زیر ایجاد کنید:

GET /api/courses/featured

یا:

POST /api/payment/verify

در چنین شرایطی می‌توان Custom Endpoint ایجاد کرد و منطق اختصاصی مورد نیاز پروژه را در آن قرار داد.

این قابلیت باعث می‌شود Payload فقط به APIهای CRUD محدود نباشد و بتوان از آن برای ساخت Backendهای پیچیده‌تر نیز استفاده کرد.

استفاده از Payload برای اپلیکیشن موبایل

موبایل است. از آنجا که Payload یک Headless CMS است و اطلاعات را از طریق API در اختیار Client قرار می‌دهد، می‌توان یک Backend مرکزی ایجاد کرد و هم‌زمان اپلیکیشن‌های Android، iOS و Flutter را به آن متصل کرد. در این معماری، اپلیکیشن موبایل مسئول نمایش اطلاعات و تعامل با کاربر است و Payload مدیریت داده‌ها، کاربران، محتوا و API را بر عهده می‌گیرد.

برای مثال فرض کنید قصد داریم یک اپلیکیشن آموزشی ایجاد کنیم. اطلاعات دوره‌ها، درس‌ها، مدرس‌ها، دسته‌بندی‌ها، مقالات و کاربران در Payload ذخیره می‌شوند و اپلیکیشن موبایل از طریق API این اطلاعات را دریافت می‌کند:

                     Payload CMS
                          │
                      PostgreSQL
                          │
                        API
                          │
             ┌────────────┼────────────┐
             │            │            │
          Android        iOS        Flutter

در این معماری، نیازی نیست برای Android، iOS و Flutter سه Backend جداگانه ایجاد کنید. همه Clientها از یک API مشترک استفاده می‌کنند و اطلاعات در یک دیتابیس مرکزی نگهداری می‌شود.

چه اطلاعاتی را می‌توان با Payload مدیریت کرد؟

Payload می‌تواند تقریباً تمام داده‌های مورد نیاز یک اپلیکیشن را مدیریت کند. برای مثال در یک اپلیکیشن آموزشی می‌توان Collectionهای زیر را ایجاد کرد:

Users
Courses
Lessons
Categories
Teachers
Articles
Comments
Media
Orders

برای یک اپلیکیشن موسیقی نیز می‌توان ساختاری مانند زیر داشت:

Artists
Albums
Songs
Genres
Playlists
Users
Comments
Media

اپلیکیشن موبایل این اطلاعات را از طریق API دریافت می‌کند و در رابط کاربری نمایش می‌دهد.

احراز هویت کاربران

یکی از نیازهای اصلی اپلیکیشن‌های موبایل، سیستم ثبت‌نام و ورود کاربران است. Payload امکان ایجاد Collectionهای احراز هویت‌شده را فراهم می‌کند و می‌توان از آن برای مدیریت کاربران استفاده کرد.

برای مثال:

Mobile App
    │
    │ Login
    ▼
Payload API
    │
    ▼
Authentication
    │
    ▼
User

پس از احراز هویت، Client می‌تواند درخواست‌های مجاز را به API ارسال کند. سطح دسترسی کاربران نیز می‌تواند بر اساس Role و Access Control مدیریت شود.

اتصال فلاتر به Payload

اگر اپلیکیشن با فلاتر توسعه داده شده باشد، می‌توان API های Payload را با کتابخانه‌هایی مانند Dio یا http مصرف کرد.

برای مثال:

final response = await dio.get(
  'https://cms.example.com/api/courses',
);

اطلاعات دریافت‌شده را می‌توان به Modelهای Dart تبدیل کرد:

class Course {
  final String id;
  final String title;

  Course({
    required this.id,
    required this.title,
  });
}

در نتیجه Payload به‌عنوان Backend و Flutter به‌عنوان Client عمل می‌کنند.

اتصال Android به Payload

در اندروید نیز می‌توان API های Payload را با ابزارهایی مانند Retrofit، OkHttp و Kotlin Serialization مصرف کرد.

معماری می‌تواند به شکل زیر باشد:

Android App
    │
    ▼
Retrofit / HTTP
    │
    ▼
Payload REST API
    │
    ▼
PostgreSQL

به این ترتیب Android مستقیماً با دیتابیس ارتباط ندارد و تمام درخواست‌ها از طریق API انجام می‌شوند.

این موضوع از نظر امنیتی نیز اهمیت زیادی دارد؛ زیرا اطلاعات اتصال به دیتابیس نباید داخل اپلیکیشن موبایل قرار بگیرد.

مدیریت محتوا از طریق پنل Payload

یکی از مزیت‌های مهم این معماری این است که مدیر سیستم می‌تواند محتوا را بدون انتشار نسخه جدید اپلیکیشن تغییر دهد.

برای مثال مدیر یک اپلیکیشن آموزشی می‌تواند از پنل Payload:

  • دوره جدید ایجاد کند
  • درس جدید اضافه کند
  • تصویر دوره را تغییر دهد
  • مقاله منتشر کند
  • دسته‌بندی ایجاد کند
  • اطلاعات مدرس را ویرایش کند

و اپلیکیشن موبایل در درخواست بعدی اطلاعات جدید را از API دریافت خواهد کرد.

Admin
  │
  ▼
Payload Admin Panel
  │
  ▼
PostgreSQL
  │
  ▼
API
  │
  ▼
Mobile App

این ویژگی باعث می‌شود برای بسیاری از تغییرات محتوایی نیازی به انتشار نسخه جدید Android یا iOS نباشد.

مدیریت فایل و تصاویر

در اپلیکیشن‌های موبایل معمولاً با فایل‌هایی مانند تصاویر، ویدئوها، فایل‌های صوتی و اسناد سروکار داریم. Payload می‌تواند اطلاعات مربوط به Media را مدیریت کند و فایل‌ها را بر اساس معماری پروژه در Storage مناسب قرار دهد.

برای پروژه‌های کوچک ممکن است فایل‌ها روی سرور ذخیره شوند، اما در پروژه‌های بزرگ بهتر است از Object Storage و CDN استفاده شود.

معماری پیشنهادی:

              Payload CMS
                   │
          ┌────────┴────────┐
          │                 │
      PostgreSQL       Object Storage
                              │
                              ▼
                             CDN
                              │
                              ▼
                         Mobile App

در این حالت دیتابیس برای ذخیره Metadata و اطلاعات محتوا استفاده می‌شود و فایل‌های حجیم از طریق Storage و CDN در اختیار کاربران قرار می‌گیرند.

آیا Payload برای Backend کامل اپلیکیشن مناسب است؟

Payload می‌تواند بخش بزرگی از Backend مورد نیاز یک اپلیکیشن را پوشش دهد؛ از جمله:

  • مدیریت کاربران
  • Authentication
  • مدیریت محتوا
  • API
  • مدیریت فایل
  • Access Control
  • Relationship بین داده‌ها
  • Hooks
  • پنل مدیریت

اما در پروژه‌های پیچیده ممکن است به سرویس‌های دیگری نیز نیاز داشته باشید. برای مثال:

Payload
+
PostgreSQL
+
Redis
+
Object Storage
+
CDN
+
Payment Gateway
+
Notification Service

بنابراین Payload را می‌توان هسته Backend یا CMS پروژه در نظر گرفت و سرویس‌های تخصصی را بر اساس نیاز به آن اضافه کرد.

مزیت مهم: یک Backend برای چند Client

یکی از مهم‌ترین مزایای استفاده از Payload برای اپلیکیشن موبایل، امکان استفاده از یک Backend مشترک است:

                     Payload
                        │
                     REST API
                        │
        ┌───────────────┼───────────────┐
        │               │               │
      Next.js         Flutter         Android
        │               │               │
     Website        Mobile App       Mobile App

این معماری باعث می‌شود منطق مدیریت داده و محتوا در یک Backend مرکزی قرار داشته باشد و تیم‌های مختلف بتوانند Clientهای خود را مستقل از Backend توسعه دهند.

Payload و Next.js

ترکیب Payload CMS و Next.js یکی از جذاب‌ترین معماری‌ها برای ساخت پروژه‌های مدرن Full-stack است. هر دو ابزار در اکوسیستم TypeScript و React قرار دارند و می‌توانند در یک پروژه واحد در کنار یکدیگر استفاده شوند. در این معماری، Payload مسئول مدیریت داده‌ها، محتوا، کاربران، احراز هویت و API است و Next.js می‌تواند وظیفه ساخت رابط کاربری، صفحات وب و تجربه کاربری را بر عهده بگیرد.

یکی از مزیت‌های مهم این ترکیب، امکان ایجاد یک پروژه یکپارچه است که در آن CMS، Backend و Frontend در کنار یکدیگر قرار دارند. به جای اینکه یک پروژه جداگانه برای CMS و یک پروژه دیگر برای Frontend ایجاد شود، می‌توان Payload را در معماری Next.js قرار داد و از قابلیت‌های هر دو فناوری استفاده کرد.

ساختار کلی چنین پروژه‌ای می‌تواند به شکل زیر باشد:

                    Next.js
                       │
          ┌────────────┴────────────┐
          │                         │
      Frontend                 Payload CMS
          │                         │
          │                     API / Admin
          │                         │
          └────────────┬────────────┘
                       │
                       ▼
                  PostgreSQL

در این معماری، Next.js مسئول بخش‌هایی مانند صفحات وب، Routing، Server Components، رابط کاربری و SEO است و Payload وظیفه مدیریت داده و CMS را بر عهده دارد. در نتیجه می‌توان یک سایت سریع و SEO-friendly در کنار یک Backend و پنل مدیریت قدرتمند ایجاد کرد.

چرا Payload و Next.js را با هم استفاده کنیم؟

یکی از دلایل مهم استفاده از این ترکیب، یکپارچگی تکنولوژی‌هاست. هر دو سیستم از اکوسیستم JavaScript/TypeScript استفاده می‌کنند و توسعه‌دهنده می‌تواند بخش زیادی از پروژه را با یک زبان و ابزارهای مشابه توسعه دهد.

برای مثال در یک سایت آموزشی می‌توان ساختار زیر را ایجاد کرد:

Next.js
│
├── Home
├── Courses
├── Course Detail
├── Blog
└── About
        │
        ▼
   Payload CMS
        │
        ├── Courses
        ├── Lessons
        ├── Posts
        ├── Teachers
        └── Users
        │
        ▼
    PostgreSQL

مدیر سایت از طریق پنل Payload محتوا را مدیریت می‌کند و Next.js همان محتوا را در صفحات سایت نمایش می‌دهد.

استفاده از Payload به‌عنوان Backend

در این معماری Payload نقش Backend پروژه را بر عهده می‌گیرد. اطلاعاتی مانند دوره‌ها، مقالات، کاربران و محصولات در Payload تعریف و در PostgreSQL ذخیره می‌شوند.

Next.js می‌تواند این اطلاعات را از طریق API دریافت کند و در صفحات سایت نمایش دهد.

برای مثال:

User
 │
 ▼
Next.js
 │
 ▼
Payload API
 │
 ▼
PostgreSQL

در نتیجه Frontend مستقیماً به دیتابیس متصل نمی‌شود و تمام ارتباط با داده‌ها از طریق لایه Backend انجام می‌شود.

استفاده از Payload در کنار Next.js App Router

نسخه‌های جدید Next.js از App Router استفاده می‌کنند و Payload نیز می‌تواند در این معماری قرار بگیرد. در چنین پروژه‌ای مسیرهای مربوط به Frontend و Admin Panel را می‌توان در ساختار پروژه مدیریت کرد.

یک ساختار نمونه:

src/
├── app/
│   ├── (frontend)/
│   │   ├── page.tsx
│   │   ├── courses/
│   │   └── blog/
│   │
│   └── (payload)/
│
├── collections/
│   ├── Users.ts
│   ├── Courses.ts
│   ├── Posts.ts
│   └── Media.ts
│
└── payload.config.ts

البته ساختار دقیق پروژه بر اساس نسخه Payload، Template انتخاب‌شده و معماری مورد استفاده می‌تواند متفاوت باشد.

استفاده از داده‌های Payload در Next.js

فرض کنید در Payload یک Collection به نام Posts داریم. Next.js می‌تواند اطلاعات مقالات را دریافت کرده و در صفحه وب نمایش دهد.

به‌صورت مفهومی:

Payload
   │
   │ Posts API
   ▼
Next.js
   │
   ▼
Blog Page

برای مثال صفحه:

/blog

می‌تواند لیست مقالات را از Payload دریافت کند و صفحه:

/blog/payload-cms

اطلاعات یک مقاله مشخص را نمایش دهد.

مزیت برای SEO

ترکیب Payload و Next.js برای سایت‌های محتوایی و آموزشی می‌تواند بسیار مناسب باشد. Next.js امکانات مختلفی برای ساخت صفحات قابل ایندکس، Metadata، Rendering و مدیریت ساختار صفحات در اختیار توسعه‌دهنده قرار می‌دهد و Payload نیز مدیریت محتوا را انجام می‌دهد.

برای مثال یک مقاله در Payload می‌تواند شامل موارد زیر باشد:

title
slug
excerpt
content
featuredImage
author
category
publishedAt

Next.js می‌تواند بر اساس این اطلاعات صفحه مقاله را ایجاد کند و Metadata مناسب صفحه را نیز تنظیم کند.

استفاده مشترک برای وب و موبایل

یکی دیگر از مزایای این معماری این است که Payload فقط برای Next.js نیست.

می‌توان یک Backend مرکزی داشت:

                    Payload
                       │
                       ▼
                      API
                       │
          ┌────────────┼────────────┐
          │            │            │
       Next.js       Flutter      Android
          │            │            │
       Website      Mobile App   Mobile App

در این حالت Next.js برای وب‌سایت و Flutter یا Android برای اپلیکیشن موبایل از یک Backend مشترک استفاده می‌کنند.

این معماری برای پروژه‌هایی مانند:

  • پلتفرم آموزشی
  • فروشگاه اینترنتی
  • سایت محتوایی
  • سرویس SaaS
  • شبکه اجتماعی
  • اپلیکیشن محتوامحور

کاربرد زیادی دارد.

Payload و Next.js در یک پروژه یا جدا؟

یکی از تصمیم‌های مهم هنگام طراحی معماری این است که Payload و Next.js را در یک پروژه قرار دهیم یا آنها را جدا کنیم.

در بسیاری از پروژه‌های معمول، قرار دادن آنها در یک پروژه می‌تواند توسعه و Deployment را ساده‌تر کند:

Next.js + Payload
        │
        ▼
   PostgreSQL

اما در پروژه‌های بزرگ‌تر ممکن است جداسازی سرویس‌ها مزایایی داشته باشد:

Next.js
   │
   ▼
Payload API
   │
   ▼
PostgreSQL

انتخاب بین این دو معماری به اندازه پروژه، تیم توسعه، نیازهای مقیاس‌پذیری و نحوه Deployment بستگی دارد.

مدیریت فایل و Media

یکی دیگر از قابلیت‌های مهم Payload، مدیریت فایل است.

فرض کنید برای مقاله‌ها تصویر داریم.

می‌توانیم Collection مربوط به Media ایجاد کنیم:

export const Media: CollectionConfig = {
  slug: 'media',

  upload: true,

  fields: [
    {
      name: 'alt',
      type: 'text',
    },
  ],
}

حالا مدیر سایت می‌تواند فایل‌ها را از پنل مدیریت آپلود کند.

آیا فایل‌ها را روی خود سرور ذخیره کنیم؟

برای پروژه‌های کوچک می‌توان فایل‌ها را روی سرور ذخیره کرد.

اما برای پروژه‌هایی که تعداد فایل‌ها یا حجم آنها زیاد است، بهتر است فایل‌ها را از سرور اصلی جدا کنیم.

معماری بهتر:

                    Payload
                       │
             ┌─────────┴─────────┐
             │                   │
         PostgreSQL          Object Storage
             │                   │
          Database            Images/Files

برای فایل‌های زیاد می‌توان از Object Storage و CDN استفاده کرد.

مزایای این معماری:

  • کاهش مصرف دیسک سرور
  • امکان Scale کردن
  • مدیریت بهتر فایل‌ها
  • افزایش سرعت تحویل فایل
  • مناسب برای CDN
  • Backup ساده‌تر

Access Control چیست؟

Access Control یا «کنترل دسترسی» در Payload CMS به مجموعه قوانینی گفته می‌شود که مشخص می‌کنند چه کاربری، به چه اطلاعاتی و با چه سطحی از دسترسی می‌تواند دسترسی داشته باشد. در یک پروژه واقعی، تنها داشتن سیستم ورود کاربران کافی نیست؛ باید مشخص شود هر کاربر بعد از ورود چه کارهایی می‌تواند انجام دهد. برای مثال ممکن است یک مدیر بتواند تمام مقالات را ویرایش کند، اما یک نویسنده فقط اجازه ویرایش مقالات خودش را داشته باشد.

Payload این امکان را فراهم می‌کند که قوانین دسترسی را برای بخش‌های مختلف سیستم تعریف کنید. برای مثال می‌توان تعیین کرد چه کسی اجازه ایجاد، مشاهده، ویرایش یا حذف یک رکورد را داشته باشد. این قوانین می‌توانند بر اساس وضعیت ورود کاربر، نقش کاربر، مالکیت یک رکورد یا حتی شرایط پیچیده‌تر تعیین شوند.

برای مثال، می‌توان ساختاری مانند زیر در نظر گرفت:

Users
│
├── Super Admin
├── Editor
├── Author
└── User

سپس برای هر نقش سطح دسترسی متفاوتی تعریف کرد:

نقش مشاهده ایجاد ویرایش حذف
Super Admin
Editor
Author فقط محتوای خودش
User

تعریف Access Control در Collection

Access Control معمولاً در Configuration مربوط به Collection تعریف می‌شود. برای مثال، اگر بخواهیم فقط کاربران واردشده اجازه ایجاد مقاله داشته باشند، می‌توانیم قانونی مشابه زیر تعریف کنیم:

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',

  access: {
    create: ({ req }) => {
      return Boolean(req.user)
    },
  },

  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
  ],
}

در این مثال، req.user بررسی می‌شود. اگر کاربر احراز هویت شده باشد، مقدار true برگردانده شده و اجازه ایجاد مقاله خواهد داشت؛ در غیر این صورت درخواست رد می‌شود.

کنترل دسترسی برای عملیات مختلف

می‌توان برای عملیات مختلف قوانین جداگانه تعریف کرد. برای مثال:

access: {
  create: () => true,
  read: () => true,
  update: () => false,
  delete: () => false,
}

در این مثال همه کاربران می‌توانند اطلاعات را مشاهده کنند، اما امکان ویرایش و حذف وجود ندارد.

در یک پروژه واقعی معمولاً قوانین پیچیده‌تر هستند و بر اساس نقش کاربر یا مالکیت رکورد نوشته می‌شوند.

Access Control بر اساس Role

یکی از رایج‌ترین روش‌ها، کنترل دسترسی بر اساس Role است. فرض کنید کاربر دارای فیلدی به نام role باشد:

role
│
├── admin
├── editor
├── author
└── user

سپس می‌توان بررسی کرد که آیا کاربر مدیر است یا خیر:

access: {
  update: ({ req }) => {
    return req.user?.role === 'admin'
  },
}

در این حالت فقط کاربری که Role او admin باشد اجازه ویرایش خواهد داشت.

دسترسی بر اساس مالکیت محتوا

گاهی لازم است کاربر فقط بتواند محتوایی را که خودش ایجاد کرده است ویرایش کند.

برای مثال:

Author A
 ├── Article 1
 └── Article 2

Author B
 ├── Article 3
 └── Article 4

در این شرایط Author A نباید بتواند Article 3 را ویرایش کند.

برای پیاده‌سازی چنین سناریویی می‌توان در Access Control مالک رکورد را با کاربر فعلی مقایسه کرد.

access: {
  update: ({ req, data }) => {
    return data?.author === req.user?.id
  },
}

منطق دقیق این بررسی به ساختار Collection و Relationshipهای پروژه بستگی دارد.

کنترل دسترسی در سطح Field

در برخی سناریوها لازم است دسترسی فقط به یک Collection محدود نشود و برای بعضی Fieldها نیز قوانین جداگانه تعریف شود.

برای مثال ممکن است یک فیلد مانند:

isFeatured

فقط توسط مدیر قابل تغییر باشد، در حالی که نویسنده بتواند عنوان و محتوای مقاله را ویرایش کند.

این قابلیت برای پروژه‌هایی که نقش‌های مختلف و داده‌های حساس دارند بسیار کاربردی است.

چرا Access Control مهم است؟

Access Control یکی از بخش‌های مهم امنیت Backend است. نباید تنها به رابط کاربری اعتماد کرد و فرض کرد چون یک دکمه در پنل نمایش داده نمی‌شود، کاربر نمی‌تواند عملیات مربوط به آن را انجام دهد. کنترل دسترسی باید در سمت Backend نیز بررسی شود تا درخواست‌های غیرمجاز مستقیماً رد شوند.

برای مثال:

Mobile App
     │
     │ Request
     ▼
Payload API
     │
     ▼
Access Control
     │
 ┌───┴────┐
 │        │
Allow    Deny

این موضوع به‌خصوص برای APIهای مورد استفاده توسط اپلیکیشن‌های موبایل اهمیت زیادی دارد؛ زیرا کاربران می‌توانند مستقیماً درخواست‌های HTTP ارسال کنند و نباید امنیت سیستم وابسته به محدودیت‌های رابط کاربری اپلیکیشن باشد.

سیستم Role

Role یا «نقش کاربری» مشخص می‌کند که هر کاربر در یک سیستم چه وظایف و سطح دسترسی‌هایی دارد. در Payload CMS می‌توان با استفاده از Roleها یک سیستم Role-Based Access Control (RBAC) ایجاد کرد و تعیین کرد هر گروه از کاربران به کدام بخش‌های سیستم دسترسی داشته باشند. این قابلیت در پروژه‌هایی که چند نوع کاربر دارند، مانند سایت‌های آموزشی، فروشگاه‌ها و پلتفرم‌های SaaS، اهمیت زیادی دارد.

برای مثال، در یک پلتفرم آموزشی ممکن است کاربران زیر را داشته باشیم:

Users
│
├── Super Admin
├── Admin
├── Editor
├── Instructor
└── Student

هر یک از این نقش‌ها می‌توانند وظایف متفاوتی داشته باشند. برای مثال Super Admin به تمام بخش‌های سیستم دسترسی دارد، Admin می‌تواند کاربران و محتوا را مدیریت کند، Editor مسئول مقالات و محتوای سایت است، Instructor دوره‌های آموزشی خود را مدیریت می‌کند و Student تنها به محتوایی که برای کاربران عادی در نظر گرفته شده دسترسی دارد.

تعریف Role در Collection کاربران

برای پیاده‌سازی Role معمولاً یک فیلد در Collection مربوط به کاربران ایجاد می‌شود. برای مثال:

{
  name: 'role',
  type: 'select',
  required: true,
  defaultValue: 'student',
  options: [
    {
      label: 'Super Admin',
      value: 'super-admin',
    },
    {
      label: 'Admin',
      value: 'admin',
    },
    {
      label: 'Instructor',
      value: 'instructor',
    },
    {
      label: 'Student',
      value: 'student',
    },
  ],
}

در این حالت هر کاربر یکی از Roleهای تعریف‌شده را خواهد داشت:

User
│
├── id
├── name
├── email
├── password
└── role

بهتر است در پروژه‌های واقعی، Roleهای حساس مانند super-admin توسط کاربران عادی قابل انتخاب یا تغییر نباشند و تغییر آنها تنها توسط کاربران دارای سطح دسترسی مناسب انجام شود.

استفاده از Role در Access Control

بعد از تعریف Role می‌توان از آن در قوانین Access Control استفاده کرد. برای مثال فرض کنید فقط Admin و Super Admin اجازه حذف مقاله داشته باشند:

access: {
  delete: ({ req }) => {
    return (
      req.user?.role === 'admin' ||
      req.user?.role === 'super-admin'
    )
  },
}

در این حالت:

Super Admin  → Delete ✓
Admin        → Delete ✓
Instructor   → Delete ✗
Student      → Delete ✗

همین منطق را می‌توان برای عملیات create، read و update نیز استفاده کرد.

ایجاد تابع قابل استفاده مجدد

در پروژه‌های بزرگ بهتر است منطق بررسی Role را در هر Collection تکرار نکنیم. می‌توان توابع Access Control ایجاد کرد و در بخش‌های مختلف پروژه از آنها استفاده کرد.

برای مثال:

export const isAdmin = ({ req }) => {
  return (
    req.user?.role === 'admin' ||
    req.user?.role === 'super-admin'
  )
}

سپس در Collectionهای مختلف:

access: {
  delete: isAdmin,
}

این روش باعث می‌شود کد پروژه تمیزتر و نگهداری آن ساده‌تر شود.

Roleهای سلسله‌مراتبی

در پروژه‌های بزرگ‌تر ممکن است Roleها سلسله‌مراتب داشته باشند:

Super Admin
     │
     ▼
   Admin
     │
     ▼
  Editor
     │
     ▼
 Instructor
     │
     ▼
  Student

اما نکته مهم این است که Roleها در Payload به‌صورت خودکار یک سلسله‌مراتب کامل ایجاد نمی‌کنند. شما باید منطق دسترسی را بر اساس نیاز پروژه تعریف کنید.

برای مثال می‌توان یک تابع ایجاد کرد که مشخص کند چه Roleهایی اجازه مدیریت کاربران را دارند:

const canManageUsers = ({ req }) => {
  return ['super-admin', 'admin'].includes(
    req.user?.role
  )
}

Role در یک پلتفرم آموزشی

فرض کنید برای یک پلتفرم آموزشی چنین ساختاری داریم:

Super Admin
│
├── مدیریت کاربران
├── مدیریت دوره‌ها
├── مدیریت مقالات
├── مدیریت سفارش‌ها
└── تنظیمات سیستم

Instructor
│
├── مدیریت دوره‌های خودش
├── مدیریت درس‌های خودش
└── مشاهده دانشجویان خودش

Student
│
├── مشاهده دوره‌های خریداری‌شده
├── مشاهده درس‌ها
└── مدیریت پروفایل

در این معماری Role تنها مشخص می‌کند کاربر در چه گروهی قرار دارد؛ جزئیات اینکه دقیقاً چه رکوردهایی را می‌تواند مشاهده یا ویرایش کند باید با Access Control و در صورت نیاز با قوانین مالکیت داده پیاده‌سازی شود.

برای مثال یک Instructor ممکن است اجازه ویرایش Course را داشته باشد، اما فقط اگر آن Course متعلق به خودش باشد. بنابراین صرفاً بررسی role === 'instructor' کافی نیست و باید مالکیت رکورد نیز بررسی شود.

Role در اپلیکیشن موبایل

Roleها برای اپلیکیشن‌های موبایل نیز کاربرد زیادی دارند. برای مثال Backend می‌تواند بر اساس Role کاربر مشخص کند که چه APIهایی قابل دسترسی هستند:

Flutter App
     │
     ▼
Payload API
     │
     ▼
Authentication
     │
     ▼
Role + Access Control
     │
 ┌───┴─────────────┐
 │                 │
Allowed          Denied

نکته مهم این است که Role نباید صرفاً در Frontend بررسی شود. مخفی کردن یک دکمه در اپلیکیشن به معنی ایجاد امنیت نیست. Payload باید در سمت Backend نیز دسترسی کاربر را بررسی کند تا کاربر نتواند با ارسال مستقیم درخواست HTTP عملیات غیرمجاز انجام دهد.

Hooks در Payload چیست؟

Hooks در Payload CMS مکانیزمی برای اجرای کدهای سفارشی در مراحل مختلف چرخه حیات داده‌ها و عملیات سیستم هستند. به کمک Hooks می‌توان زمانی که یک رکورد ایجاد، ویرایش یا حذف می‌شود، قبل یا بعد از انجام عملیات اصلی، منطق دلخواهی را اجرا کرد. این قابلیت باعث می‌شود بدون تغییر در هسته Payload، رفتار سیستم را متناسب با نیاز پروژه سفارشی کنید.

برای مثال فرض کنید در یک سایت آموزشی، مدیر یک دوره جدید ایجاد می‌کند. می‌توان با استفاده از Hook بعد از ایجاد دوره، یک Log ثبت کرد، اطلاعات دیگری را به‌روزرسانی کرد یا یک رویداد را به سرویس دیگری ارسال کرد.

به‌صورت ساده می‌توان چرخه اجرای Hook را این‌گونه تصور کرد:

Create / Update / Delete
          │
          ▼
       Payload
          │
     ┌────┴────┐
     │         │
   Before     After
     │         │
     ▼         ▼
  Hook       Hook
     │         │
     └────┬────┘
          ▼
       Database

انواع Hook در Payload

Payload Hooks در بخش‌های مختلف سیستم قابل استفاده هستند. یکی از رایج‌ترین دسته‌ها، Collection Hooks است که روی عملیات مربوط به Collectionها اجرا می‌شوند.

برای مثال می‌توان از Hookهایی مانند موارد زیر استفاده کرد:

beforeValidate
beforeChange
afterChange
beforeRead
afterRead
beforeDelete
afterDelete

هر Hook در مرحله متفاوتی از چرخه پردازش داده اجرا می‌شود و انتخاب Hook مناسب به کاری که می‌خواهید انجام دهید بستگی دارد.

beforeValidate

این Hook قبل از مرحله Validation اجرا می‌شود و برای زمانی مناسب است که بخواهید قبل از اعتبارسنجی نهایی داده‌ها، آنها را بررسی یا آماده کنید.

برای مثال:

hooks: {
  beforeValidate: [
    async ({ data }) => {
      if (data?.title) {
        data.title = data.title.trim()
      }

      return data
    },
  ],
}

در این مثال فاصله‌های اضافی ابتدای و انتهای عنوان حذف می‌شوند.

beforeChange

beforeChange قبل از ذخیره تغییرات در دیتابیس اجرا می‌شود و برای اعمال منطق قبل از ایجاد یا ویرایش رکورد کاربرد دارد.

برای مثال می‌توان هنگام ایجاد یک مقاله، اطلاعات نویسنده را بر اساس کاربر فعلی تنظیم کرد.

hooks: {
  beforeChange: [
    async ({ data, req }) => {
      if (req.user) {
        data.author = req.user.id
      }

      return data
    },
  ],
}

afterChange

afterChange پس از ایجاد یا ویرایش موفق یک رکورد اجرا می‌شود. این Hook برای انجام کارهایی که باید بعد از ذخیره موفقیت‌آمیز داده انجام شوند بسیار کاربردی است.

برای مثال:

hooks: {
  afterChange: [
    async ({ doc }) => {
      console.log(`Post created: ${doc.id}`)
    },
  ],
}

از این Hook می‌توان برای کارهایی مانند ارسال Notification، ثبت Log، ارسال Webhook یا اطلاع‌رسانی به یک سرویس دیگر استفاده کرد.

beforeDelete و afterDelete

این Hooks هنگام حذف رکورد کاربرد دارند.

برای مثال قبل از حذف یک Course می‌توان بررسی کرد که آیا شرایط لازم برای حذف آن وجود دارد یا خیر:

hooks: {
  beforeDelete: [
    async ({ id }) => {
      console.log(`Deleting course: ${id}`)
    },
  ],
}

همچنین afterDelete پس از حذف موفق رکورد اجرا می‌شود.

Hook در یک پروژه واقعی

فرض کنید یک فروشگاه آموزشی داریم و زمانی که سفارش پرداخت‌شده ایجاد می‌شود، باید دسترسی کاربر به دوره فعال شود.

می‌توان فرآیند را به شکل زیر طراحی کرد:

Payment
   │
   ▼
Order Created
   │
   ▼
afterChange Hook
   │
   ▼
Activate Course Access
   │
   ▼
Student can access Course

در چنین سناریویی Hook می‌تواند ارتباط بین چند بخش از سیستم را برقرار کند.

Hookهای Global

Hooks فقط به Collectionها محدود نیستند. Payload برای بخش‌هایی مانند Global نیز امکان استفاده از Hook را فراهم می‌کند. این قابلیت زمانی مفید است که داده مورد نظر یک مجموعه از رکوردها نباشد و به یک تنظیمات کلی سیستم مربوط شود.

برای مثال می‌توان تنظیمات عمومی سایت را در یک Global نگهداری کرد و هنگام تغییر آنها منطق خاصی اجرا کرد.

نکات مهم هنگام استفاده از Hooks

Hooks بسیار قدرتمند هستند، اما بهتر است از آنها با دقت استفاده شود. اگر منطق پیچیده‌ای را مستقیماً داخل Hook قرار دهید، ممکن است با بزرگ شدن پروژه نگهداری کد دشوار شود. بهتر است Hook مسئولیت محدودی داشته باشد و منطق پیچیده را به Service یا Functionهای جداگانه منتقل کند.

همچنین باید مراقب اجرای زنجیره‌ای Hookها باشید. اگر یک Hook باعث ایجاد یا تغییر رکورد دیگری شود و آن عملیات نیز Hook دیگری را اجرا کند، ممکن است زنجیره‌ای از عملیات ایجاد شود که مدیریت آن دشوار باشد.

تولید Slug خودکار

فرض کنید عنوان مقاله این باشد:

آموزش کامل Payload CMS

می‌توانیم Slug ایجاد کنیم:

payload-cms-tutorial

این کار را می‌توان با Hook یا منطق برنامه انجام داد.

Slug برای SEO و ایجاد URLهای مناسب اهمیت زیادی دارد.

امنیت در Payload CMS

امنیت در یک CMS فقط به احراز هویت کاربران محدود نمی‌شود. در یک پروژه واقعی باید مشخص شود چه کسی می‌تواند وارد سیستم شود، به چه داده‌هایی دسترسی دارد، چه عملیاتی انجام دهد و اطلاعات حساس چگونه نگهداری شوند. Payload CMS مجموعه‌ای از قابلیت‌ها برای پیاده‌سازی این لایه‌های امنیتی در اختیار توسعه‌دهنده قرار می‌دهد و می‌توان آن را متناسب با نیاز پروژه به یک Backend امن و قابل کنترل تبدیل کرد.

یکی از مهم‌ترین بخش‌های امنیت Payload، Authentication و Access Control است. Authentication مشخص می‌کند کاربر چه کسی است و Access Control تعیین می‌کند پس از احراز هویت، چه عملیاتی مجاز به انجام آن است. برای مثال ممکن است یک کاربر عادی فقط بتواند اطلاعات پروفایل خود را مشاهده کند، در حالی که یک Editor امکان ایجاد و ویرایش مقالات و یک Admin دسترسی گسترده‌تری داشته باشد.

             User
               │
               ▼
        Authentication
               │
               ▼
         Access Control
               │
        ┌──────┴──────┐
        │             │
      Allow          Deny
        │
        ▼
      Payload

مدیریت دسترسی کاربران

یکی از مهم‌ترین اقدامات امنیتی در Payload، تعریف دقیق قوانین دسترسی برای Collectionهاست. برای هر عملیات مانند مشاهده، ایجاد، ویرایش و حذف می‌توان قانون جداگانه تعریف کرد.

برای مثال:

access: {
  create: ({ req }) => Boolean(req.user),
  update: ({ req }) => req.user?.role === 'admin',
  delete: ({ req }) => req.user?.role === 'admin',
}

در این مثال فقط کاربران احراز هویت‌شده می‌توانند رکورد ایجاد کنند و عملیات ویرایش و حذف فقط برای Admin مجاز است.

نکته مهم این است که امنیت باید در Backend اعمال شود. مخفی کردن یک دکمه در پنل مدیریت یا اپلیکیشن موبایل به‌تنهایی امنیت ایجاد نمی‌کند؛ زیرا کاربر می‌تواند مستقیماً API را فراخوانی کند. Payload باید هر درخواست را در سمت سرور بررسی کند.

مدیریت Roleها

در پروژه‌های چندکاربره بهتر است از Roleها برای تعریف سطح دسترسی استفاده شود. برای مثال:

Super Admin
    │
    ├── تمام دسترسی‌ها
    │
Admin
    │
    ├── مدیریت کاربران
    ├── مدیریت محتوا
    │
Editor
    │
    └── مدیریت مقالات
    │
Author
    │
    └── مدیریت محتوای خودش
    │
User
    │
    └── دسترسی عمومی

ترکیب Role با Access Control به شما اجازه می‌دهد قوانین دقیق‌تری برای پروژه تعریف کنید.

حفاظت از اطلاعات حساس

اطلاعات حساسی مانند رمز عبور دیتابیس، Secret مربوط به Payload، کلیدهای API و اطلاعات سرویس‌های خارجی نباید مستقیماً در Source Code قرار بگیرند. این اطلاعات باید در Environment Variables نگهداری شوند.

برای مثال:

DATABASE_URL=postgresql://user:password@localhost:5432/payload
PAYLOAD_SECRET=your-secure-secret

فایل .env نیز نباید در Repository عمومی قرار گیرد و باید در .gitignore اضافه شود.

استفاده از HTTPS

در محیط Production تمام ارتباطات بین Client و Payload باید از طریق HTTPS انجام شود. این موضوع به‌خصوص برای Login، Authentication Tokenها، اطلاعات کاربران و APIهای حساس اهمیت دارد.

معماری معمول می‌تواند به شکل زیر باشد:

             HTTPS
Client ─────────────────► Nginx / Proxy
                              │
                              ▼
                         Payload CMS
                              │
                              ▼
                         PostgreSQL

استفاده از HTTPS باعث می‌شود اطلاعات در مسیر انتقال رمزنگاری شوند و احتمال شنود اطلاعات حساس کاهش پیدا کند.

امنیت API

از آنجا که Payload می‌تواند API در اختیار اپلیکیشن‌های موبایل و وب‌سایت قرار دهد، باید Endpointها بر اساس نیاز پروژه محافظت شوند. APIهای عمومی باید فقط اطلاعاتی را ارائه دهند که واقعاً برای کاربران عمومی لازم است و عملیات حساس مانند ایجاد، ویرایش یا حذف باید به Authentication و Access Control مناسب مجهز باشند.

برای مثال:

Public
GET /api/posts

Authenticated
GET /api/profile

Admin
POST   /api/posts
PATCH  /api/posts/:id
DELETE /api/posts/:id

این تفکیک باعث می‌شود هر Client فقط به بخش‌هایی از Backend که واقعاً نیاز دارد دسترسی داشته باشد.

امنیت PostgreSQL

Payload مسئول مدیریت CMS و Backend است، اما دیتابیس نیز باید به‌صورت جداگانه امن شود. PostgreSQL نباید بدون دلیل از اینترنت عمومی قابل دسترسی باشد و بهتر است فقط Payload یا سرویس‌های مورد نیاز بتوانند به آن متصل شوند.

همچنین استفاده از یک User اختصاصی برای پروژه و تعیین حداقل دسترسی‌های مورد نیاز، روش مناسب‌تری نسبت به استفاده از کاربر اصلی PostgreSQL است.

Internet
   │
   ✕
PostgreSQL
   ▲
   │
Payload Server

در یک معماری امن، Client نباید مستقیماً به PostgreSQL متصل شود.

امنیت فایل‌ها و Media

اگر پروژه دارای تصاویر، ویدئوها، فایل‌های صوتی یا اسناد است، باید برای فایل‌ها نیز سیاست دسترسی مناسبی تعریف شود. فایل‌های عمومی را می‌توان از طریق CDN ارائه کرد، اما فایل‌های خصوصی مانند محتوای خریداری‌شده یا اسناد کاربران باید با کنترل دسترسی مناسب ارائه شوند.

برای پروژه‌های بزرگ بهتر است فایل‌ها در Object Storage ذخیره شوند و Payload اطلاعات مربوط به آنها را مدیریت کند.

Payload
   │
   ├── PostgreSQL
   │     └── Metadata
   │
   └── Object Storage
         └── Files
              │
              ▼
             CDN

اعتبارسنجی داده‌ها

امنیت فقط مربوط به کاربران نیست. داده‌هایی که از طریق API وارد سیستم می‌شوند نیز باید اعتبارسنجی شوند. Payload امکان تعریف Fieldهای مختلف و قوانین Validation را فراهم می‌کند تا داده‌های نامعتبر یا غیرمنتظره وارد سیستم نشوند.

برای مثال می‌توان مشخص کرد یک فیلد اجباری باشد یا مقدار آن محدودیت خاصی داشته باشد:

{
  name: 'title',
  type: 'text',
  required: true,
}

برای Validationهای پیچیده‌تر نیز می‌توان منطق اختصاصی تعریف کرد.

جلوگیری از افشای اطلاعات حساس

در طراحی API باید مراقب باشید اطلاعاتی که برای Client ارسال می‌شوند بیش از نیاز نباشند. برای مثال اطلاعاتی مانند Password Hash، Secretهای داخلی یا اطلاعات حساس کاربران نباید در Responseهای عمومی قرار بگیرند.

بهتر است برای هر Collection مشخص شود چه اطلاعاتی عمومی هستند و چه اطلاعاتی فقط برای کاربران مجاز قابل مشاهده‌اند.

Backup و امنیت عملیاتی

حتی اگر Backend به‌درستی امن شده باشد، باید برای اتفاقاتی مانند حذف تصادفی داده‌ها، خرابی سرور یا حمله نیز برنامه داشته باشید. Backup منظم PostgreSQL یکی از مهم‌ترین اقدامات امنیتی و عملیاتی در پروژه‌های Payload است.

بهتر است Backupها نیز در همان سرور اصلی نگهداری نشوند و حداقل یک نسخه خارج از سرور Production ذخیره شود.

به‌روزرسانی Payload و وابستگی‌ها

Payload، Next.js، Node.js و سایر Packageهای پروژه به‌مرور زمان به‌روزرسانی می‌شوند و ممکن است نسخه‌های جدید شامل اصلاحات امنیتی باشند. بنابراین باید وابستگی‌های پروژه به‌صورت دوره‌ای بررسی و به‌روزرسانی شوند.

قبل از به‌روزرسانی در Production بهتر است ابتدا تغییرات روی محیط Staging یا Development بررسی و سپس نسخه جدید Deploy شود.

در نهایت، امنیت Payload را نباید یک قابلیت واحد دانست؛ بلکه باید آن را مجموعه‌ای از چند لایه در نظر گرفت:

Security
│
├── Authentication
├── Access Control
├── Role Management
├── API Security
├── HTTPS
├── Environment Variables
├── PostgreSQL Security
├── File Security
├── Input Validation
├── Backup
└── Dependency Updates

اگر این لایه‌ها به‌درستی طراحی و پیاده‌سازی شوند، Payload می‌تواند پایه مناسبی برای ساخت Backend، CMS و API امن برای وب‌سایت‌ها، اپلیکیشن‌های موبایل و پلتفرم‌های بزرگ‌تر باشد.

اجرای Payload در Production

بعد از توسعه و تست Payload CMS در محیط Development، مرحله بعدی انتقال پروژه به Production است. در این مرحله برنامه باید روی یک سرور واقعی اجرا شود، به دیتابیس Production متصل باشد و از طریق دامنه و HTTPS در دسترس کاربران قرار گیرد. اجرای Payload در Production فقط به اجرای npm run start محدود نمی‌شود و باید مواردی مانند Build، Environment Variables، PostgreSQL، Process Manager، Reverse Proxy، SSL و Backup نیز در نظر گرفته شوند.

یک معماری معمول برای اجرای Payload در Production می‌تواند به شکل زیر باشد:

                    Internet
                       │
                       ▼
                  Cloudflare
                       │
                     HTTPS
                       │
                       ▼
                     Nginx
                       │
                       ▼
                  Payload CMS
                       │
             ┌─────────┴─────────┐
             │                   │
             ▼                   ▼
        PostgreSQL          Object Storage

در پروژه‌های کوچک ممکن است PostgreSQL روی همان سرور قرار داشته باشد، اما در پروژه‌های بزرگ‌تر می‌توان دیتابیس و Object Storage را از سرور Application جدا کرد.

آماده‌سازی پروژه

قبل از انتقال پروژه به Production، ابتدا باید نسخه Production پروژه را آماده کنید. بهتر است وابستگی‌های پروژه نصب شده و Build پروژه بدون خطا انجام شود:

npm install
npm run build

اگر Build با موفقیت انجام شود، می‌توان برنامه را با دستور Production اجرا کرد:

npm run start

در این حالت Next.js و Payload در محیط Production اجرا می‌شوند.

تنظیم Environment Variables

اطلاعات حساس و تنظیمات Production نباید داخل Source Code قرار بگیرند. متغیرهای محیطی مورد نیاز را روی سرور تنظیم کنید.

برای مثال:

NODE_ENV=production

DATABASE_URL=postgresql://payloaduser:strong-password@localhost:5432/payloaddb

PAYLOAD_SECRET=your-production-secret

NEXT_PUBLIC_SERVER_URL=https://cms.example.com

مقادیر واقعی DATABASE_URL و PAYLOAD_SECRET باید با اطلاعات محیط Production جایگزین شوند.

به‌خصوص PAYLOAD_SECRET باید یک مقدار طولانی، تصادفی و امن باشد و نباید در Repository عمومی قرار بگیرد.

Build پروژه

پس از قرار دادن Source Code روی سرور و نصب Dependencies، پروژه را Build کنید:

npm run build

Build باعث می‌شود نسخه Production برنامه ایجاد شود.

در صورت موفقیت Build، پروژه آماده اجرا خواهد بود:

npm run start

اما اجرای مستقیم برنامه با Terminal برای Production مناسب نیست؛ زیرا با بسته شدن Session یا Restart شدن سرور، فرآیند نیز متوقف می‌شود.

استفاده از PM2

برای اجرای دائمی Payload می‌توان از PM2 به‌عنوان Process Manager استفاده کرد.

ابتدا PM2 را نصب کنید:

npm install -g pm2

سپس Payload را اجرا کنید:

pm2 start npm --name payload-cms -- start

برای مشاهده وضعیت:

pm2 status

برای مشاهده Logها:

pm2 logs payload-cms

و برای ذخیره فرآیندها جهت اجرای مجدد بعد از Restart سرور:

pm2 save

همچنین باید Startup مربوط به PM2 را برای سیستم تنظیم کنید. دستور دقیق آن را می‌توان با اجرای زیر دریافت کرد:

pm2 startup

PM2 یک دستور مناسب به شما نمایش می‌دهد که باید با دسترسی مناسب اجرا شود.

استفاده از Nginx

معمولاً بهتر است Payload مستقیماً روی پورت عمومی اینترنت قرار نگیرد. به جای آن می‌توان Nginx را به‌عنوان Reverse Proxy در مقابل Payload قرار داد.

برای مثال Payload روی پورت 3000 اجرا می‌شود:

Internet
   │
   ▼
Nginx :443
   │
   ▼
Payload :3000

یک Configuration ساده Nginx می‌تواند شبیه زیر باشد:

server {
    listen 80;
    server_name cms.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;

        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

بعد از تنظیم Nginx باید Configuration را بررسی و سرویس را Reload کنید:

sudo nginx -t
sudo systemctl reload nginx

در محیط Production بهتر است HTTPS نیز فعال باشد و دسترسی HTTP به HTTPS منتقل شود.

اتصال دامنه

فرض کنید دامنه CMS شما:

cms.example.com

باشد. ابتدا DNS دامنه را به IP سرور Production متصل می‌کنید. سپس Nginx درخواست‌های مربوط به این دامنه را به Payload منتقل می‌کند.

در نتیجه:

https://cms.example.com
             │
             ▼
           Nginx
             │
             ▼
      Payload :3000

پنل مدیریت نیز از طریق مسیر Admin در دسترس خواهد بود:

https://cms.example.com/admin

PostgreSQL در Production

Payload در Production باید به Database واقعی پروژه متصل باشد. بهتر است برای Production یک Database و User اختصاصی داشته باشید.

برای مثال:

Database: payloaddb
User: payloaduser
Host: 127.0.0.1
Port: 5432

و Connection String در Environment Variable قرار گیرد:

DATABASE_URL=postgresql://payloaduser:password@127.0.0.1:5432/payloaddb

دسترسی مستقیم عمومی به PostgreSQL معمولاً ضروری نیست و بهتر است Firewall و تنظیمات PostgreSQL طوری باشند که فقط سرویس‌های مورد نیاز بتوانند به آن متصل شوند.

مدیریت فایل‌ها

اگر پروژه دارای فایل‌های زیادی مانند تصاویر، ویدئوها، فایل‌های صوتی و اسناد است، بهتر است آنها را مستقیماً روی دیسک سرور Application ذخیره نکنید.

یک معماری مناسب‌تر می‌تواند شامل Object Storage باشد:

Payload
   │
   ├── PostgreSQL
   │
   └── Object Storage
          │
          ▼
         CDN
          │
          ▼
        Users

این معماری به‌خصوص برای پروژه‌های آموزشی، فروشگاه‌ها و اپلیکیشن‌های محتوامحور اهمیت زیادی دارد.

Logging و Monitoring

در Production باید بتوانید وضعیت Payload را بررسی کنید. PM2 امکان مشاهده Logهای برنامه را فراهم می‌کند:

pm2 logs payload-cms

همچنین می‌توانید وضعیت Process را بررسی کنید:

pm2 status

در پروژه‌های بزرگ‌تر بهتر است علاوه بر این موارد، سیستم Monitoring و Alerting نیز داشته باشید تا در صورت Crash شدن سرویس، افزایش مصرف منابع یا خطاهای غیرعادی سریعاً مطلع شوید.

Backup

یکی از مهم‌ترین بخش‌های اجرای Payload در Production، داشتن Backup است. مهم‌ترین داده‌های پروژه معمولاً در PostgreSQL قرار دارند و باید به‌صورت منظم از آنها Backup تهیه شود.

برای مثال:

Production
    │
    ▼
PostgreSQL
    │
    ▼
Scheduled Backup
    │
    ▼
Remote Storage

اگر فایل‌های Media نیز روی Storage اختصاصی قرار دارند، باید برای آنها نیز سیاست Backup یا Redundancy مناسبی در نظر گرفته شود.

فرآیند پیشنهادی Deployment

یک فرآیند ساده و قابل تکرار برای Deployment می‌تواند به شکل زیر باشد:

git pull

npm install

npm run build

pm2 restart payload-cms

pm2 status

البته در پروژه‌های حرفه‌ای بهتر است این فرآیند به‌صورت CI/CD خودکار شود تا بعد از انتشار نسخه جدید، مراحل تست، Build و Deployment به شکل کنترل‌شده انجام شوند.

معماری پیشنهادی Production

برای یک پروژه واقعی می‌توان معماری زیر را در نظر گرفت:

                         Internet
                            │
                            ▼
                       Cloudflare
                            │
                         HTTPS
                            │
                            ▼
                          Nginx
                            │
                            ▼
                     Payload + Next.js
                            │
              ┌─────────────┼─────────────┐
              │             │             │
              ▼             ▼             ▼
         PostgreSQL    Object Storage    Redis
              │             │
              │             ▼
              │            CDN
              │
              ▼
           Backup

در پروژه‌های کوچک می‌توان این معماری را ساده‌تر کرد و چند سرویس را روی یک سرور قرار داد. با افزایش کاربران و حجم داده‌ها، می‌توان PostgreSQL، Object Storage، CDN و سایر سرویس‌ها را به زیرساخت‌های مستقل منتقل کرد.

استفاده از PM2

اگر Payload را روی VPS اجرا می‌کنید، بهتر است از Process Manager استفاده کنید.

یکی از گزینه‌های رایج PM2 است.

ابتدا:

npm install -g pm2

سپس پروژه را اجرا کنید:

pm2 start npm --name payload-cms -- start

برای مشاهده وضعیت:

pm2 status

برای مشاهده Log:

pm2 logs payload-cms

برای ذخیره فرآیندها:

pm2 save

و برای راه‌اندازی خودکار PM2 بعد از Restart سرور:

pm2 startup

دستوری که PM2 در خروجی پیشنهاد می‌کند را نیز باید اجرا کنید.

استفاده از Nginx

در Production معمولاً بهتر است Node.js مستقیماً روی پورت عمومی اینترنت قرار نگیرد.

معماری مناسب‌تر:

Internet
   │
   ▼
Nginx :443
   │
   ▼
Node.js / Payload :3000
   │
   ▼
PostgreSQL

Nginx به عنوان Reverse Proxy عمل می‌کند.

برای مثال درخواست:

https://cms.example.com

به سرویس Payload روی پورت داخلی منتقل می‌شود.

اتصال دامنه به Payload

بعد از راه‌اندازی سرور، می‌توانید یک Subdomain برای CMS ایجاد کنید.

مثلاً:

cms.example.com

و معماری را به شکل زیر داشته باشید:

example.com
      │
      ├── Website
      │
      └── cms.example.com
                │
                ▼
            Payload CMS

این ساختار برای پروژه‌های واقعی بسیار مناسب است.

فعال کردن HTTPS

برای Production استفاده از HTTPS ضروری است.

می‌توانید از سرویس‌هایی مانند Cloudflare یا Let’s Encrypt برای مدیریت SSL استفاده کنید.

در معماری Cloudflare:

User
 │
 ▼
Cloudflare
 │
 ▼
Nginx
 │
 ▼
Payload

استفاده از CDN و لایه‌های امنیتی نیز می‌تواند در کنار این معماری انجام شود.

Deploy Payload روی VPS

یک معماری پیشنهادی برای Production می‌تواند به شکل زیر باشد:

                 Internet
                    │
                    ▼
                Cloudflare
                    │
                    ▼
                  Nginx
                    │
          ┌─────────┴─────────┐
          │                   │
       Next.js             Payload
          │                   │
          └─────────┬─────────┘
                    │
                    ▼
               PostgreSQL

روی VPS می‌توانید موارد زیر را نصب کنید:

Linux
Node.js
PostgreSQL
Nginx
PM2
Git

سپس پروژه را از Git دریافت کرده، Dependencyها را نصب، Build و با PM2 اجرا کنید.

ساختار پیشنهادی برای یک پروژه واقعی

فرض کنید می‌خواهیم یک پلتفرم آموزشی ایجاد کنیم.

Collectionهای ما می‌توانند شامل موارد زیر باشند:

Users
│
├── Courses
│    ├── Lessons
│    ├── Categories
│    └── Teachers
│
├── Posts
│    └── Categories
│
├── Media
│
└── Comments

در چنین پروژه‌ای Payload می‌تواند نقش Backend و CMS را بر عهده داشته باشد.

Payload CMS برای چه پروژه‌هایی مناسب است؟

Payload CMS برای پروژه‌هایی مناسب است که در آنها انعطاف‌پذیری Backend، مدیریت محتوا، API و امکان توسعه اختصاصی اهمیت زیادی دارد. برخلاف CMSهای سنتی که بیشتر برای ساخت وب‌سایت‌های محتوایی طراحی شده‌اند، Payload را می‌توان به‌عنوان یک CMS و Backend قابل توسعه در پروژه‌های مختلف استفاده کرد. به همین دلیل انتخاب آن می‌تواند از یک وب‌سایت ساده تا یک پلتفرم چندسرویسی متفاوت باشد.

یکی از کاربردهای مناسب Payload، وب‌سایت‌های محتوایی و خبری است. در چنین پروژه‌هایی می‌توان مقالات، نویسندگان، دسته‌بندی‌ها، برچسب‌ها، تصاویر و سایر محتواها را در Collectionهای مختلف مدیریت کرد و سپس آنها را از طریق API در وب‌سایت نمایش داد. ترکیب Payload با Next.js نیز امکان ساخت سایت‌های سریع و SEO-friendly را فراهم می‌کند.

پلتفرم‌های آموزشی نیز یکی از سناریوهای بسیار مناسب برای Payload هستند. برای مثال می‌توان Collectionهایی مانند دوره، درس، مدرس، دانشجو، دسته‌بندی، آزمون، مقاله و سفارش ایجاد کرد و روابط بین آنها را تعریف کرد. سپس همین Backend می‌تواند هم‌زمان توسط وب‌سایت و اپلیکیشن موبایل مورد استفاده قرار گیرد.

Payload CMS
│
├── Courses
├── Lessons
├── Teachers
├── Students
├── Articles
└── Orders
       │
       ▼
      API
   ┌───┴────┐
   │        │
 Website   Mobile App

Payload برای فروشگاه‌های اینترنتی و سیستم‌های فروش نیز می‌تواند گزینه مناسبی باشد؛ به‌خصوص زمانی که فروشگاه نیاز به مدل‌های داده اختصاصی داشته باشد. محصول، دسته‌بندی، برند، موجودی، مشتری، سفارش و سایر موجودیت‌ها را می‌توان به‌صورت Collection تعریف کرد و منطق اختصاصی مورد نیاز را با Hooks و Access Control توسعه داد.

یکی دیگر از کاربردهای Payload، ساخت Backend برای اپلیکیشن‌های موبایل است. اگر یک اپلیکیشن Android، iOS یا Flutter به Backend برای مدیریت کاربران، محتوا، فایل‌ها و API نیاز داشته باشد، Payload می‌تواند این نقش را ایفا کند. در این حالت اپلیکیشن موبایل مستقیماً به دیتابیس متصل نمی‌شود و از APIهای Payload استفاده می‌کند.

                 Payload CMS
                      │
                    API
                      │
       ┌──────────────┼──────────────┐
       │              │              │
    Next.js         Flutter        Android
       │              │              │
     Web App       Mobile App     Mobile App

Payload همچنین برای SaaS و پلتفرم‌های اختصاصی مناسب است. اگر پروژه‌ای نیاز به کاربران، نقش‌ها، احراز هویت، مدیریت محتوا، API، کنترل دسترسی و مدل‌های داده سفارشی داشته باشد، می‌توان Payload را به‌عنوان بخش Backend آن در نظر گرفت. در چنین پروژه‌هایی قابلیت‌هایی مانند Hooks و Access Control امکان پیاده‌سازی منطق اختصاصی را فراهم می‌کنند.

برای پروژه‌های چندپلتفرمی نیز Payload مزیت مهمی دارد. یک Backend می‌تواند داده‌ها را به چند Client مختلف ارائه کند؛ بنابراین لازم نیست برای وب‌سایت و اپلیکیشن موبایل سیستم مدیریت محتوای جداگانه‌ای ایجاد شود.

در مقابل، Payload همیشه بهترین انتخاب نیست. اگر هدف فقط ایجاد یک وبلاگ بسیار ساده یا سایت شرکتی کوچک باشد و نیازی به API، مدل‌های داده اختصاصی یا توسعه Backend وجود نداشته باشد، یک CMS سنتی و آماده ممکن است راه‌اندازی ساده‌تر و سریع‌تری داشته باشد. همچنین اگر تیم توسعه تجربه کافی با TypeScript و Node.js نداشته باشد، یادگیری و نگهداری Payload ممکن است نسبت به CMSهای سنتی به دانش فنی بیشتری نیاز داشته باشد.

به‌صورت خلاصه، Payload برای پروژه‌هایی مناسب‌تر است که در آنها کنترل روی Backend، API و ساختار داده اهمیت دارد:

نوع پروژه میزان تناسب
پلتفرم آموزشی ⭐⭐⭐⭐⭐
Backend اپلیکیشن موبایل ⭐⭐⭐⭐⭐
SaaS ⭐⭐⭐⭐⭐
فروشگاه اختصاصی ⭐⭐⭐⭐⭐
سایت محتوایی و خبری ⭐⭐⭐⭐⭐
پروژه چندپلتفرمی ⭐⭐⭐⭐⭐
سایت شرکتی ساده ⭐⭐⭐
وبلاگ بسیار ساده ⭐⭐

Payload CMS یا وردپرس؟

انتخاب بین Payload CMS و وردپرس بیشتر از آنکه به این موضوع مربوط باشد که کدام سیستم «بهتر» است، به نوع پروژه، نیازهای فنی، میزان سفارشی‌سازی و تجربه تیم توسعه بستگی دارد. هر دو سیستم می‌توانند برای مدیریت محتوا استفاده شوند، اما فلسفه طراحی آنها متفاوت است.

وردپرس یک CMS سنتی و بسیار کامل است که سال‌ها برای ساخت وب‌سایت، وبلاگ، فروشگاه و سایت‌های محتوایی استفاده شده است. در مقابل، Payload CMS یک Headless CMS مدرن و TypeScript-based است که بیشتر برای پروژه‌هایی طراحی شده که Backend، API و مدل داده قابل توسعه اهمیت زیادی دارند.

Payload CMS و وردپرس

Payload CMS و وردپرس

تفاوت معماری

در وردپرس، معمولاً CMS و Frontend در یک سیستم قرار دارند:

              WordPress
            ┌────┴────┐
            │         │
         Backend   Frontend
            │         │
            └────┬────┘
                 ▼
              Database

در Payload، CMS بیشتر نقش Backend و مدیریت داده را دارد:

                 Payload
                    │
                   API
          ┌─────────┼─────────┐
          │         │         │
       Next.js    Flutter   Android
          │         │         │
          ▼         ▼         ▼
        Website   Mobile   Mobile

این تفاوت معماری باعث می‌شود Payload برای پروژه‌هایی که چند Client دارند، انعطاف بیشتری داشته باشد.

مقایسه Payload و WordPress

ویژگی Payload CMS WordPress
نوع معماری Headless / Backend-oriented Traditional CMS
زبان اصلی TypeScript / JavaScript PHP
دیتابیس رایج PostgreSQL / MongoDB و سایر Adapterها MySQL / MariaDB
API بخش اصلی معماری قابل استفاده
Admin Panel دارد دارد
REST API دارد دارد
GraphQL دارد از طریق راهکارهای مربوطه
توسعه اختصاصی بسیار بالا بسیار بالا
Plugin Ecosystem کوچک‌تر بسیار بزرگ
مناسب برای SEO بسیار خوب با Frontend مناسب بسیار خوب
مناسب برای اپ موبایل بسیار خوب خوب
سرعت توسعه سایت ساده متوسط بسیار سریع
مناسب برای SaaS بسیار خوب معمولاً انتخاب اول نیست
مناسب برای سایت شرکتی ساده خوب بسیار خوب
نیاز به دانش برنامه‌نویسی بیشتر کمتر برای پروژه‌های ساده

وردپرس چه زمانی انتخاب بهتری است؟

اگر هدف شما ساخت یک سایت محتوایی، وبلاگ، سایت شرکتی یا فروشگاه نسبتاً استاندارد باشد، وردپرس می‌تواند انتخاب بسیار مناسبی باشد.

یکی از بزرگ‌ترین مزایای وردپرس ، اکوسیستم گسترده آن است. برای بسیاری از نیازها می‌توان Plugin آماده پیدا کرد و بدون توسعه Backend اختصاصی قابلیت مورد نظر را به سایت اضافه کرد.

برای مثال:

WordPress
│
├── SEO Plugin
├── Cache Plugin
├── Security Plugin
├── WooCommerce
├── Payment Plugin
└── Page Builder

این موضوع باعث می‌شود برای پروژه‌های کوچک و متوسط، زمان راه‌اندازی وردپرس بسیار کوتاه باشد.

Payload چه زمانی انتخاب بهتری است؟

اگر پروژه شما یک محصول نرم‌افزاری اختصاصی باشد و نیاز داشته باشید Backend را دقیقاً مطابق نیاز خود طراحی کنید، Payload گزینه جذاب‌تری خواهد بود.

برای مثال یک پلتفرم آموزشی می‌تواند چنین ساختاری داشته باشد:

Payload
│
├── Users
├── Courses
├── Lessons
├── Teachers
├── Exams
├── Orders
├── Payments
└── Subscriptions

و همین Backend می‌تواند به چند Client سرویس بدهد:

                Payload API
                     │
        ┌────────────┼────────────┐
        │            │            │
      Next.js      Flutter       iOS
        │            │            │
      Website      Mobile       Mobile

در چنین پروژه‌ای استفاده از WordPress ممکن است باعث شود بخش قابل توجهی از Backend با Pluginها، Custom Post Typeها و کدهای سفارشی ساخته شود؛ در حالی که Payload از ابتدا با رویکرد Backend و API طراحی شده است.

توسعه‌دهنده یا مدیر محتوا؟

یکی از تفاوت‌های مهم این دو سیستم، مخاطب اصلی آنهاست.

WordPress به‌گونه‌ای طراحی شده که مدیر سایت بتواند بدون دانش برنامه‌نویسی زیادی سایت را مدیریت کند. قالب‌ها، Pluginها و Page Builderها نیز این موضوع را تقویت می‌کنند.

Payload بیشتر برای تیمی جذاب است که توسعه‌دهنده درگیر معماری و توسعه سیستم است. ساخت Collection، تعریف Field، Access Control، Hook و API معمولاً در کد انجام می‌شود.

به همین دلیل می‌توان گفت:

WordPress
    ↓
Content Management First

Payload
    ↓
Developer + Backend First

Payload یا WordPress برای اپلیکیشن موبایل؟

اگر قرار است Backend اصلی یک اپلیکیشن Flutter، Android یا iOS را ایجاد کنید، Payload معمولاً معماری طبیعی‌تری ارائه می‌دهد.

برای مثال:

Flutter
   │
   ▼
Payload API
   │
   ▼
PostgreSQL

در WordPress نیز می‌توان API ساخت و اپلیکیشن موبایل را به WordPress متصل کرد، اما اگر پروژه از ابتدا یک اپلیکیشن و Backend اختصاصی باشد، Payload معمولاً کنترل بیشتری روی مدل داده و معماری Backend در اختیار توسعه‌دهنده قرار می‌دهد.

Payload یا WordPress برای SEO؟

هر دو می‌توانند برای SEO مناسب باشند؛ اما SEO بیشتر به Frontend و نحوه پیاده‌سازی سایت وابسته است.

در WordPress بسیاری از قابلیت‌های SEO از طریق Pluginها در اختیار مدیر سایت قرار می‌گیرند.

در Payload، اگر از Next.js استفاده کنید، می‌توانید Metadata، صفحات، Structured Data، Rendering و سایر بخش‌های SEO را مستقیماً در معماری Frontend کنترل کنید.

بنابراین:

WordPress
→ SEO با امکانات آماده + Plugin

Payload + Next.js
→ SEO با کنترل کامل توسعه‌دهنده

کدام یک برای پروژه‌های بزرگ مناسب‌تر است؟

برای پروژه‌های بزرگ نمی‌توان صرفاً بر اساس نام CMS تصمیم گرفت. معماری، تیم توسعه، زیرساخت، Database، Cache، CDN و نحوه Deployment اهمیت بسیار بیشتری دارند.

با این حال، اگر پروژه نیازمند Backend اختصاصی، APIهای متعدد، اپلیکیشن موبایل، Roleهای پیچیده و مدل‌های داده سفارشی باشد، معماری Payload می‌تواند انتخاب مناسبی باشد.

در مقابل، اگر پروژه یک سایت محتوایی بزرگ باشد که تیم تولید محتوا باید به‌سرعت مقالات، صفحات و Media را مدیریت کند و Pluginهای زیادی برای آن وجود داشته باشد، WordPress همچنان انتخاب بسیار قدرتمندی است.

جمع‌بندی

به‌صورت ساده می‌توان انتخاب را این‌گونه خلاصه کرد:

اگر پروژه شما:

سایت ساده / شرکتی / وبلاگ
        ↓
     WordPress

فروشگاه استاندارد
        ↓
     WordPress + WooCommerce

پلتفرم آموزشی اختصاصی
        ↓
     Payload

Backend اپلیکیشن موبایل
        ↓
     Payload

SaaS
        ↓
     Payload

Headless + Next.js
        ↓
     Payload

سایت محتوایی با مدیریت ساده
        ↓
     WordPress

بنابراین Payload CMS الزاماً جایگزین WordPress نیست. این دو ابزار برای سناریوهای متفاوتی بسیار مناسب هستند. اگر هدف شما راه‌اندازی سریع یک سایت با امکانات آماده و اکوسیستم Plugin گسترده باشد، WordPress انتخاب منطقی‌تری است؛ اما اگر بخواهید یک Backend مدرن، Headless CMS و API قابل توسعه برای وب‌سایت و اپلیکیشن‌های مختلف ایجاد کنید، Payload می‌تواند گزینه بسیار قدرتمندی باشد.

Payload CMS یا Strapi؟

Payload CMS و Strapi هر دو از محبوب‌ترین Headless CMSهای مدرن هستند و می‌توانند برای ساخت Backend، API و مدیریت محتوا مورد استفاده قرار بگیرند. هر دو امکان ایجاد Collection، مدیریت کاربران، کنترل دسترسی، API و توسعه قابلیت‌های اختصاصی را فراهم می‌کنند؛ اما معماری، تجربه توسعه و اکوسیستم آنها تفاوت‌هایی دارد.

اگر بخواهیم خیلی خلاصه بگوییم، Payload بیشتر به یک Backend Framework + CMS مدرن نزدیک است و کنترل زیادی را در اختیار توسعه‌دهنده قرار می‌دهد؛ در حالی که Strapi بیشتر به‌عنوان یک Headless CMS آماده با Admin Panel قدرتمند و تجربه کاربری مناسب برای تیم‌های محتوا شناخته می‌شود.

مقایسه کلی

ویژگی Payload CMS Strapi
معماری Headless CMS / Backend Headless CMS
زبان TypeScript JavaScript / TypeScript
Backend Node.js Node.js
Frontend Admin React React
دیتابیس PostgreSQL و Adapterهای دیگر PostgreSQL و سایر دیتابیس‌ها
REST API دارد دارد
GraphQL دارد دارد
Admin Panel دارد دارد
Authentication دارد دارد
Role & Permissions دارد دارد
Hooks / Lifecycle دارد دارد
Type Safety بسیار خوب خوب
سفارشی‌سازی Backend بسیار بالا بالا
تجربه توسعه‌دهنده بسیار خوب برای TypeScript خوب
اکوسیستم Plugin کوچک‌تر بزرگ‌تر
مناسب برای Next.js ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
مناسب برای Mobile API ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
مناسب برای SaaS ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

Payload و Strapi از نظر معماری

در هر دو سیستم، Client از طریق API به Backend متصل می‌شود:

                    CMS
                     │
                    API
          ┌──────────┼──────────┐
          │          │          │
       Next.js     Flutter    Android

اما فلسفه توسعه آنها کمی متفاوت است.

Payload از ابتدا با TypeScript و رویکرد توسعه‌دهنده‌محور طراحی شده و بسیاری از تنظیمات سیستم در قالب Code تعریف می‌شوند.

Strapi نیز بسیار قابل توسعه است، اما تجربه آن بیشتر حول یک CMS آماده با Admin Panel و مدیریت Content Typeها شکل گرفته است.

Payload و TypeScript

یکی از نقاط قوت Payload برای توسعه‌دهندگان TypeScript، Type Safety است. مدل‌های داده و Configuration سیستم در کد تعریف می‌شوند و این موضوع می‌تواند در پروژه‌های بزرگ باعث کاهش خطا و هماهنگی بهتر Backend و Frontend شود.

برای مثال:

export const Courses: CollectionConfig = {
  slug: 'courses',

  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
  ],
}

این رویکرد برای تیم‌هایی که Backend خود را به‌صورت Code-first توسعه می‌دهند بسیار جذاب است.

Strapi و Content Type Builder

یکی از ویژگی‌های شناخته‌شده Strapi، Content-Type Builder است. توسعه‌دهنده می‌تواند مدل‌های داده و فیلدهای آنها را از طریق Admin Panel ایجاد و مدیریت کند.

برای تیم‌هایی که می‌خواهند مدل‌های محتوا را با سرعت بالا ایجاد کنند و بخش قابل توجهی از کار را از طریق رابط گرافیکی انجام دهند، این رویکرد می‌تواند بسیار مناسب باشد.

در Payload نیز Admin Panel قدرتمندی وجود دارد، اما رویکرد توسعه Collectionها بیشتر Code-first است.

کدام یک برای Next.js بهتر است؟

هر دو می‌توانند در کنار Next.js استفاده شوند:

Option 1

Next.js
   │
   ▼
Payload
   │
   ▼
PostgreSQL

یا:

Option 2

Next.js
   │
   ▼
Strapi
   │
   ▼
PostgreSQL

هر دو معماری کاملاً قابل استفاده هستند.

با این حال اگر پروژه از ابتدا بر پایه Next.js + TypeScript طراحی شده باشد، Payload معمولاً تجربه یکپارچه‌تری ایجاد می‌کند؛ به‌خصوص زمانی که بخواهید CMS و Backend را بسیار نزدیک به کد Frontend توسعه دهید.

کدام یک برای اپلیکیشن موبایل بهتر است؟

برای اپلیکیشن‌های Flutter، Android و iOS، هر دو گزینه مناسبی هستند.

                 Backend
              ┌──────┴──────┐
              │             │
           Payload        Strapi
              │             │
              └──────┬──────┘
                     │
                    API
                     │
          ┌──────────┼──────────┐
          │          │          │
       Flutter     Android      iOS

در این سناریو، تفاوت اصلی بیشتر به معماری Backend و نیازهای توسعه‌دهنده مربوط می‌شود تا توانایی ارائه API.

اگر API و مدل داده پیچیده‌ای دارید و می‌خواهید کنترل زیادی روی Backend داشته باشید، Payload گزینه بسیار خوبی است.

مدیریت محتوا

اگر تمرکز اصلی پروژه روی تیم تولید محتوا باشد، تجربه Admin Panel اهمیت زیادی پیدا می‌کند.

برای مثال در یک سایت خبری:

Editor
  │
  ▼
Admin Panel
  │
  ├── Articles
  ├── Categories
  ├── Authors
  └── Media

هر دو سیستم می‌توانند چنین محیطی ایجاد کنند.

Strapi سابقه بیشتری به‌عنوان یک Headless CMS مستقل دارد و اکوسیستم آن نیز بزرگ است. Payload نیز Admin Panel مدرن و قابل سفارشی‌سازی دارد و برای پروژه‌هایی که مدل داده پیچیده‌تری دارند بسیار قدرتمند است.

Access Control

هر دو سیستم امکان تعریف Role و Permission را دارند.

برای مثال:

Super Admin
    │
    ├── Full Access
    │
Editor
    │
    ├── Articles
    └── Categories
    │
Author
    │
    └── Own Articles
    │
User
    │
    └── Public Content

در Payload می‌توان Access Control را بسیار نزدیک به مدل داده و کد Backend تعریف کرد. این موضوع برای پروژه‌هایی که قوانین دسترسی پیچیده دارند یک مزیت مهم است.

Hooks و منطق اختصاصی

هر دو سیستم امکان اجرای منطق سفارشی در چرخه حیات داده‌ها را دارند.

برای مثال:

Create Order
      │
      ▼
Hook / Lifecycle
      │
      ├── Update User
      ├── Create Access
      ├── Send Notification
      └── Create Log

بنابراین برای پروژه‌هایی که نیاز به Business Logic دارند، هر دو قابل استفاده هستند.

Payload یا Strapi برای SaaS؟

برای ساخت یک SaaS اختصاصی، Payload می‌تواند انتخاب بسیار مناسبی باشد؛ به‌خصوص اگر تیم توسعه TypeScript باشد و بخواهد Backend را به‌صورت Code-first توسعه دهد.

مثلاً:

Payload
│
├── Users
├── Organizations
├── Subscriptions
├── Plans
├── Permissions
├── Projects
└── Billing

در چنین پروژه‌ای معمولاً CMS تنها بخشی از Backend است و قابلیت توسعه و کنترل روی Business Logic اهمیت زیادی پیدا می‌کند.

اکوسیستم و Plugin

یکی از نقاط قوت Strapi، اکوسیستم و سابقه آن در دنیای Headless CMS است. برای بسیاری از نیازهای رایج می‌توان Integration یا Plugin پیدا کرد.

Payload نیز قابلیت توسعه و Integrationهای مختلفی دارد، اما اکوسیستم آن نسبت به Strapi کوچک‌تر است.

بنابراین اگر پروژه شما شدیداً به Pluginهای آماده وابسته است، Strapi ممکن است انتخاب جذاب‌تری باشد.

کدام را انتخاب کنیم؟

انتخاب نهایی را می‌توان به شکل زیر خلاصه کرد:

TypeScript + Next.js
        │
        ▼
     Payload
        ⭐⭐⭐⭐⭐

CMS آماده + Admin محور
        │
        ▼
      Strapi
        ⭐⭐⭐⭐⭐

Backend اختصاصی
        │
        ▼
     Payload

Plugin / Ecosystem
        │
        ▼
      Strapi

Mobile API
        │
   ┌────┴────┐
   │         │
Payload    Strapi
   ⭐⭐⭐⭐⭐   ⭐⭐⭐⭐⭐

SaaS
   │
   ▼
Payload

Content-heavy CMS
   │
   ▼
Payload / Strapi

مزایای Payload CMS

Payload CMS مزایای متعددی دارد که آن را به گزینه‌ای مناسب برای توسعه پروژه‌های مدرن تبدیل می‌کند. یکی از مهم‌ترین مزایای آن انعطاف‌پذیری بالا است؛ توسعه‌دهنده می‌تواند ساختار داده‌ها، Collectionها، Fieldها، APIها، سطح دسترسی کاربران و منطق اختصاصی سیستم را متناسب با نیاز پروژه طراحی کند. Payload بر پایه TypeScript و Node.js توسعه داده شده و برای تیم‌هایی که با این فناوری‌ها کار می‌کنند، تجربه توسعه یکپارچه‌ای ایجاد می‌کند. از طرف دیگر، Payload یک Headless CMS است و اطلاعات را از طریق API در اختیار Clientهای مختلف قرار می‌دهد؛ بنابراین می‌توان یک Backend مرکزی ایجاد کرد و هم‌زمان وب‌سایت، اپلیکیشن Flutter، Android یا iOS را به آن متصل کرد.

وجود Admin Panel، Authentication، Role و Access Control، Hooks و پشتیبانی از REST و GraphQL نیز باعث می‌شود بسیاری از قابلیت‌های مورد نیاز Backend در خود سیستم وجود داشته باشد. پشتیبانی مناسب از PostgreSQL و امکان استفاده از Object Storage و CDN نیز Payload را برای پروژه‌های بزرگ‌تر و محتوامحور مناسب می‌کند. همچنین ترکیب Payload با Next.js امکان ساخت یک معماری مدرن Full-stack را فراهم می‌کند که در آن مدیریت محتوا، Backend و Frontend می‌توانند در کنار یکدیگر توسعه پیدا کنند. در مجموع، مهم‌ترین مزیت Payload این است که تنها یک ابزار برای مدیریت محتوا نیست، بلکه می‌تواند به‌عنوان هسته Backend و CMS یک پروژه اختصاصی و قابل توسعه مورد استفاده قرار گیرد.

آیا Payload CMS رایگان است؟

بله، Payload CMS یک CMS متن‌باز است و می‌توان هسته اصلی آن را بدون پرداخت هزینه لایسنس استفاده کرد. این موضوع باعث شده Payload برای توسعه‌دهندگانی که قصد دارند یک CMS یا Backend اختصاصی ایجاد کنند، گزینه جذابی باشد. کد پروژه در دسترس است و می‌توان آن را روی سرور شخصی یا زیرساخت ابری خودتان نصب و اجرا کرد؛ بنابراین برخلاف برخی سرویس‌های SaaS، برای اجرای خود CMS الزاماً نیاز به پرداخت هزینه ماهانه به سازنده ندارید.

البته رایگان بودن Payload به این معنی نیست که اجرای یک پروژه مبتنی بر آن هیچ هزینه‌ای ندارد. هزینه‌هایی مانند سرور، PostgreSQL، Object Storage، CDN، دامنه، Backup و سرویس‌های جانبی می‌توانند بخشی از هزینه زیرساخت پروژه باشند. برای مثال اگر Payload را روی یک VPS شخصی اجرا کنید، هزینه اصلی مربوط به سرور و سرویس‌های زیرساختی خواهد بود، نه خرید لایسنس CMS.

یکی از مزیت‌های مهم Payload این است که می‌توانید معماری را متناسب با بودجه و اندازه پروژه انتخاب کنید. برای یک پروژه کوچک می‌توان Payload، PostgreSQL و Next.js را روی یک سرور اجرا کرد، اما برای یک پروژه بزرگ‌تر می‌توان اجزای مختلف را از یکدیگر جدا کرد:

Next.js + Payload
        │
        ├── PostgreSQL
        ├── Object Storage
        ├── CDN
        └── Backup

Payload همچنین دارای قابلیت‌ها و امکاناتی است که ممکن است بسته به نسخه و نوع استفاده، در قالب‌های مختلف ارائه شوند؛ بنابراین هنگام شروع یک پروژه تجاری بهتر است لایسنس و امکانات نسخه فعلی Payload را از مستندات رسمی بررسی کنید.

آیا Payload برای پروژه‌های بزرگ مناسب است؟

بله، Payload CMS می‌تواند برای پروژه‌های بزرگ و پرترافیک مناسب باشد؛ اما مقیاس‌پذیری پروژه فقط به انتخاب CMS وابسته نیست و به معماری کلی سیستم، طراحی Database، نحوه مدیریت فایل‌ها، Cache، CDN، زیرساخت سرور و روش Deployment نیز بستگی دارد. Payload به دلیل انعطاف‌پذیری بالا و امکان توسعه با TypeScript می‌تواند در پروژه‌هایی استفاده شود که تعداد زیادی کاربر، محتوای زیاد و API های متعدد دارند.

برای پروژه‌های بزرگ باید معماری مناسبی برای موارد زیر طراحی شود:

  • Database
  • Caching
  • CDN
  • Storage
  • API
  • Logging
  • Monitoring
  • Backup
  • Load Balancing

یک معماری پیشرفته‌تر می‌تواند به شکل زیر باشد:

                 Users
                   │
                   ▼
                  CDN
                   │
                   ▼
              Load Balancer
                   │
          ┌────────┼────────┐
          ▼        ▼        ▼
       Payload  Payload  Payload
          │        │        │
          └────────┼────────┘
                   │
                   ▼
              PostgreSQL
                   │
                   ▼
              Object Storage

Payload CMS برای برنامه‌نویسان مناسب است؟

بله، Payload CMS به‌خصوص برای برنامه‌نویسان و تیم‌های توسعه نرم‌افزار گزینه مناسبی است؛ زیرا برخلاف بسیاری از CMSهای سنتی، تمرکز زیادی روی توسعه‌دهنده، TypeScript، API و امکان سفارشی‌سازی Backend دارد. در Payload بخش قابل توجهی از ساختار پروژه از طریق کد تعریف می‌شود و برنامه‌نویس می‌تواند مدل داده، Collectionها، دسترسی کاربران، Hookها، APIها و منطق اختصاصی سیستم را کنترل کند.

یکی از مهم‌ترین مزیت‌های Payload برای برنامه‌نویسان، استفاده از TypeScript است. توسعه‌دهنده می‌تواند مدل‌های داده و Configuration مربوط به CMS را در کد تعریف کند و از قابلیت‌هایی مانند Type Safety، Autocomplete و بررسی خطا در زمان توسعه استفاده کند. این موضوع در پروژه‌های متوسط و بزرگ که تعداد زیادی Collection و رابطه بین داده‌ها وجود دارد، باعث می‌شود نگهداری و توسعه پروژه ساده‌تر شود.

Payload همچنین برای برنامه‌نویسانی که با Next.js و Node.js کار می‌کنند جذاب است. می‌توان Payload را در معماری پروژه در کنار Next.js قرار داد و یک Backend و CMS مدرن ایجاد کرد:

Next.js
   │
   ├── Frontend
   │
   └── Payload CMS
          │
          ▼
      PostgreSQL

برنامه‌نویس همچنین می‌تواند از قابلیت‌هایی مانند Hooks، Access Control، Authentication و Custom API برای پیاده‌سازی Business Logic استفاده کند. بنابراین Payload فقط برای ذخیره و نمایش محتوا نیست و می‌توان از آن برای ساخت بخش قابل توجهی از Backend یک محصول نرم‌افزاری استفاده کرد.

از طرف دیگر، Payload برای پروژه‌هایی که یک Backend باید به چند Client سرویس بدهد نیز بسیار مناسب است. برای مثال:

                 Payload API
                      │
          ┌───────────┼───────────┐
          │           │           │
       Next.js      Flutter      Android
          │           │           │
        Web App    Mobile App   Mobile App

این معماری به برنامه‌نویس اجازه می‌دهد یک Backend مرکزی ایجاد کند و APIهای آن را در چند پلتفرم مورد استفاده قرار دهد.

البته Payload برای افراد کاملاً مبتدی که هیچ تجربه‌ای در برنامه‌نویسی ندارند، لزوماً ساده‌ترین گزینه نیست. برای استفاده حرفه‌ای از آن بهتر است با JavaScript یا TypeScript، Node.js، API، Database و مفاهیم Backend آشنایی داشته باشید. هرچه پروژه پیچیده‌تر شود، دانش PostgreSQL، Authentication، امنیت، Deployment و معماری نرم‌افزار نیز اهمیت بیشتری پیدا می‌کند.

یک معماری پیشنهادی برای پروژه مدرن

برای یک پروژه مدرن که نیاز به CMS، Backend، وب‌سایت، اپلیکیشن موبایل، API، مدیریت فایل و قابلیت توسعه در آینده دارد، می‌توان از معماری مبتنی بر Payload CMS استفاده کرد. در این معماری Payload به‌عنوان هسته Backend و CMS، PostgreSQL به‌عنوان پایگاه داده، Object Storage برای فایل‌ها و CDN برای ارائه سریع محتوا مورد استفاده قرار می‌گیرند. در سمت Frontend نیز می‌توان از Next.js برای وب‌سایت و Flutter یا Native Android و iOS برای اپلیکیشن‌های موبایل استفاده کرد.

                         Users
                           │
              ┌────────────┼────────────┐
              │            │            │
           Next.js       Flutter       iOS/Android
              │            │            │
              └────────────┼────────────┘
                           │
                          API
                           │
                    ┌──────▼──────┐
                    │   Payload   │
                    │    CMS      │
                    └──────┬──────┘
                           │
          ┌────────────────┼────────────────┐
          │                │                │
          ▼                ▼                ▼
     PostgreSQL       Object Storage       Cache
          │                │                │
          │                ▼                │
          │               CDN               │
          │                                 │
          └───────────────┬─────────────────┘
                          ▼
                     Monitoring
                          │
                        Backup

در این معماری، Payload CMS مسئول مدیریت داده‌ها، کاربران، Authentication، Roleها، Access Control، Collectionها، Media و APIها است. این بخش می‌تواند Backend مرکزی پروژه باشد و تمام Clientها از طریق API با آن ارتباط داشته باشند. به این ترتیب منطق اصلی سیستم در یک Backend متمرکز قرار می‌گیرد و توسعه Clientهای جدید در آینده ساده‌تر خواهد بود.

PostgreSQL به‌عنوان Database اصلی انتخاب مناسبی برای چنین معماری‌ای است. اطلاعاتی مانند کاربران، دوره‌ها، محصولات، سفارش‌ها، مقالات، دسته‌بندی‌ها و سایر داده‌های ساختاریافته در PostgreSQL ذخیره می‌شوند. برای پروژه‌های بزرگ‌تر می‌توان Database را به سرور یا سرویس مستقلی منتقل کرد و متناسب با افزایش بار، آن را بهینه و مقیاس‌پذیر کرد.

برای فایل‌هایی مانند تصاویر، ویدئوها، فایل‌های صوتی و اسناد بهتر است از Object Storage استفاده شود. نگهداری فایل‌های حجیم روی همان سروری که Payload اجرا می‌شود، در پروژه‌های بزرگ می‌تواند باعث مصرف بیش از حد منابع شود. Object Storage امکان نگهداری مستقل فایل‌ها را فراهم می‌کند و سپس CDN می‌تواند این فایل‌ها را با سرعت بیشتری به کاربران ارائه دهد.

در بخش Frontend می‌توان از Next.js برای وب‌سایت استفاده کرد. Next.js می‌تواند از APIهای Payload داده دریافت کند و صفحات مورد نیاز را ایجاد کند. در همین حال، اپلیکیشن‌های Flutter، Android و iOS نیز می‌توانند از همان API استفاده کنند. در نتیجه یک Backend مرکزی می‌تواند به چندین پلتفرم سرویس ارائه دهد.

برای مثال در یک پلتفرم آموزشی:

                       Payload
                          │
       ┌──────────────────┼──────────────────┐
       │                  │                  │
    Courses            Users              Orders
       │                  │                  │
       └──────────────────┼──────────────────┘
                          │
                         API
                          │
            ┌─────────────┼─────────────┐
            │             │             │
         Website        Flutter       Android/iOS

در لایه زیرساخت نیز بهتر است HTTPS، Reverse Proxy، CDN، Monitoring و Backup در نظر گرفته شوند. برای مثال Nginx یا یک سرویس مشابه می‌تواند در مقابل Payload قرار بگیرد و Cloudflare یا یک CDN دیگر می‌تواند وظیفه DNS، Cache، امنیت و توزیع محتوا را بر عهده داشته باشد.

برای اجرای Payload در Production نیز می‌توان از یک Process Manager مانند PM2 استفاده کرد و در پروژه‌های بزرگ‌تر، چند Instance از Backend را پشت Load Balancer قرار داد:

                    Load Balancer
                         │
              ┌──────────┴──────────┐
              │                     │
         Payload #1             Payload #2
              │                     │
              └──────────┬──────────┘
                         │
                    PostgreSQL

مزیت اصلی این معماری جداسازی مسئولیت‌ها است. Payload وظیفه Backend و مدیریت محتوا را بر عهده دارد، PostgreSQL داده‌ها را مدیریت می‌کند، Object Storage فایل‌ها را نگهداری می‌کند، CDN محتوا را سریع‌تر به کاربران می‌رساند و Frontendها نیز مستقل از Backend توسعه پیدا می‌کنند.

چنین معماری‌ای برای پروژه‌هایی مانند پلتفرم‌های آموزشی، فروشگاه‌های اینترنتی، SaaS، سایت‌های محتوایی، سرویس‌های چندپلتفرمی و Backend اپلیکیشن‌های موبایل مناسب است و می‌توان آن را از یک پروژه کوچک شروع کرد و با افزایش کاربران و ترافیک، به‌تدریج توسعه داد.

Payload CMS؛ انتخابی مدرن برای توسعه Backend

Payload CMS در سال‌های اخیر به یکی از گزینه‌های جذاب برای توسعه پروژه‌های مدرن تبدیل شده است؛ زیرا برخلاف CMSهای سنتی، تنها به مدیریت محتوا محدود نمی‌شود و می‌تواند به‌عنوان بخشی از Backend یک محصول نرم‌افزاری مورد استفاده قرار گیرد. ترکیب Payload با TypeScript، Node.js، PostgreSQL و APIهای مدرن این امکان را فراهم می‌کند که توسعه‌دهنده یک Backend قابل توسعه ایجاد کند و در عین حال از یک پنل مدیریتی مناسب برای مدیریت داده‌ها و محتوا بهره ببرد.

یکی از مهم‌ترین ویژگی‌های Payload، رویکرد Developer-first آن است. توسعه‌دهنده می‌تواند Collectionها، Fieldها، Relationshipها، Roleها، Access Control و Hooks را مطابق نیاز پروژه تعریف کند و منطق اختصاصی سیستم را در کنار ساختار اصلی Backend قرار دهد. این انعطاف‌پذیری باعث می‌شود Payload برای پروژه‌هایی که نیاز به مدل داده اختصاصی و Business Logic پیچیده دارند، گزینه مناسبی باشد.

از طرف دیگر، معماری Headless Payload باعث می‌شود Backend از رابط کاربری مستقل باشد. برای مثال یک Payload می‌تواند هم‌زمان API مورد نیاز یک وب‌سایت Next.js، اپلیکیشن Flutter و اپلیکیشن‌های Android و iOS را تأمین کند:

                    Payload CMS
                         │
                        API
             ┌───────────┼───────────┐
             │           │           │
          Next.js      Flutter    Android/iOS
             │           │           │
           Web App    Mobile App   Mobile App

این معماری در پروژه‌های بزرگ‌تر نیز قابل توسعه است. می‌توان PostgreSQL را به‌عنوان Database اصلی، Object Storage را برای فایل‌های حجیم و CDN را برای ارائه سریع محتوا در نظر گرفت. با افزایش ترافیک نیز می‌توان بخش‌های مختلف زیرساخت را مستقل از یکدیگر Scale کرد.

Payload همچنین برای پروژه‌هایی که امنیت و کنترل دسترسی اهمیت زیادی دارند، امکانات مناسبی ارائه می‌کند. Authentication، Role، Access Control و Hooks به توسعه‌دهنده اجازه می‌دهند قوانین دسترسی و Business Logic را در سمت Backend پیاده‌سازی کند. این موضوع برای پروژه‌هایی مانند پلتفرم‌های آموزشی، SaaS، فروشگاه‌های اختصاصی و Backend اپلیکیشن‌های موبایل اهمیت زیادی دارد.

با این حال، Payload همیشه بهترین انتخاب برای همه پروژه‌ها نیست. برای یک وبلاگ ساده یا سایت شرکتی که قرار است در سریع‌ترین زمان ممکن و بدون توسعه Backend پیچیده راه‌اندازی شود، WordPress ممکن است گزینه ساده‌تر و اقتصادی‌تری باشد. Payload زمانی بیشترین ارزش خود را نشان می‌دهد که توسعه‌پذیری، کنترل روی Backend، API و معماری نرم‌افزار اهمیت داشته باشند.

جمع‌بندی

Payload CMS یک Headless CMS مدرن و توسعه‌پذیر است که می‌تواند فراتر از یک سیستم مدیریت محتوا، به‌عنوان هسته Backend یک محصول نرم‌افزاری مورد استفاده قرار گیرد. استفاده از TypeScript، Node.js و PostgreSQL در کنار قابلیت‌هایی مانند Collection، Authentication، Role و Access Control، Hooks و API باعث می‌شود توسعه‌دهنده بتواند ساختار داده و منطق پروژه را متناسب با نیاز خود طراحی کند.

یکی از مهم‌ترین نقاط قوت Payload، امکان استفاده از یک Backend مشترک برای وب‌سایت، اپلیکیشن موبایل و سایر Clientها است. ترکیب Payload با Next.js برای وب، Flutter یا Native برای موبایل و PostgreSQL برای ذخیره داده‌ها می‌تواند معماری مناسبی برای پروژه‌های مدرن ایجاد کند. همچنین استفاده از Object Storage و CDN برای مدیریت فایل‌ها، بهبود Performance و مقیاس‌پذیری پروژه را امکان‌پذیر می‌کند.

Payload برای پروژه‌هایی مانند پلتفرم‌های آموزشی، SaaS، فروشگاه‌های اختصاصی، سایت‌های محتوایی، Backend اپلیکیشن‌های موبایل و محصولات چندپلتفرمی گزینه مناسبی است. با این حال، برای یک سایت ساده که تنها به امکانات آماده و مدیریت محتوای سنتی نیاز دارد، WordPress ممکن است انتخاب سریع‌تر و ساده‌تری باشد.

سوالات متداول Payload CMS

Payload CMS چیست؟

Payload یک Headless CMS متن‌باز و قابل توسعه است که با TypeScript و اکوسیستم Node.js توسعه داده شده و برای مدیریت محتوا، ساخت API، احراز هویت و ایجاد Backend کاربرد دارد.

آیا Payload CMS رایگان است؟

Payload یک پروژه متن‌باز است و می‌توان آن را به صورت Self-hosted استفاده کرد. با این حال هزینه‌هایی مانند سرور، دیتابیس، Storage و Backup ممکن است وجود داشته باشد.

آیا Payload به PostgreSQL متصل می‌شود؟

بله. Payload از دیتابیس‌های مدرن پشتیبانی می‌کند و PostgreSQL یکی از گزینه‌های مناسب برای پروژه‌های Production است.

آیا Payload برای Next.js مناسب است؟

بله. Payload و Next.js هر دو در اکوسیستم TypeScript/React قرار دارند و می‌توان از آنها برای ساخت پروژه‌های مدرن Full-stack استفاده کرد.

آیا می‌توان از Payload برای اپلیکیشن موبایل استفاده کرد؟

بله. اپلیکیشن‌های Android، iOS و Flutter می‌توانند از APIهای Payload برای دریافت و ارسال اطلاعات استفاده کنند.

آیا Payload جایگزین WordPress است؟

در برخی پروژه‌ها بله، اما فلسفه این دو کاملاً یکسان نیست. WordPress برای راه‌اندازی سریع سایت‌های محتوایی و استفاده از اکوسیستم عظیم افزونه‌ها بسیار مناسب است، در حالی که Payload برای توسعه‌دهندگانی که به دنبال یک Headless CMS مدرن و قابل سفارشی‌سازی هستند گزینه جذابی است.

آیا Payload برای پروژه‌های بزرگ مناسب است؟

بله، اما برای پروژه‌های بزرگ باید معماری زیرساخت، دیتابیس، Cache، CDN، Storage، Backup و Monitoring نیز به شکل صحیح طراحی شود.

آیا برای استفاده از Payload باید برنامه‌نویسی بلد باشیم؟

برای استفاده حرفه‌ای و سفارشی‌سازی Payload، آشنایی با TypeScript، Node.js، React و دیتابیس بسیار مفید است.

آیا Payload API دارد؟

بله. Payload امکان استفاده از API را برای دسترسی به Collectionها و داده‌های سیستم فراهم می‌کند و می‌توان از آن برای اتصال Frontendها و اپلیکیشن‌های مختلف استفاده کرد.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *