---
name: payload-lexical-integration
description: แนวทางการรวม Payload CMS Lexical richText content กับ design system components — อธิบายว่าทำไม design skill output กับ Payload content ถึงอยู่คนละ layer และวิธี integrate มันเข้าด้วยกัน
category: software-development
---
# Payload Lexical Integration
## ปัญหา
เวลาใช้ design skill (ui-ux-pro-max) กับ Payload CMS มักเกิดความสับสน:
- Design skill ให้โค้ดแบบไหน?
- Payload Lexical เก็บ content ยังไง?
- ทำไม content ไม่แสดงหลังสร้าง fields เสร็จ?
## สิ่งที่ต้องเข้าใจก่อน
### Two Layers — แยกกันทำ
```
┌─────────────────────────────────────────────────────────┐
│ DESIGN LAYER (ui-ux-pro-max, ckm:design, ckm:ui-styling)│
│ • Component structure (Hero, Card, Navbar) │
│ • Color tokens, typography, spacing │
│ • Animation specs (150-300ms, ease-out) │
│ • Layout grid, responsive breakpoints │
│ • Interaction states │
│ │
│ Output: React + Tailwind code — "ภาชนะ" ไม่ใช่ "เนื้อหา"│
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ CONTENT LAYER (Payload CMS) │
│ • ข้อความ + format (bold, italic, link) │
│ • Headings (H1-H6) │
│ • Lists, blockquotes, code blocks │
│ • Images, links │
│ • Tables │
│ │
│ Output: Lexical JSON — "เนื้อหา" ไม่ใช่ "ภาชนะ" │
└─────────────────────────────────────────────────────────┘
```
**Design skill สร้าง "ภาชนะ" — Payload สร้าง "เนื้อหา" — ต้องรวมกันตอน render**
---
## ขั้นตอน
```
[1] Design Phase
ui-ux-pro-max → Component structure, tokens, animations
Output: Component skeleton (ไม่มี content)
↓
[2] Payload Phase
สร้าง Collections + richText Fields
Output: Content structure ใน Payload
↓
[3] Content Phase
พิมพ์ content ใน /admin (Lexical visual editor)
Output: Lexical JSON
↓
[4] Integration Phase
ครอบ Payload content ด้วย Design components
```
---
## Step 1: Payload Collection
กำหนด content fields ตาม section:
```ts
// src/collections/Posts.ts
const Posts: CollectionConfig = {
slug: 'posts',
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'slug', type: 'text', required: true },
{ name: 'heroContent', type: 'richText' }, // content สำหรับ Hero
{ name: 'features', type: 'array',
fields: [
{ name: 'heading', type: 'text' },
{ name: 'content', type: 'richText' }, // content ในแต่ละ card
]
},
{ name: 'testimonial', type: 'richText' },
{ name: 'featuredImage', type: 'upload', relationTo: 'media' },
{ name: 'status', type: 'select', options: [...], defaultValue: 'draft' },
],
}
```
---
## Step 2: สร้าง Payload Helpers
```ts
// src/lib/payload-helpers.ts
import { getPayload } from 'payload'
import config from '@/payload.config'
export async function getPost(slug: string) {
const p = await getPayload({ config })
const { docs } = await p.find({
collection: 'posts',
where: { slug: { equals: slug } },
depth: 2,
})
return docs[0] ?? null
}
export async function getAllPosts() {
const p = await getPayload({ config })
return p.find({
collection: 'posts',
where: { status: { equals: 'published' } },
depth: 1,
})
}
```
---
## Step 3: Integration — Design Component + RichText
```tsx
// src/app/(frontend)/posts/[slug]/page.tsx
import { getPost } from '@/lib/payload-helpers'
import { RichText } from '@payloadcms/richtext-lexical'
// Design tokens จาก ui-ux-pro-max
const tokens = {
hero: 'text-5xl md:text-7xl font-bold tracking-tight',
section: 'py-20 px-6 max-w-7xl mx-auto',
card: 'rounded-2xl border border-slate-200 p-6 shadow-sm',
animate: 'animate-fade-in duration-300 ease-out',
}
// Design component ครอบ Payload richText
function HeroSection({ title, content }: { title: string; content: any }) {
return (
{title}
{content && (
Amazing content here...
// hardcode