JSTAcademy
0 XP
Dashboard
Crash Courses
Rich Text with Lexical
11 min
Masters+175 XP
Crash Courses · Masters

Rich Text with Lexical

Build flexible content with Payload's Lexical rich text editor and custom blocks.
11 min read+175 XP on completionCert: Payload CMS Crash Course
Tap any word in the text below to start reading from there.

Rich Text with Lexical

Payload's Lexical editor outputs structured JSON. You render it with the RichTextContent component or serialize it yourself.

Configure Lexical

// payload.config.ts
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import {
  BoldFeature, ItalicFeature, UnderlineFeature,
  HeadingFeature, BlockquoteFeature, CodeFeature,
  LinkFeature, UploadFeature, BlocksFeature,
} from '@payloadcms/richtext-lexical'

export default buildConfig({
  editor: lexicalEditor({
    features: [
      BoldFeature(), ItalicFeature(), UnderlineFeature(),
      HeadingFeature({ enabledHeadingSizes: ['h2', 'h3'] }),
      BlockquoteFeature(), CodeFeature(),
      LinkFeature({ enabledCollections: ['posts', 'pages'] }),
      UploadFeature({ collections: { media: { fields: [] } } }),
    ],
  }),
})

Blocks Field

// Block definition
const CallToAction: Block = {
  slug: 'cta',
  fields: [
    { name: 'heading', type: 'text', required: true },
    { name: 'buttonText', type: 'text', required: true },
    { name: 'buttonUrl', type: 'text', required: true },
    { name: 'style', type: 'select', options: ['primary', 'secondary'] },
  ],
}

// Use in a collection
{
  name: 'layout',
  type: 'blocks',
  blocks: [CallToAction, HeroBlock, QuoteBlock],
}

Render Rich Text in Next.js

import { RichText } from '@payloadcms/richtext-lexical/react'

export function PostContent({ content }: { content: any }) {
  return (
    <div className="prose prose-lg max-w-none">
      <RichText data={content} />
    </div>
  )
}

Render Blocks

function LayoutRenderer({ blocks }: { blocks: any[] }) {
  return (
    <div>
      {blocks.map((block, i) => {
        switch (block.blockType) {
          case 'cta': return <CTABlock key={i} {...block} />
          case 'hero': return <HeroBlock key={i} {...block} />
          default: return null
        }
      })}
    </div>
  )
}
0%