---
title: "Rich Text — Converting to Plaintext"
aliases: [lexical-to-plaintext, convert-richtext-plaintext]
tags: [payloadcms, lexical, rich-text, plaintext, converters]
sources: [raw/rich-text__converting-plaintext.md]
created: 2026-05-15
updated: 2026-05-15
---

## Overview

`@payloadcms/richtext-lexical/plaintext` provides `convertLexicalToPlaintext` to strip Lexical JSON down to a plain string — useful for search indexing, excerpts, or email previews.

## Basic Usage

```ts
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
import { convertLexicalToPlaintext } from '@payloadcms/richtext-lexical/plaintext'

const data: SerializedEditorState = { /* your richtext data */ }

const plaintext = convertLexicalToPlaintext({ data })
```

## Custom Converters

Pass a `converters` object to override how specific node types are rendered.

```ts
import type { DefaultNodeTypes, SerializedBlockNode } from '@payloadcms/richtext-lexical'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
import type { MyTextBlock } from '@/payload-types'
import {
  convertLexicalToPlaintext,
  type PlaintextConverters,
} from '@payloadcms/richtext-lexical/plaintext'

const converters: PlaintextConverters<
  DefaultNodeTypes | SerializedBlockNode<MyTextBlock>
> = {
  blocks: {
    textBlock: ({ node }) => node.fields.text ?? '',
  },
  link: ({ node }) => node.fields.url ?? '',
}

const plaintext = convertLexicalToPlaintext({ converters, data })
```

## Fallback Heuristics

Unlike HTML/JSX/Markdown converters, **there are no built-in default converters** for plaintext. For nodes without a defined converter, the following heuristics apply in order:

| Node has… | Behavior |
|-----------|----------|
| `text` field | Use it as plaintext |
| `children` field | Recursively convert children |
| Neither | Ignored (node produces no output) |

Special nodes:
- **Paragraph** → inserts a newline (`\n`)
- **Text** → inserts the text value
- **Tab** → inserts a tab character (`\t`)

## Key Takeaways

- Import from `@payloadcms/richtext-lexical/plaintext` (separate entrypoint).
- No default converters — you must handle custom block/node types yourself or rely on the fallback heuristics.
- Fallback order: `text` field → `children` (recursive) → ignored.
- Paragraph/text/tab nodes emit `\n` / text / `\t` automatically.
- Use `PlaintextConverters<DefaultNodeTypes | SerializedBlockNode<YourBlock>>` for TypeScript-safe custom converters.
- Common use cases: full-text search indexing, email body generation, excerpt/preview generation.

## Related

- [[wiki/payloadcms/rich-text-converters|Rich Text — Converters Overview]] — HTML, JSX, Markdown, Plaintext converter architecture
- [[wiki/payloadcms/rich-text-converting-html|Rich Text — Converting HTML]] — `convertLexicalToHTML` and `convertHTMLToLexical`
- [[wiki/payloadcms/rich-text-converting-jsx|Rich Text — Converting to JSX]] — `RichText` component and custom JSX converters
- [[wiki/payloadcms/rich-text-converting-markdown|Rich Text — Converting Markdown]] — Markdown ↔ Lexical round-trip

## Sources

- `raw/rich-text__converting-plaintext.md`
- https://payloadcms.com/docs/rich-text/converting-plaintext
