tiptap

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Tiptap Rich Text Editor

Tiptap 富文本编辑器

Status: Production Ready Last Updated: 2026-01-21 Dependencies: React 19+, Tailwind v4, shadcn/ui (recommended) Latest Versions: @tiptap/react@3.16.0, @tiptap/starter-kit@3.16.0, @tiptap/pm@3.16.0 (verified 2026-01-21)

状态: 可用于生产环境 最后更新: 2026-01-21 依赖: React 19+, Tailwind v4, shadcn/ui(推荐) 最新版本: @tiptap/react@3.16.0, @tiptap/starter-kit@3.16.0, @tiptap/pm@3.16.0(2026-01-21 已验证)

Quick Start (5 Minutes)

快速开始(5分钟)

1. Install Dependencies

1. 安装依赖

bash
npm install @tiptap/react @tiptap/starter-kit @tiptap/pm @tiptap/extension-image @tiptap/extension-color @tiptap/extension-text-style @tiptap/extension-typography
Why this matters:
  • @tiptap/pm
    is required peer dependency (ProseMirror engine)
  • StarterKit bundles 20+ essential extensions (headings, lists, bold, italic, etc.)
  • Image/color/typography are common additions not in StarterKit
Important: If using Tiptap v3.14.0+, drag handle functionality requires minimum v3.14.0 (regression fixed in that release). For Pro extensions with drag handles, React 18 is recommended due to tippyjs-react dependency.
bash
npm install @tiptap/react @tiptap/starter-kit @tiptap/pm @tiptap/extension-image @tiptap/extension-color @tiptap/extension-text-style @tiptap/extension-typography
重要性说明:
  • @tiptap/pm
    是必需的对等依赖(ProseMirror 引擎)
  • StarterKit 包含20+个核心扩展(标题、列表、粗体、斜体等)
  • 图片/颜色/排版是 StarterKit 未包含的常用扩展
注意: 如果使用 Tiptap v3.14.0+,拖拽手柄功能需要最低 v3.14.0(该版本修复了回归问题)。对于带有拖拽手柄的 Pro 扩展,推荐使用 React 18,因为 tippyjs-react 依赖的限制。

2. Create SSR-Safe Editor

2. 创建支持SSR的编辑器

typescript
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'

export function Editor() {
  const editor = useEditor({
    extensions: [StarterKit],
    content: '<p>Hello World!</p>',
    immediatelyRender: false, // ⚠️ CRITICAL for SSR/Next.js
    editorProps: {
      attributes: {
        class: 'prose prose-sm focus:outline-none min-h-[200px] p-4',
      },
    },
  })

  return <EditorContent editor={editor} />
}
CRITICAL:
  • Always set
    immediatelyRender: false
    for Next.js/SSR apps (prevents hydration mismatch)
  • Without this, you'll see: "SSR has been detected, please set
    immediatelyRender
    explicitly to
    false
    "
  • This is the #1 error reported by Tiptap users
typescript
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'

export function Editor() {
  const editor = useEditor({
    extensions: [StarterKit],
    content: '<p>Hello World!</p>',
    immediatelyRender: false, // ⚠️ 对SSR/Next.js至关重要
    editorProps: {
      attributes: {
        class: 'prose prose-sm focus:outline-none min-h-[200px] p-4',
      },
    },
  })

  return <EditorContent editor={editor} />
}
关键提示:
  • 务必设置
    immediatelyRender: false
    用于 Next.js/SSR 应用(防止水合不匹配)
  • 如果不设置,你会看到错误:"检测到SSR,请显式将
    immediatelyRender
    设置为
    false
    "
  • 这是Tiptap用户报告最多的错误

3. Add Tailwind Typography (Optional but Recommended)

3. 添加Tailwind排版(可选但推荐)

bash
npm install @tailwindcss/typography
Update your
tailwind.config.ts
:
typescript
import typography from '@tailwindcss/typography'

export default {
  plugins: [typography],
}
Why this matters:
  • Provides default prose styling for headings, lists, links, etc.
  • Without it, formatted content looks unstyled
  • Alternative: Use custom Tailwind classes with
    .tiptap
    selector

bash
npm install @tailwindcss/typography
更新你的
tailwind.config.ts
:
typescript
import typography from '@tailwindcss/typography'

export default {
  plugins: [typography],
}
重要性说明:
  • 为标题、列表、链接等提供默认文档样式
  • 不添加的话,格式化内容会显示为无样式状态
  • 替代方案:使用自定义Tailwind类配合
    .tiptap
    选择器

The 3-Step Setup Process

三步配置流程

Step 1: Choose Your Integration Method

步骤1:选择集成方式

Option A: shadcn Minimal Tiptap Component (Recommended)
Install the pre-built shadcn component:
bash
npx shadcn@latest add https://raw.githubusercontent.com/Aslam97/shadcn-minimal-tiptap/main/registry/block-registry.json
This installs:
  • Fully-featured editor component with toolbar
  • Image upload support
  • Code block with syntax highlighting
  • Typography extension configured
  • Dark mode support
Option B: Build Custom Editor (Full Control)
Use templates from this skill:
  • templates/base-editor.tsx
    - Minimal editor setup
  • templates/common-extensions.ts
    - Extension bundle
  • templates/tiptap-prose.css
    - Tailwind styling
Key Points:
  • Option A: Faster setup, opinionated UI
  • Option B: Complete customization, headless approach
  • Both work with React + Tailwind v4
选项A:shadcn极简Tiptap组件(推荐)
安装预构建的shadcn组件:
bash
npx shadcn@latest add https://raw.githubusercontent.com/Aslam97/shadcn-minimal-tiptap/main/registry/block-registry.json
此命令会安装:
  • 带工具栏的全功能编辑器组件
  • 图片上传支持
  • 带语法高亮的代码块
  • 已配置的排版扩展
  • 深色模式支持
选项B:构建自定义编辑器(完全控制)
使用本技能提供的模板:
  • templates/base-editor.tsx
    - 极简编辑器配置
  • templates/common-extensions.ts
    - 扩展包
  • templates/tiptap-prose.css
    - Tailwind样式
核心要点:
  • 选项A:配置更快,UI有预设
  • 选项B:完全自定义,无头模式
  • 两者都兼容React + Tailwind v4

Step 2: Configure Extensions

步骤2:配置扩展

Extensions add functionality to your editor:
typescript
import StarterKit from '@tiptap/starter-kit'
import Image from '@tiptap/extension-image'
import Link from '@tiptap/extension-link'
import Typography from '@tiptap/extension-typography'

const editor = useEditor({
  extensions: [
    StarterKit.configure({
      // Customize built-in extensions
      heading: {
        levels: [1, 2, 3],
      },
      bulletList: {
        keepMarks: true,
      },
    }),
    Image.configure({
      inline: true,
      allowBase64: false, // ⚠️ Prevent base64 bloat
      resize: {
        enabled: true,
        directions: ['top-right', 'bottom-right', 'bottom-left', 'top-left'],
        minWidth: 100,
        minHeight: 100,
        alwaysPreserveAspectRatio: true,
      },
    }),
    Link.configure({
      openOnClick: false,
      HTMLAttributes: {
        class: 'text-primary underline',
      },
    }),
    Typography, // Smart quotes, dashes, etc.
  ],
})
CRITICAL:
  • Set
    allowBase64: false
    to prevent huge JSON payloads
  • Use upload handler pattern (see templates/image-upload-r2.tsx)
  • Extension order matters - dependencies must load first
扩展为编辑器添加功能:
typescript
import StarterKit from '@tiptap/starter-kit'
import Image from '@tiptap/extension-image'
import Link from '@tiptap/extension-link'
import Typography from '@tiptap/extension-typography'

const editor = useEditor({
  extensions: [
    StarterKit.configure({
      // 自定义内置扩展
      heading: {
        levels: [1, 2, 3],
      },
      bulletList: {
        keepMarks: true,
      },
    }),
    Image.configure({
      inline: true,
      allowBase64: false, // ⚠️ 防止base64膨胀
      resize: {
        enabled: true,
        directions: ['top-right', 'bottom-right', 'bottom-left', 'top-left'],
        minWidth: 100,
        minHeight: 100,
        alwaysPreserveAspectRatio: true,
      },
    }),
    Link.configure({
      openOnClick: false,
      HTMLAttributes: {
        class: 'text-primary underline',
      },
    }),
    Typography, // 智能引号、破折号等
  ],
})
关键提示:
  • 设置
    allowBase64: false
    避免JSON payload过大
  • 使用上传处理模式(见templates/image-upload-r2.tsx)
  • 扩展顺序很重要 - 依赖项必须先加载

Step 3: Handle Image Uploads (If Needed)

步骤3:处理图片上传(如需)

Pattern: Base64 preview → background upload → replace with URL
See
templates/image-upload-r2.tsx
for full implementation:
typescript
import { Editor } from '@tiptap/core'

async function uploadImageToR2(file: File, env: Env): Promise<string> {
  // 1. Create base64 preview for immediate display
  const reader = new FileReader()
  const base64 = await new Promise<string>((resolve) => {
    reader.onload = () => resolve(reader.result as string)
    reader.readAsDataURL(file)
  })

  // 2. Insert preview into editor
  editor.chain().focus().setImage({ src: base64 }).run()

  // 3. Upload to R2 in background
  const formData = new FormData()
  formData.append('file', file)

  const response = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
  })

  const { url } = await response.json()

  // 4. Replace base64 with permanent URL
  editor.chain()
    .focus()
    .updateAttributes('image', { src: url })
    .run()

  return url
}
Why this pattern:
  • Immediate user feedback (preview)
  • No database bloat from base64
  • Works with Cloudflare R2
  • Graceful error handling

模式: Base64预览 → 后台上传 → 替换为URL
完整实现见
templates/image-upload-r2.tsx
:
typescript
import { Editor } from '@tiptap/core'

async function uploadImageToR2(file: File, env: Env): Promise<string> {
  // 1. 创建base64预览以立即显示
  const reader = new FileReader()
  const base64 = await new Promise<string>((resolve) => {
    reader.onload = () => resolve(reader.result as string)
    reader.readAsDataURL(file)
  })

  // 2. 将预览插入编辑器
  editor.chain().focus().setImage({ src: base64 }).run()

  // 3. 后台上传到R2
  const formData = new FormData()
  formData.append('file', file)

  const response = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
  })

  const { url } = await response.json()

  // 4. 用永久URL替换base64
  editor.chain()
    .focus()
    .updateAttributes('image', { src: url })
    .run()

  return url
}
该模式优势:
  • 即时用户反馈(预览)
  • 避免base64导致的数据库膨胀
  • 兼容Cloudflare R2
  • 优雅的错误处理

Critical Rules

关键规则

Always Do

必须执行

✅ Set
immediatelyRender: false
in
useEditor()
for SSR apps ✅ Install
@tailwindcss/typography
for prose styling ✅ Use upload handler for images (not base64) ✅ Memoize editor configuration to prevent re-renders ✅ Include
@tiptap/pm
peer dependency
✅ 为SSR应用在
useEditor()
中设置
immediatelyRender: false
✅ 安装
@tailwindcss/typography
用于文档样式 ✅ 对图片使用上传处理(而非base64) ✅ 对编辑器配置进行记忆化以防止重复渲染 ✅ 包含
@tiptap/pm
对等依赖

Never Do

禁止操作

❌ Use
immediatelyRender: true
(default) with Next.js/SSR ❌ Store images as base64 in database (use URL after upload) ❌ Forget to add
prose
classes to editor container ❌ Load more than 100 widgets in collaborative mode ❌ Use Create React App (v3 incompatible - use Vite)

❌ 在Next.js/SSR中使用默认的
immediatelyRender: true
❌ 将图片以base64形式存储在数据库中(上传后使用URL) ❌ 忘记为编辑器容器添加
prose
类 ❌ 在协同模式下加载超过100个小部件 ❌ 使用Create React App(v3不兼容 - 使用Vite)

Known Issues Prevention

已知问题预防

This skill prevents 7 documented issues:
本技能可预防7个已记录的问题:

Issue #1: SSR Hydration Mismatch

问题1:SSR水合不匹配

Error: "SSR has been detected, please set
immediatelyRender
explicitly to
false
" Source: GitHub Issue #5856, #5602 Why It Happens: Default
immediatelyRender: true
breaks Next.js hydration Prevention: Template includes
immediatelyRender: false
by default
错误信息: "检测到SSR,请显式将
immediatelyRender
设置为
false
" 来源: GitHub Issue #5856, #5602 原因: 默认的
immediatelyRender: true
会破坏Next.js水合 预防: 模板默认包含
immediatelyRender: false

Issue #2: Editor Re-renders on Every Keystroke

问题2:编辑器每次按键都重新渲染

Error: Laggy typing, poor performance in large documents Source: Tiptap Performance Docs Why It Happens:
useEditor()
hook re-renders component on every change Prevention: Use
useEditorState()
hook or memoization patterns (see templates)
错误表现: 输入卡顿,大文档中性能差 来源: Tiptap性能文档 原因:
useEditor()
钩子在每次变更时重新渲染组件 预防: 使用
useEditorState()
钩子或记忆化模式(见模板)

Issue #3: Tailwind Typography Not Working

问题3:Tailwind排版不生效

Error: Headings/lists render unstyled, no formatting visible Source: shadcn Tiptap Discussion Why It Happens: Missing
@tailwindcss/typography
plugin Prevention: Skill includes typography plugin installation in checklist
错误表现: 标题/列表无样式,看不到格式化效果 来源: shadcn Tiptap讨论 原因: 缺少
@tailwindcss/typography
插件 预防: 技能清单中包含排版插件安装步骤

Issue #4: Image Upload Base64 Bloat

问题4:图片上传导致Base64膨胀

Error: JSON payloads become megabytes, slow saves, database bloat Source: Tiptap Image Docs Why It Happens: Default allows base64, no upload handler configured Prevention: R2 upload template with URL replacement pattern
错误表现: JSON payload变为数MB,保存缓慢,数据库膨胀 来源: Tiptap图片文档 原因: 默认允许base64,未配置上传处理 预防: 带URL替换模式的R2上传模板

Issue #5: Build Errors in Create React App

问题5:Create React App中构建失败

Error: "jsx-runtime" module resolution errors after upgrading to v3 Source: GitHub Issue #6812 Why It Happens: CRA incompatibility with v3 module structure Prevention: Skill documents Vite as preferred bundler + provides working config
错误信息: "升级到v3后出现jsx-runtime模块解析错误" 来源: GitHub Issue #6812 原因: CRA与v3模块结构不兼容 预防: 技能文档推荐使用Vite作为打包工具,并提供可用配置

Issue #6: ProseMirror Multiple Versions Conflict

问题6:ProseMirror多版本冲突

Error:
Error: Looks like multiple versions of prosemirror-model were loaded
Source: GitHub Issue #577 (131 comments), Issue #6171 Why It Happens: Installing additional Tiptap extensions can pull different versions of prosemirror-model or prosemirror-view, creating duplicate dependencies in node_modules. The unique-id extension is particularly problematic in testing environments. Prevention: Use package resolutions to force a single ProseMirror version
json
// package.json
{
  "resolutions": {
    "prosemirror-model": "~1.21.0",
    "prosemirror-view": "~1.33.0",
    "prosemirror-state": "~1.4.3"
  }
}
Or reinstall dependencies:
bash
rm -rf node_modules package-lock.json
npm install
Note: The @tiptap/pm package is designed to prevent this issue, but extensions may still introduce conflicts.
错误信息:
Error: Looks like multiple versions of prosemirror-model were loaded
来源: GitHub Issue #577(131条评论), Issue #6171 原因: 安装额外的Tiptap扩展可能会引入不同版本的prosemirror-model或prosemirror-view,在node_modules中创建重复依赖。unique-id扩展在测试环境中尤其容易引发问题。 预防: 使用package resolutions强制单一ProseMirror版本
json
// package.json
{
  "resolutions": {
    "prosemirror-model": "~1.21.0",
    "prosemirror-view": "~1.33.0",
    "prosemirror-state": "~1.4.3"
  }
}
或重新安装依赖:
bash
rm -rf node_modules package-lock.json
npm install
注意: @tiptap/pm包旨在防止此问题,但扩展仍可能引入冲突。

Issue #7: EditorProvider vs useEditor Confusion (Community-sourced)

问题7:EditorProvider与useEditor混淆(社区反馈)

Error:
SSR has been detected, please set 'immediatelyRender' explicitly to 'false'
(when both used together) Source: GitHub Issue #5856 Comment Why It Happens: Users commonly use EditorProvider and useEditor together, but EditorProvider is a wrapper around useEditor for React Context setup - they should not be used simultaneously. Prevention: Choose one pattern only
Incorrect Pattern:
typescript
// Don't use both together
<EditorProvider>
  <MyComponent />
</EditorProvider>

function MyComponent() {
  const editor = useEditor({ ... }) // ❌ Wrong - EditorProvider already created editor
}
Correct Patterns:
typescript
// Option 1: Use EditorProvider only
<EditorProvider immediatelyRender={false} extensions={[StarterKit]}>
  <EditorContent />
</EditorProvider>

// Option 2: Use useEditor only
function Editor() {
  const editor = useEditor({
    extensions: [StarterKit],
    immediatelyRender: false,
  })
  return <EditorContent editor={editor} />
}

错误信息:
检测到SSR,请显式将 'immediatelyRender' 设置为 'false'
(当两者一起使用时) 来源: GitHub Issue #5856评论 原因: 用户通常同时使用EditorProvider和useEditor,但EditorProvider是useEditor的React Context包装器 - 不应同时使用。 预防: 仅选择一种模式
错误模式:
typescript
// 不要同时使用
<EditorProvider>
  <MyComponent />
</EditorProvider>

function MyComponent() {
  const editor = useEditor({ ... }) // ❌ 错误 - EditorProvider已创建编辑器
}
正确模式:
typescript
// 选项1:仅使用EditorProvider
<EditorProvider immediatelyRender={false} extensions={[StarterKit]}>
  <EditorContent />
</EditorProvider>

// 选项2:仅使用useEditor
function Editor() {
  const editor = useEditor({
    extensions: [StarterKit],
    immediatelyRender: false,
  })
  return <EditorContent editor={editor} />
}

Configuration Files Reference

配置文件参考

Tailwind Prose Styling (tiptap-prose.css)

Tailwind文档样式(tiptap-prose.css)

css
/* Apply to editor container */
.tiptap {
  /* Tailwind Typography */
  @apply prose prose-sm sm:prose-base lg:prose-lg dark:prose-invert max-w-none;

  /* Custom overrides */
  h1 {
    @apply text-3xl font-bold mt-8 mb-4;
  }

  h2 {
    @apply text-2xl font-semibold mt-6 mb-3;
  }

  p {
    @apply my-4 text-base leading-7;
  }

  ul, ol {
    @apply my-4 ml-6;
  }

  code {
    @apply bg-muted px-1.5 py-0.5 rounded text-sm font-mono;
  }

  pre {
    @apply bg-muted p-4 rounded-lg overflow-x-auto;
  }

  blockquote {
    @apply border-l-4 border-primary pl-4 italic my-4;
  }
}
Why these settings:
  • prose
    classes provide consistent formatting
  • dark:prose-invert
    handles dark mode automatically
  • Custom overrides use semantic Tailwind v4 colors

css
/* 应用于编辑器容器 */
.tiptap {
  /* Tailwind排版 */
  @apply prose prose-sm sm:prose-base lg:prose-lg dark:prose-invert max-w-none;

  /* 自定义覆盖 */
  h1 {
    @apply text-3xl font-bold mt-8 mb-4;
  }

  h2 {
    @apply text-2xl font-semibold mt-6 mb-3;
  }

  p {
    @apply my-4 text-base leading-7;
  }

  ul, ol {
    @apply my-4 ml-6;
  }

  code {
    @apply bg-muted px-1.5 py-0.5 rounded text-sm font-mono;
  }

  pre {
    @apply bg-muted p-4 rounded-lg overflow-x-auto;
  }

  blockquote {
    @apply border-l-4 border-primary pl-4 italic my-4;
  }
}
设置原因:
  • prose
    类提供一致的格式化
  • dark:prose-invert
    自动处理深色模式
  • 自定义覆盖使用语义化Tailwind v4颜色

Common Patterns

常见模式

Pattern 1: Collaborative Editing with Y.js

模式1:使用Y.js进行协同编辑

typescript
import { useEditor } from '@tiptap/react'
import Collaboration from '@tiptap/extension-collaboration'
import * as Y from 'yjs'

const ydoc = new Y.Doc()

const editor = useEditor({
  extensions: [
    StarterKit.configure({
      history: false, // Disable history for collaboration
    }),
    Collaboration.configure({
      document: ydoc,
    }),
  ],
})
When to use: Real-time multi-user editing (Notion-like) See:
templates/collaborative-setup.tsx
for full example
typescript
import { useEditor } from '@tiptap/react'
import Collaboration from '@tiptap/extension-collaboration'
import * as Y from 'yjs'

const ydoc = new Y.Doc()

const editor = useEditor({
  extensions: [
    StarterKit.configure({
      history: false, // 为协同编辑禁用历史记录
    }),
    Collaboration.configure({
      document: ydoc,
    }),
  ],
})
适用场景: 实时多用户编辑(类Notion) 查看:
templates/collaborative-setup.tsx
获取完整示例

Pattern 2: Markdown Support

模式2:Markdown支持

typescript
import { useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { Markdown } from '@tiptap/markdown'

// Load editor with markdown content
const editor = useEditor({
  extensions: [StarterKit, Markdown],
  content: '# Hello World\n\nThis is **Markdown**!',
  contentType: 'markdown',  // ⚠️ CRITICAL: Must specify or content parsed as HTML
  immediatelyRender: false,
})

// Get markdown from editor
const markdownOutput = editor.getMarkdown()

// Insert markdown content
editor.commands.setContent('## New heading', { contentType: 'markdown' })
editor.commands.insertContent('**Bold** text', { contentType: 'markdown' })
When to use: Storing content as markdown, displaying/editing rich text Install:
npm install @tiptap/markdown@3.16.0
Status: Beta (released Oct 2025, API stable but may change) CRITICAL: Always specify
contentType: 'markdown'
when setting markdown content
Recent Fixes (v3.15.0-v3.16.0):
  • Fixed incorrect Markdown output when underline is mixed with bold/italic and ranges don't fully overlap
  • Improved serialization for overlapping formatting marks
  • Source: v3.16.0 Release
typescript
import { useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { Markdown } from '@tiptap/markdown'

// 使用markdown内容加载编辑器
const editor = useEditor({
  extensions: [StarterKit, Markdown],
  content: '# Hello World\n\nThis is **Markdown**!',
  contentType: 'markdown',  // ⚠️ 关键:必须指定,否则内容会被解析为HTML
  immediatelyRender: false,
})

// 从编辑器获取markdown
const markdownOutput = editor.getMarkdown()

// 插入markdown内容
editor.commands.setContent('## New heading', { contentType: 'markdown' })
editor.commands.insertContent('**Bold** text', { contentType: 'markdown' })
适用场景: 以markdown形式存储内容,显示/编辑富文本 安装:
npm install @tiptap/markdown@3.16.0
状态: Beta版(2025年10月发布,API稳定但可能变更) 关键提示: 设置markdown内容时务必指定
contentType: 'markdown'
近期修复 (v3.15.0-v3.16.0):
  • 修复了当下划线与粗体/斜体混合且范围不完全重叠时的错误Markdown输出
  • 改进了重叠格式标记的序列化
  • 来源: v3.16.0发布说明

Pattern 3: Form Integration with react-hook-form

模式3:与react-hook-form集成

typescript
import { useForm, Controller } from 'react-hook-form'

function BlogForm() {
  const { control, handleSubmit } = useForm()

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="content"
        control={control}
        render={({ field }) => (
          <Editor
            content={field.value}
            onUpdate={({ editor }) => {
              field.onChange(editor.getHTML())
            }}
          />
        )}
      />
    </form>
  )
}
When to use: Blog posts, comments, any form-based content

typescript
import { useForm, Controller } from 'react-hook-form'

function BlogForm() {
  const { control, handleSubmit } = useForm()

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="content"
        control={control}
        render={({ field }) => (
          <Editor
            content={field.value}
            onUpdate={({ editor }) => {
              field.onChange(editor.getHTML())
            }}
          />
        )}
      />
    </form>
  )
}
适用场景: 博客文章、评论、任何基于表单的内容

Using Bundled Resources

使用捆绑资源

Scripts (scripts/)

脚本(scripts/)

No executable scripts for this skill.
本技能无可执行脚本。

Templates (templates/)

模板(templates/)

Required for all projects:
  • templates/base-editor.tsx
    - Minimal React editor component
  • templates/package.json
    - Required dependencies
Optional based on needs:
  • templates/minimal-tiptap-setup.sh
    - shadcn component installation
  • templates/image-upload-r2.tsx
    - R2 upload handler
  • templates/tiptap-prose.css
    - Tailwind styling
  • templates/collaborative-setup.tsx
    - Y.js collaboration
  • templates/common-extensions.ts
    - Extension bundle
When to load these: Claude should reference templates when user asks to:
  • Set up tiptap editor
  • Add image uploads
  • Configure collaborative editing
  • Style with Tailwind prose
所有项目必需:
  • templates/base-editor.tsx
    - 极简React编辑器组件
  • templates/package.json
    - 必需依赖
根据需求可选:
  • templates/minimal-tiptap-setup.sh
    - shadcn组件安装脚本
  • templates/image-upload-r2.tsx
    - R2上传处理
  • templates/tiptap-prose.css
    - Tailwind样式
  • templates/collaborative-setup.tsx
    - Y.js协同编辑
  • templates/common-extensions.ts
    - 扩展包
何时使用这些模板: 当用户要求以下操作时,Claude应参考模板:
  • 配置tiptap编辑器
  • 添加图片上传
  • 配置协同编辑
  • 使用Tailwind文档样式

References (references/)

参考资料(references/)

  • references/tiptap-docs.md
    - Key documentation links
  • references/common-errors.md
    - Error troubleshooting guide
  • references/extension-catalog.md
    - Popular extensions list
When Claude should load these: Troubleshooting errors, exploring extensions, understanding API

  • references/tiptap-docs.md
    - 关键文档链接
  • references/common-errors.md
    - 错误排查指南
  • references/extension-catalog.md
    - 热门扩展列表
何时使用这些参考资料: 排查错误、探索扩展、理解API

Advanced Topics

高级主题

Custom Extensions

自定义扩展

Create your own Tiptap extensions:
typescript
import { Node } from '@tiptap/core'

const CustomNode = Node.create({
  name: 'customNode',

  group: 'block',

  content: 'inline*',

  parseHTML() {
    return [{ tag: 'div[data-custom]' }]
  },

  renderHTML({ HTMLAttributes }) {
    return ['div', { 'data-custom': '', ...HTMLAttributes }, 0]
  },

  addCommands() {
    return {
      insertCustomNode: () => ({ commands }) => {
        return commands.insertContent({ type: this.name })
      },
    }
  },
})
Use cases: Custom widgets, embeds, interactive elements
创建自己的Tiptap扩展:
typescript
import { Node } from '@tiptap/core'

const CustomNode = Node.create({
  name: 'customNode',

  group: 'block',

  content: 'inline*',

  parseHTML() {
    return [{ tag: 'div[data-custom]' }]
  },

  renderHTML({ HTMLAttributes }) {
    return ['div', { 'data-custom': '', ...HTMLAttributes }, 0]
  },

  addCommands() {
    return {
      insertCustomNode: () => ({ commands }) => {
        return commands.insertContent({ type: this.name })
      },
    }
  },
})
适用场景: 自定义小部件、嵌入内容、交互元素

Slash Commands

斜杠命令

Add Notion-like
/
commands:
typescript
import { Extension } from '@tiptap/core'
import Suggestion from '@tiptap/suggestion'

const SlashCommands = Extension.create({
  name: 'slashCommands',

  addOptions() {
    return {
      suggestion: {
        char: '/',
        items: ({ query }) => {
          return [
            { title: 'Heading 1', command: ({ editor, range }) => {
              editor.chain().focus().deleteRange(range).setHeading({ level: 1 }).run()
            }},
            { title: 'Bullet List', command: ({ editor, range }) => {
              editor.chain().focus().deleteRange(range).toggleBulletList().run()
            }},
          ]
        },
      },
    }
  },

  addProseMirrorPlugins() {
    return [Suggestion({ editor: this.editor, ...this.options.suggestion })]
  },
})
Use cases: Productivity shortcuts, quick formatting

添加类Notion的
/
命令:
typescript
import { Extension } from '@tiptap/core'
import Suggestion from '@tiptap/suggestion'

const SlashCommands = Extension.create({
  name: 'slashCommands',

  addOptions() {
    return {
      suggestion: {
        char: '/',
        items: ({ query }) => {
          return [
            { title: 'Heading 1', command: ({ editor, range }) => {
              editor.chain().focus().deleteRange(range).setHeading({ level: 1 }).run()
            }},
            { title: 'Bullet List', command: ({ editor, range }) => {
              editor.chain().focus().deleteRange(range).toggleBulletList().run()
            }},
          ]
        },
      },
    }
  },

  addProseMirrorPlugins() {
    return [Suggestion({ editor: this.editor, ...this.options.suggestion })]
  },
})
适用场景: 生产力快捷方式、快速格式化

Dependencies

依赖

Required:
  • @tiptap/react@^3.16.0
    - React integration (React 19 supported)
  • @tiptap/starter-kit@^3.16.0
    - Essential extensions bundle
  • @tiptap/pm@^3.16.0
    - ProseMirror peer dependency
  • react@^19.0.0
    - React framework
React Version Compatibility:
  • Core Tiptap: Supports React 19 as of v2.10.0
  • UI Components: Work best with React 18 (Next.js 15 recommended per official docs)
  • Pro Extensions: May require React 18 - drag-handle extension depends on archived tippyjs-react without React 19 support (Issue #5876)
Optional:
  • @tiptap/extension-audio@^3.16.0
    - Audio support (NEW in v3.16.0)
  • @tiptap/extension-image@^3.16.0
    - Image support
  • @tiptap/extension-link@^3.16.0
    - Link support (NEW in v3, included in StarterKit)
  • @tiptap/extension-color@^3.16.0
    - Text color
  • @tiptap/extension-typography@^3.16.0
    - Smart typography
  • @tiptap/extension-collaboration@^3.16.0
    - Real-time collaboration
  • @tiptap/extension-markdown@^3.16.0
    - Markdown support (Beta)
  • @tailwindcss/typography@^0.5.19
    - Prose styling
  • yjs@^13.6.0
    - Collaborative editing backend
  • react-medium-image-zoom@^5.2.0
    - Image zoom functionality

必需:
  • @tiptap/react@^3.16.0
    - React集成(支持React 19)
  • @tiptap/starter-kit@^3.16.0
    - 核心扩展包
  • @tiptap/pm@^3.16.0
    - ProseMirror对等依赖
  • react@^19.0.0
    - React框架
React版本兼容性:
  • 核心Tiptap: 从v2.10.0开始支持React 19
  • UI组件: 与React 18配合最佳(根据官方文档推荐使用Next.js 15)
  • Pro扩展: 可能需要React 18 - 拖拽手柄扩展依赖已归档的tippyjs-react,不支持React 19 (Issue #5876)
可选:
  • @tiptap/extension-audio@^3.16.0
    - 音频支持(v3.16.0新增)
  • @tiptap/extension-image@^3.16.0
    - 图片支持
  • @tiptap/extension-link@^3.16.0
    - 链接支持(v3新增,包含在StarterKit中)
  • @tiptap/extension-color@^3.16.0
    - 文本颜色
  • @tiptap/extension-typography@^3.16.0
    - 智能排版
  • @tiptap/extension-collaboration@^3.16.0
    - 实时协同编辑
  • @tiptap/extension-markdown@^3.16.0
    - Markdown支持(Beta版)
  • @tailwindcss/typography@^0.5.19
    - 文档样式
  • yjs@^13.6.0
    - 协同编辑后端
  • react-medium-image-zoom@^5.2.0
    - 图片缩放功能

Official Documentation

官方文档

Package Versions (Verified 2026-01-21)

包版本(2026-01-21已验证)

json
{
  "dependencies": {
    "@tiptap/react": "^3.16.0",
    "@tiptap/starter-kit": "^3.16.0",
    "@tiptap/pm": "^3.16.0",
    "@tiptap/extension-audio": "^3.16.0",
    "@tiptap/extension-image": "^3.16.0",
    "@tiptap/extension-color": "^3.16.0",
    "@tiptap/extension-text-style": "^3.16.0",
    "@tiptap/extension-typography": "^3.16.0",
    "@tiptap/extension-link": "^3.16.0",
    "@tiptap/extension-markdown": "^3.16.0"
  },
  "devDependencies": {
    "@tailwindcss/typography": "^0.5.19",
    "react": "^19.2.3",
    "react-dom": "^19.2.3"
  }
}

json
{
  "dependencies": {
    "@tiptap/react": "^3.16.0",
    "@tiptap/starter-kit": "^3.16.0",
    "@tiptap/pm": "^3.16.0",
    "@tiptap/extension-audio": "^3.16.0",
    "@tiptap/extension-image": "^3.16.0",
    "@tiptap/extension-color": "^3.16.0",
    "@tiptap/extension-text-style": "^3.16.0",
    "@tiptap/extension-typography": "^3.16.0",
    "@tiptap/extension-link": "^3.16.0",
    "@tiptap/extension-markdown": "^3.16.0"
  },
  "devDependencies": {
    "@tailwindcss/typography": "^0.5.19",
    "react": "^19.2.3",
    "react-dom": "^19.2.3"
  }
}

Production Example

生产示例

This skill is based on real-world implementations:
  • GitLab: Uses Tiptap for issue/MR descriptions
  • Statamic CMS: Tiptap as default rich text editor
  • shadcn minimal-tiptap: 3.14M downloads/week
Token Savings: ~71% (14k → 4k tokens) Errors Prevented: 7/7 documented errors (5 critical setup + 2 community patterns) Validation: ✅ SSR compatibility, ✅ Image uploads, ✅ Tailwind v4, ✅ Performance, ✅ React 19 compatibility

本技能基于真实世界的实现:
  • GitLab: 使用Tiptap处理议题/MR描述
  • Statamic CMS: Tiptap作为默认富文本编辑器
  • shadcn minimal-tiptap: 每周314万次下载
Token节省: ~71%(14k → 4k tokens) 预防错误: 7/7已记录错误(5个关键配置 + 2个社区模式) 验证: ✅ SSR兼容性, ✅ 图片上传, ✅ Tailwind v4, ✅ 性能, ✅ React 19兼容性

Troubleshooting

故障排除

Problem: "SSR has been detected, please set
immediatelyRender
explicitly to
false
"

问题: "检测到SSR,请显式将
immediatelyRender
设置为
false
"

Solution: Add
immediatelyRender: false
to your
useEditor()
config
解决方案: 在
useEditor()
配置中添加
immediatelyRender: false

Problem: Headings/lists look unstyled

问题: 标题/列表显示无样式

Solution: Install
@tailwindcss/typography
and add
prose
classes to editor container
解决方案: 安装
@tailwindcss/typography
并为编辑器容器添加
prose

Problem: Editor lags when typing

问题: 输入时编辑器卡顿

Solution: Use
useEditorState()
hook instead of
useEditor()
for read-only rendering, or memoize editor configuration
解决方案: 对于只读渲染,使用
useEditorState()
钩子替代
useEditor()
,或对编辑器配置进行记忆化

Problem: Images make JSON huge

问题: 图片导致JSON过大

Solution: Set
allowBase64: false
in Image extension config and use upload handler (see templates/image-upload-r2.tsx)
解决方案: 在Image扩展配置中设置
allowBase64: false
并使用上传处理(见templates/image-upload-r2.tsx)

Problem: Build fails in Create React App

问题: Create React App中构建失败

Solution: Switch to Vite - CRA incompatible with Tiptap v3. See cloudflare-worker-base skill for Vite setup.

解决方案: 切换到Vite - CRA与Tiptap v3不兼容。查看cloudflare-worker-base技能获取Vite配置。

Complete Setup Checklist

完整配置清单

Use this checklist to verify your setup:
  • Installed
    @tiptap/react
    ,
    @tiptap/starter-kit
    ,
    @tiptap/pm
  • Set
    immediatelyRender: false
    in
    useEditor()
    config
  • Installed
    @tailwindcss/typography
    plugin
  • Added
    prose
    classes to editor container
  • Configured image upload handler (if using images)
  • Set
    allowBase64: false
    in Image extension
  • Editor renders without hydration errors
  • Formatted text displays correctly (headings, lists, etc.)
  • Dev server runs without TypeScript errors
  • Production build succeeds

Questions? Issues?
  1. Check
    references/common-errors.md
    for troubleshooting
  2. Verify
    immediatelyRender: false
    is set
  3. Check official docs: https://tiptap.dev
  4. Ensure
    @tiptap/pm
    peer dependency is installed
使用此清单验证你的配置:
  • 已安装
    @tiptap/react
    ,
    @tiptap/starter-kit
    ,
    @tiptap/pm
  • useEditor()
    配置中设置了
    immediatelyRender: false
  • 已安装
    @tailwindcss/typography
    插件
  • 已为编辑器容器添加
    prose
  • 已配置图片上传处理(如果使用图片)
  • 在Image扩展中设置了
    allowBase64: false
  • 编辑器无错渲染,无水合错误
  • 格式化文本正确显示(标题、列表等)
  • 开发服务器运行无TypeScript错误
  • 生产构建成功

有疑问?遇到问题?
  1. 查看
    references/common-errors.md
    进行故障排除
  2. 验证
    immediatelyRender: false
    是否已设置
  3. 查看官方文档: https://tiptap.dev
  4. 确保已安装
    @tiptap/pm
    对等依赖