Back to skills
SKILL.md
Rich Text Editor Expert
ASecurityRich text editors integration (Tiptap, Lexical) & collaboration / Integrasi editor rich text (Tiptap, Lexical) dan kolaborasi.
- 125 stars
- 0 votes
- 0 copies
- 0 views
- Added November 12, 2026
Works with
Security analysis
100/100npx -y skills add roedyrustam/vibes-plug --skill rich-text-editor-expert --agent claude-codeAre you the author of Rich Text Editor Expert?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/roedyrustam-rich-text-editor-expert-vibes-plug)---
name: rich-text-editor-expert
description: "Rich text editors integration (Tiptap, Lexical) & collaboration / Integrasi editor rich text (Tiptap, Lexical) dan kolaborasi."
author: "Roedy Rustam"
version: "4.8.0"
---
# Rich Text Editor Expert (2026 Edition)
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
---
<a name="english"></a>
## English
### Orchestration & Integration
- **`design-system-architect`**: Provides accessible toolbar primitives, floating bubble menus, and surface token styling.
- **`ui-ux-pro-max`**: Typography scale, optical letter-spacing, and readable editorial prose width (`max-w-prose`).
- **`anti-slop`**: Prevents empty paragraph bloat, unstyled placeholder flashes, and dead formatting buttons.
- **`realtime-collaboration-expert`**: Yjs/Automerge CRDTs for collaborative editing.
- **`form-validation-expert`**: Form integration patterns for editor content.
- **`headless-cms-expert`**: CMS schema integration for rich text fields.
- **`file-upload-media-expert`**: Image/video embedding within editor content.
- **`senior-frontend`**: React component patterns for editor wrappers.
### Description
Expert guide for integrating production-quality rich text editors into web applications. Covers Tiptap v2 (ProseMirror-based, extensible), Lexical (Meta's framework, high-performance), and ProseMirror (low-level, maximum control). Includes custom node/mark creation, collaborative editing with Yjs, slash commands, mention systems, image/video embedding, Portable Text output, and accessibility compliance.
### Trigger Conditions
- Adding a WYSIWYG or rich text editor to an application.
- Building collaborative document editing features.
- Creating custom editor extensions (mentions, slash commands, embeds).
- Choosing between Tiptap, Lexical, or ProseMirror.
- Implementing content serialization (HTML, JSON, Markdown, Portable Text).
---
### Editor Selection Guide
| Criteria | Tiptap v2 | Lexical (Meta) | ProseMirror |
|----------|-----------|----------------|-------------|
| Abstraction Level | High | Medium | Low |
| Framework | React, Vue, vanilla | React (primary) | Vanilla JS |
| Extension Ecosystem | ★★★★★ (50+ extensions) | ★★★ (growing) | ★★★★ (community) |
| Collaboration | Yjs built-in | Yjs plugin | Yjs via prosemirror-collab |
| Performance | ★★★★ | ★★★★★ | ★★★★ |
| Learning Curve | Low-Medium | Medium-High | High |
| **Best For** | Most apps, CMS | High-scale, messaging | Custom editors |
**Recommendation:** Use **Tiptap v2** for 90% of use cases. Use **Lexical** for high-performance messaging apps. Use **ProseMirror** only when you need full low-level control.
### Core Patterns
#### 1. Tiptap v2 Setup (React)
```tsx
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Placeholder from '@tiptap/extension-placeholder';
import Image from '@tiptap/extension-image';
import Link from '@tiptap/extension-link';
import Collaboration from '@tiptap/extension-collaboration';
import * as Y from 'yjs';
const ydoc = new Y.Doc();
function RichEditor({ onUpdate }: { onUpdate: (json: object) => void }) {
const editor = useEditor({
extensions: [
StarterKit.configure({ history: false }), // Disable history for collab
Placeholder.configure({ placeholder: 'Start writing...' }),
Image.configure({ inline: true, allowBase64: false }),
Link.configure({ openOnClick: false, autolink: true }),
Collaboration.configure({ document: ydoc }),
],
onUpdate: ({ editor }) => onUpdate(editor.getJSON()),
});
return (
<div className="editor-wrapper">
<MenuBar editor={editor} />
<EditorContent editor={editor} className="prose max-w-none" />
</div>
);
}
```
#### 2. Custom Slash Command Extension (Tiptap)
```typescript
import { Extension } from '@tiptap/core';
import Suggestion from '@tiptap/suggestion';
export const SlashCommands = Extension.create({
name: 'slashCommands',
addOptions() {
return {
suggestion: {
char: '/',
items: ({ query }) => [
{ title: 'Heading 1', command: ({ editor }) => editor.chain().focus().toggleHeading({ level: 1 }).run() },
{ title: 'Bullet List', command: ({ editor }) => editor.chain().focus().toggleBulletList().run() },
{ title: 'Code Block', command: ({ editor }) => editor.chain().focus().toggleCodeBlock().run() },
{ title: 'Image', command: ({ editor }) => { /* open upload dialog */ } },
].filter((item) => item.title.toLowerCase().includes(query.toLowerCase())),
},
};
},
addProseMirrorPlugins() {
return [Suggestion({ editor: this.editor, ...this.options.suggestion })];
},
});
```
#### 3. Lexical Setup (React)
```tsx
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
import { HeadingNode, QuoteNode } from '@lexical/rich-text';
import { ListNode, ListItemNode } from '@lexical/list';
import { CodeNode } from '@lexical/code';
const editorConfig = {
namespace: 'MyEditor',
nodes: [HeadingNode, QuoteNode, ListNode, ListItemNode, CodeNode],
onError: (error: Error) => console.error(error),
theme: { /* custom theme classes */ },
};
function LexicalEditor() {
return (
<LexicalComposer initialConfig={editorConfig}>
<RichTextPlugin
contentEditable={<ContentEditable className="prose" />}
placeholder={<div className="text-gray-400">Start writing...</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
<AutoFocusPlugin />
</LexicalComposer>
);
}
```
#### 4. Content Serialization Patterns
- **JSON** (Tiptap/Lexical): Store editor state as JSON for exact restoration.
- **HTML**: Use `editor.getHTML()` for rendering in non-editor contexts.
- **Markdown**: Convert with `@tiptap/extension-markdown` for developer-facing content.
- **Portable Text** (Sanity): Map Tiptap nodes to Portable Text blocks for CMS storage.
### Production Checklist
- [ ] Content sanitization (DOMPurify) before rendering user HTML.
- [ ] Image upload with presigned URLs (not base64 in content).
- [ ] Keyboard shortcuts documented and accessible.
- [ ] Mobile-responsive toolbar (sticky or floating).
- [ ] Autosave with debounce (500ms) and conflict resolution.
- [ ] Max content length validation.
### Hard Guardrails (Declarative Invariants)
1. **Mandatory DOMPurify Sanitization Gate (Zero Raw HTML Injection)**:
- User-generated rich text markup rendered outside the editor canvas (e.g. `dangerouslySetInnerHTML`) MUST pass strict DOMPurify sanitization with explicit allowlists of tags and attributes. Injecting raw un-sanitized editor HTML into the DOM is strictly prohibited.
2. **Prohibition of Base64 Inlined Image Blobs**:
- Rich text editors MUST configure image extensions (`allowBase64: false`) to upload assets to object storage (S3/R2) via presigned URLs and store only secure HTTPS URLs. Inlining base64 data strings directly into document JSON/HTML is strictly prohibited.
3. **Structured JSON Serialization as Source of Truth**:
- Document state MUST be stored as structured JSON AST (ProseMirror JSON or Lexical state) in the database. Relying solely on HTML strings for primary storage without structured schema representations is prohibited.
4. **Debounced Autosave & Conflict Resolution Invariant**:
- Autosave listeners on editor updates MUST be debounced ($\ge 300\text{ms}$) to prevent database flooding, and MUST handle optimistic concurrency or merge conflicts via CRDTs (Yjs) in collaborative modes.
### Sovereign Execution, Token Efficiency & Invariants
| Dimension | Sovereign Mandate & Deterministic Contract |
| :--- | :--- |
| **Frontier Model Cascade** | Medium / High (`GPT-5.6 Sol Medium`, `Gemini 4 Argon`, `Claude Sonnet 5.5 High`, `Grok 4.7 High Fast`) |
| **Availability Fallback** | `Gemini 4 Argon/Pro` -> `Gemini 3.8 Flash`; `Claude Opus 5.5` -> `Claude Opus 4.6` (Zero unhandled missing-model errors) |
| **KV-Cache & Token Protocol** | Pin static instructions & schemas at prompt prefix (`kv-cache-prefix-optimizer`); pass surgical `CONTEXT_MAP.md` slices (<250 tokens/call) during Swarm Fan-Out |
| **SaaT CLI & MCP Dispatch** | CLI: `vibes skill exec rich-text-editor-expert <audit\|eval\|verify\|generate\|blueprint>` / MCP: `vibes_skill_dispatch`, `vibes_ast_query`, `vibes_compile_cache`, `vibes_optimize_budget`, `vibes_verify_gate` |
| **NFR & Anti-Slop Invariants** | 100% DOMPurify sanitization on rendered HTML (0 XSS vectors), 0 inlined base64 images in storage, autosave debounce >= 300ms; 100% complete zero-placeholder output verified via `node scripts/check-anti-slop.js --strict` |
---
---
<a name="bahasa-indonesia"></a>
## Bahasa Indonesia
### Integrasi Orkestrasi
- **`design-system-architect`**: Menyediakan primitif toolbar yang aksesibel, menu bubble melayang, dan token permukaan.
- **`ui-ux-pro-max`**: Skala tipografi, tracking huruf optik, dan lebar kolom editorial yang nyaman dibaca (`max-w-prose`).
- **`anti-slop`**: Mencegah penumpukan paragraf kosong, kedipan placeholder tak bergaya, dan tombol format tanpa fungsi nyata.
- **`realtime-collaboration-expert`**: CRDT Yjs/Automerge untuk editing dokumen kolaboratif real-time.
- **`form-validation-expert`**: Pola integrasi formulir untuk konten rich text (Zod + React Hook Form).
- **`headless-cms-expert`**: Integrasi skema CMS untuk field rich text dan Portable Text.
- **`file-upload-media-expert`**: Upload gambar/video dengan presigned URL ke dalam konten editor.
### Deskripsi
Panduan ahli untuk mengintegrasikan editor rich text berkualitas produksi ke dalam aplikasi web. Mencakup Tiptap v2 (berbasis ProseMirror, modular), Lexical (framework berperforma tinggi dari Meta), dan ProseMirror murni. Termasuk pembuatan ekstensi kustom (slash commands, mention, blockquote kustom), kolaborasi real-time dengan Yjs, sanitasi DOMPurify, dan output JSON/HTML.
### Kondisi Pemicu
- Menambahkan editor WYSIWYG atau rich text ke aplikasi SaaS.
- Membangun fitur kolaborasi pengeditan dokumen langsung antar banyak pengguna.
- Membuat ekstensi kustom seperti slash commands (`/`), tag mention (`@`), atau embedding media.
---
### Implementasi Pola Kunci (TypeScript & React)
#### 1. Konfigurasi Editor Tiptap v2 dengan Ekstensi Lengkap
```tsx
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Placeholder from '@tiptap/extension-placeholder';
import Image from '@tiptap/extension-image';
import Link from '@tiptap/extension-link';
export function EditorDokumen({ onPerubahan }: { onPerubahan: (json: object) => void }) {
const editor = useEditor({
extensions: [
StarterKit,
Placeholder.configure({ placeholder: 'Ketik "/" untuk perintah...' }),
Image.configure({ inline: true, allowBase64: false }),
Link.configure({ openOnClick: false, autolink: true }),
],
onUpdate: ({ editor }) => onPerubahan(editor.getJSON()),
});
return (
<div className="border border-slate-200 dark:border-slate-800 rounded-lg p-4 bg-white dark:bg-slate-900">
<EditorContent editor={editor} className="prose dark:prose-invert max-w-none focus:outline-none" />
</div>
);
}
```
#### 2. Sanitasi Output HTML Mencegah XSS (DOMPurify)
```typescript
import DOMPurify from 'isomorphic-dompurify';
export function bersihkanHtmlKonten(htmlMentah: string): string {
return DOMPurify.sanitize(htmlMentah, {
ALLOWED_TAGS: ['p', 'b', 'i', 'h1', 'h2', 'h3', 'ul', 'ol', 'li', 'a', 'img', 'pre', 'code'],
ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'target'],
});
}
```
### Matriks Eksekusi Berdaulat, Efisiensi Token & Invarian
| Dimensi | Mandat Berdaulat & Kontrak Deterministik |
| :--- | :--- |
| **Kaskade Model Frontier** | Medium / High (`GPT-5.6 Sol Medium`, `Gemini 4 Argon`, `Claude Sonnet 5.5 High`, `Grok 4.7 High Fast`) |
| **Invarian Fallback Ketersediaan** | `Gemini 4 Argon/Pro` -> `Gemini 3.8 Flash`; `Claude Opus 5.5` -> `Claude Opus 4.6` (Bebas gagal saat model belum tersedia/kuota penuh) |
| **Protokol Hemat Token & KV-Cache** | Kunci instruksi & skema statis di prefix awal (`kv-cache-prefix-optimizer`); kirim potongan `CONTEXT_MAP.md` (<250 token/panggilan) saat Fan-Out |
| **Eksekusi SaaT CLI & MCP** | CLI: `vibes skill exec rich-text-editor-expert <audit\|eval\|verify\|generate\|blueprint>` / MCP: `vibes_skill_dispatch`, `vibes_ast_query`, `vibes_compile_cache`, `vibes_optimize_budget`, `vibes_verify_gate` |
| **Invarian NFR & Anti-Slop** | 100% sanitasi DOMPurify pada HTML yang dirender (0 vektor XSS), 0 gambar base64 inline di penyimpanan, debounce autosave >= 300ms; kode 100% tuntas tanpa placeholder diverifikasi melalui `node scripts/check-anti-slop.js --strict` |
Attribution
Related skills
View all in ai-agents →Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.