tiptap by jezweb/claude-skills
npx skills add https://github.com/jezweb/claude-skills --skill tiptap状态:生产就绪 最后更新: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)
npm install @tiptap/react @tiptap/starter-kit @tiptap/pm @tiptap/extension-image @tiptap/extension-color @tiptap/extension-text-style @tiptap/extension-typography
为何重要:
@tiptap/pm 是必需的 peer 依赖项 (ProseMirror 引擎)重要提示:如果使用 Tiptap v3.14.0+,拖拽手柄功能需要最低 v3.14.0 (该版本修复了回归问题)。对于带有拖拽手柄的 Pro 扩展,由于 tippyjs-react 依赖项,推荐使用 React 18。
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} />
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
关键点:
immediatelyRender: false (防止水合不匹配)immediatelyRender explicitly to false"npm install @tailwindcss/typography
更新您的 tailwind.config.ts:
import typography from '@tailwindcss/typography'
export default {
plugins: [typography],
}
为何重要:
.tiptap 选择器的自定义 Tailwind 类选项 A:shadcn 最小化 Tiptap 组件 (推荐)
安装预构建的 shadcn 组件:
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 样式要点:
扩展为您的编辑器添加功能:
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 负载模式:Base64 预览 → 后台上传 → 替换为 URL
完整实现参见 templates/image-upload-r2.tsx:
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. 将 base64 替换为永久 URL
editor.chain()
.focus()
.updateAttributes('image', { src: url })
.run()
return url
}
为何使用此模式:
✅ 为 SSR 应用在 useEditor() 中设置 immediatelyRender: false ✅ 安装 @tailwindcss/typography 以获得散文样式 ✅ 对图像使用上传处理程序 (而非 base64) ✅ 记忆化编辑器配置以防止重新渲染 ✅ 包含 @tiptap/pm peer 依赖项
❌ 在 Next.js/SSR 中使用 immediatelyRender: true (默认值) ❌ 将图像作为 base64 存储在数据库中 (上传后使用 URL) ❌ 忘记向编辑器容器添加 prose 类 ❌ 在协作模式下加载超过 100 个小部件 ❌ 使用 Create React App (v3 不兼容 - 使用 Vite)
此技能预防 7 个已记录的问题:
错误:"SSR has been detected, please set immediatelyRender explicitly to false" 来源:GitHub Issue #5856, #5602 发生原因:默认 immediatelyRender: true 会破坏 Next.js 水合 预防措施:模板默认包含 immediatelyRender: false
错误:打字卡顿,大型文档性能差 来源:Tiptap Performance Docs 发生原因:useEditor() 钩子在每次更改时重新渲染组件 预防措施:使用 useEditorState() 钩子或记忆化模式 (参见模板)
错误:标题/列表渲染无样式,格式化不可见 来源:shadcn Tiptap Discussion 发生原因:缺少 @tailwindcss/typography 插件 预防措施:技能清单中包含排版插件安装
错误:JSON 负载变为兆字节,保存缓慢,数据库膨胀 来源:Tiptap Image Docs 发生原因:默认允许 base64,未配置上传处理程序 预防措施:带有 URL 替换模式的 R2 上传模板
错误:升级到 v3 后出现 "jsx-runtime" 模块解析错误 来源:GitHub Issue #6812 发生原因:CRA 与 v3 模块结构不兼容 预防措施:技能文档将 Vite 作为首选打包工具并提供工作配置
错误: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 版本
// package.json
{
"resolutions": {
"prosemirror-model": "~1.21.0",
"prosemirror-view": "~1.33.0",
"prosemirror-state": "~1.4.3"
}
}
或重新安装依赖项:
rm -rf node_modules package-lock.json
npm install
注意:@tiptap/pm 包旨在防止此问题,但扩展仍可能引入冲突。
错误:SSR has been detected, please set 'immediatelyRender' explicitly to 'false' (当两者一起使用时) 来源:GitHub Issue #5856 Comment 发生原因:用户通常同时使用 EditorProvider 和 useEditor,但 EditorProvider 是用于 React Context 设置的 useEditor 包装器 - 它们不应同时使用。 预防措施:仅选择一种模式
错误模式:
// 不要同时使用两者
<EditorProvider>
<MyComponent />
</EditorProvider>
function MyComponent() {
const editor = useEditor({ ... }) // ❌ 错误 - EditorProvider 已创建编辑器
}
正确模式:
// 选项 1:仅使用 EditorProvider
<EditorProvider immediatelyRender={false} extensions={[StarterKit]}>
<EditorContent />
</EditorProvider>
// 选项 2:仅使用 useEditor
function Editor() {
const editor = useEditor({
extensions: [StarterKit],
immediatelyRender: false,
})
return <EditorContent editor={editor} />
}
/* 应用于编辑器容器 */
.tiptap {
/* Tailwind Typography */
@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 自动处理深色模式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 获取完整示例
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):
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>
)
}
何时使用:博客文章、评论、任何基于表单的内容
此技能没有可执行脚本。
所有项目必需:
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 应参考模板:
references/tiptap-docs.md - 关键文档链接references/common-errors.md - 错误故障排除指南references/extension-catalog.md - 热门扩展列表Claude 何时应加载这些:故障排除错误、探索扩展、理解 API
创建您自己的 Tiptap 扩展:
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 })
},
}
},
})
使用场景:自定义小部件、嵌入、交互式元素
添加类似 Notion 的 / 命令:
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 })]
},
})
使用场景:生产力快捷方式、快速格式化
必需:
@tiptap/react@^3.16.0 - React 集成 (支持 React 19)@tiptap/starter-kit@^3.16.0 - 基本扩展包@tiptap/pm@^3.16.0 - ProseMirror peer 依赖项react@^19.0.0 - React 框架React 版本兼容性:
可选:
@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 - 图像缩放功能{
"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"
}
}
此技能基于实际实现:
令牌节省:~71% (14k → 4k 令牌) 预防错误:7/7 个已记录错误 (5 个关键设置 + 2 个社区模式) 验证:✅ SSR 兼容性, ✅ 图像上传, ✅ Tailwind v4, ✅ 性能, ✅ React 19 兼容性
immediatelyRender explicitly to false"解决方案:在您的 useEditor() 配置中添加 immediatelyRender: false
解决方案:安装 @tailwindcss/typography 并向编辑器容器添加 prose 类
解决方案:对于只读渲染,使用 useEditorState() 钩子替代 useEditor(),或使用记忆化模式
解决方案:在 Image 扩展配置中设置 allowBase64: false 并使用上传处理程序 (参见 templates/image-upload-r2.tsx)
解决方案:切换到 Vite - CRA 与 Tiptap v3 不兼容。参见 cloudflare-worker-base 技能获取 Vite 设置。
使用此清单验证您的设置:
@tiptap/react, @tiptap/starter-kit, @tiptap/pmuseEditor() 配置中设置了 immediatelyRender: false@tailwindcss/typography 插件prose 类allowBase64: false有问题?遇到问题?
references/common-errors.md 进行故障排除immediatelyRender: false 已设置@tiptap/pm peer 依赖项已安装每周安装
478
仓库
GitHub 星标
652
首次出现
Jan 20, 2026
安全审计
安装于
claude-code386
opencode326
gemini-cli308
cursor287
codex283
antigravity262
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)
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)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.
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:
immediatelyRender: false for Next.js/SSR apps (prevents hydration mismatch)immediatelyRender explicitly to false"npm install @tailwindcss/typography
Update your tailwind.config.ts:
import typography from '@tailwindcss/typography'
export default {
plugins: [typography],
}
Why this matters:
.tiptap selectorOption A: shadcn Minimal Tiptap Component (Recommended)
Install the pre-built shadcn component:
npx shadcn@latest add https://raw.githubusercontent.com/Aslam97/shadcn-minimal-tiptap/main/registry/block-registry.json
This installs:
Option B: Build Custom Editor (Full Control)
Use templates from this skill:
templates/base-editor.tsx - Minimal editor setuptemplates/common-extensions.ts - Extension bundletemplates/tiptap-prose.css - Tailwind stylingKey Points:
Extensions add functionality to your editor:
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:
allowBase64: false to prevent huge JSON payloadsPattern : Base64 preview → background upload → replace with URL
See templates/image-upload-r2.tsx for full implementation:
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:
✅ 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
❌ 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)
This skill prevents 7 documented issues:
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
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)
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
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
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
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
// package.json
{
"resolutions": {
"prosemirror-model": "~1.21.0",
"prosemirror-view": "~1.33.0",
"prosemirror-state": "~1.4.3"
}
}
Or reinstall dependencies:
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 : 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 :
// Don't use both together
<EditorProvider>
<MyComponent />
</EditorProvider>
function MyComponent() {
const editor = useEditor({ ... }) // ❌ Wrong - EditorProvider already created editor
}
Correct Patterns :
// 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} />
}
/* 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 formattingdark:prose-invert handles dark mode automaticallyimport { 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
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):
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
No executable scripts for this skill.
Required for all projects:
templates/base-editor.tsx - Minimal React editor componenttemplates/package.json - Required dependenciesOptional based on needs:
templates/minimal-tiptap-setup.sh - shadcn component installationtemplates/image-upload-r2.tsx - R2 upload handlertemplates/tiptap-prose.css - Tailwind stylingtemplates/collaborative-setup.tsx - Y.js collaborationtemplates/common-extensions.ts - Extension bundleWhen to load these : Claude should reference templates when user asks to:
references/tiptap-docs.md - Key documentation linksreferences/common-errors.md - Error troubleshooting guidereferences/extension-catalog.md - Popular extensions listWhen Claude should load these : Troubleshooting errors, exploring extensions, understanding API
Create your own Tiptap extensions:
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
Add Notion-like / commands:
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
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 dependencyreact@^19.0.0 - React frameworkReact Version Compatibility :
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 stylingyjs@^13.6.0 - Collaborative editing backend{
"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"
}
}
This skill is based on real-world implementations:
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
immediatelyRender explicitly to false"Solution : Add immediatelyRender: false to your useEditor() config
Solution : Install @tailwindcss/typography and add prose classes to editor container
Solution : Use useEditorState() hook instead of useEditor() for read-only rendering, or memoize editor configuration
Solution : Set allowBase64: false in Image extension config and use upload handler (see templates/image-upload-r2.tsx)
Solution : Switch to Vite - CRA incompatible with Tiptap v3. See cloudflare-worker-base skill for Vite setup.
Use this checklist to verify your setup:
@tiptap/react, @tiptap/starter-kit, @tiptap/pmimmediatelyRender: false in useEditor() config@tailwindcss/typography pluginprose classes to editor containerallowBase64: false in Image extensionQuestions? Issues?
references/common-errors.md for troubleshootingimmediatelyRender: false is set@tiptap/pm peer dependency is installedWeekly Installs
478
Repository
GitHub Stars
652
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubWarnSocketPassSnykPass
Installed on
claude-code386
opencode326
gemini-cli308
cursor287
codex283
antigravity262
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
106,200 周安装
react-medium-image-zoom@^5.2.0 - Image zoom functionality