tiptap について
tiptapは、Tiptapを使ったReactリッチテキストエディターの構築を開発者向けに案内するスキルです。セットアップ、拡張機能の設定、テンプレート、連携やパフォーマンスの問題への対処法を含みます。
主な機能
- 01Reactエディターのセットアップ案内
- 02拡張機能の設定パターン
- 03画像アップロード用テンプレート
- 04Y.jsによる共同編集
- 05Markdownとフォーム連携
- 06SSRと性能問題のトラブルシューティング
活用シーン
- 01ReactでのTiptapエディター構築
- 02エディターコンテンツへの画像アップロード追加
- 03共同編集の設定
- 04SSRまたはエディター性能問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill tiptapインストール後、Claude Code で/tiptapを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsonreferences/common-errors.mdextension-catalog.mdtiptap-docs.mdrules/tiptap.mdtemplates/base-editor.tsxcommon-extensions.tsimage-upload-r2.tsxminimal-tiptap-setup.shpackage.jsontiptap-prose.css詳細
Tiptap リッチテキストエディター
ステータス:本番環境対応 最終更新日:2026-01-21 依存関係:React 19+、Tailwind v4、shadcn/ui(推奨) 最新バージョン:@tiptap/[email protected]、@tiptap/[email protected]、@tiptap/[email protected](2026-01-21に確認済み)
クイックスタート(5分)
1. 依存関係をインストールする
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 拡張機能では、tippyjs-react の依存関係があるため、React 18を推奨します。
2. SSR に対応したエディターを作成する
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} />
}
重要:
- Next.js/SSR アプリでは、必ず
immediatelyRender: falseを設定してください(ハイドレーションの不一致を防止します)。 - これを設定しないと、次のメッセージが表示されます:「SSR has been detected, please set
immediatelyRenderexplicitly tofalse」 - これは Tiptap ユーザーから報告されるエラーの第1位です。
3. Tailwind Typography を追加する(任意ですが推奨)
npm install @tailwindcss/typography
tailwind.config.ts を更新します。
import typography from '@tailwindcss/typography'
export default {
plugins: [typography],
}
重要な理由:
- 見出し、リスト、リンクなどに標準の文章スタイルを適用します。
- これがないと、書式設定されたコンテンツのスタイルが適用されません。
- 代替方法:
.tiptapセレクターを使ってカスタム Tailwind クラスを指定します。
3ステップのセットアップ手順
ステップ1:統合方法を選択する
オプションA:shadcn の Minimal 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 のスタイル設定
要点:
- オプションA:セットアップが速く、UI の仕様があらかじめ決まっています。
- オプションB:完全にカスタマイズできるヘッドレス方式です。
- どちらも React + Tailwind v4 で動作します。
ステップ2:拡張機能を設定する
拡張機能を使って、エディターに機能を追加します。
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.
],
})
重要:
- 巨大な JSON ペイロードを防ぐため、
allowBase64: falseを設定します。 - アップロードハンドラーのパターンを使用します(
templates/image-upload-r2.tsxを参照)。 - 拡張機能の順序は重要です。依存関係を先に読み込む必要があります。
ステップ3:画像のアップロードを処理する(必要な場合)
パターン:Base64 プレビュー → バックグラウンドでアップロード → URL に置き換え
実装全体については、templates/image-upload-r2.tsx を参照してください。
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
}
このパターンを使う理由:
- ユーザーにすぐフィードバックを返せます(プレビュー)。
- Base64 によるデータベースの肥大化を防げます。
- Cloudflare R2 で動作します。
- エラーを適切に処理できます。
重要なルール
必ず行うこと
✅ SSR アプリでは useEditor() に immediatelyRender: false を設定する
✅ 文章スタイルの適用に @tailwindcss/typography をインストールする
✅ 画像には(Base64 ではなく)アップロードハンドラーを使用する
✅ 再レンダリングを防ぐため、エディターの設定をメモ化する
✅ ピア依存関係として @tiptap/pm を含める
絶対に行わないこと
❌ Next.js/SSR で immediatelyRender: true(デフォルト)を使用する
❌ データベースに画像を Base64 で保存する(アップロード後の URL を使用する)
❌ エディターのコンテナーに prose クラスを追加し忘れる
❌ コラボレーションモードで100個を超えるウィジェットを読み込む
❌ Create React App を使用する(v3と互換性がありません。Vite を使用してください)
既知の問題を防ぐ
このスキルは、報告されている7件の問題を防ぎます。
問題 #1:SSR ハイドレーションの不一致
エラー:「SSR has been detected, please set immediatelyRender explicitly to false」
ソース:GitHub Issue #5856、#5602
発生する理由:デフォルトの immediatelyRender: true によって Next.js のハイドレーションが壊れます。
防止策:テンプレートでは、デフォルトで immediatelyRender: false を設定しています。
Issue #2:キー入力ごとにエディターが再レンダリングされる
エラー:入力の遅延、大きなドキュメントでのパフォーマンス低下
ソース:Tiptap のパフォーマンスに関するドキュメント
発生する理由:useEditor() フックは変更のたびにコンポーネントを再レンダリングします
予防策:useEditorState() フックまたはメモ化のパターンを使用します(テンプレートを参照)
Issue #3:Tailwind Typography が機能しない
エラー:見出しやリストがスタイルなしで表示され、書式が反映されない
ソース:shadcn の Tiptap に関するディスカッション
発生する理由:@tailwindcss/typography プラグインが不足しています
予防策:スキルのチェックリストに、Typography プラグインのインストールが含まれています
Issue #4:画像アップロードによる Base64 の肥大化
エラー:JSON ペイロードが数メガバイトになり、保存が遅くなってデータベースが肥大化する ソース:Tiptap の画像に関するドキュメント 発生する理由:デフォルトでは Base64 が許可されており、アップロードハンドラーが設定されていません 予防策:URL 置換パターンを使用する R2 アップロードテンプレート
Issue #5:Create React App でのビルドエラー
エラー:v3 へのアップグレード後に「jsx-runtime」モジュールの解決エラーが発生する ソース:GitHub Issue #6812 発生する理由:CRA と v3 のモジュール構造に互換性がありません 予防策:スキルでは推奨バンドラーとして Vite を説明し、動作する設定を提供しています
Issue #6:ProseMirror の複数バージョンの競合
エラー: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 拡張機能は、テスト環境で特に問題を起こしやすいものです。
予防策:パッケージの解決設定を使用して、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 パッケージはこの問題を防ぐように設計されていますが、拡張機能によっては依然として競合が発生する場合があります。
Issue #7:EditorProvider と useEditor の混同(コミュニティからの報告)
エラー:SSR has been detected, please set 'immediatelyRender' explicitly to 'false'(両方を同時に使用した場合)
ソース:GitHub Issue #5856 のコメント
発生する理由:ユーザーは EditorProvider と useEditor を併用しがちですが、EditorProvider は React Context を設定するための useEditor のラッパーです。そのため、両方を同時に使用しないでください。
予防策:どちらか一方のパターンだけを選択します
誤ったパターン:
// Don't use both together
<EditorProvider>
<MyComponent />
</EditorProvider>
function MyComponent() {
const editor = useEditor({ ... }) // ❌ Wrong - EditorProvider already created editor
}
正しいパターン:
// 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} />
}
設定ファイルのリファレンス
Tailwind の Prose スタイル(tiptap-prose.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;
}
}
これらの設定を使用する理由:
proseクラスによって一貫した書式が適用されますdark:prose-invertによってダークモードが自動的に処理されます- カスタムオーバーライドでは、Tailwind v4 のセマンティックカラーを使用します
一般的なパターン
パターン 1:Y.js による共同編集
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,
}),
],
})
使用場面:リアルタイムの複数ユーザー編集(Notion のようなもの)
参照:全体の例については templates/collaborative-setup.tsx を参照してください
パターン 2:Markdown のサポート
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' })
使用場面:コンテンツを Markdown として保存し、リッチテキストを表示・編集する場合
インストール:npm install @tiptap/[email protected]
ステータス:ベータ版(2025 年 10 月リリース。API は安定していますが、変更される可能性があります)
重要:Markdown コンテンツを設定する際は、必ず contentType: 'markdown' を指定してください
最近の修正(v3.15.0-v3.16.0):
- 下線が太字や斜体と混在し、それらの範囲が完全には重ならない場合に、Markdown の出力が誤っていた問題を修正
- 書式マークが重なる場合のシリアライズを改善
- ソース:v3.16.0 リリース
パターン 3:react-hook-form を使ったフォーム連携
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>
)
}
使用する場面:ブログ記事、コメントなど、フォームベースのコンテンツ
バンドルされたリソースの使用
スクリプト(scripts/)
このスキルには実行可能なスクリプトはありません。
テンプレート(templates/)
すべてのプロジェクトで必須:
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 prose を使ったスタイリング
リファレンス(references/)
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 のピア依存関係react@^19.0.0- React フレームワーク
React バージョンの互換性:
- Tiptap コア:v2.10.0 以降、React 19 をサポート
- UI コンポーネント:React 18 で最もよく動作します(公式ドキュメントでは Next.js 15 を推奨)
- Pro 拡張機能:React 18 が必要になる場合があります。drag-handle 拡張機能は、React 19 をサポートしていないアーカイブ済みの tippyjs-react に依存しています(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 のサポート(ベータ版)@tailwindcss/typography@^0.5.19- prose のスタイリングyjs@^13.6.0- 共同編集のバックエンドreact-medium-image-zoom@^5.2.0- 画像のズーム機能
公式ドキュメント
- Tiptap:https://tiptap.dev
- インストールガイド:https://tiptap.dev/docs/editor/installation/react
- 拡張機能:https://tiptap.dev/docs/editor/extensions
- API リファレンス:https://tiptap.dev/docs/editor/api/editor
- shadcn minimal-tiptap:https://github.com/Aslam97/shadcn-minimal-tiptap
- Context7 ライブラリ ID:tiptap/tiptap
パッケージバージョン(2026-01-21 に確認済み)
{
"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"
}
}
本番環境での導入例
このスキルは、実際の導入事例をもとにしています。
- GitLab:課題や MR の説明に Tiptap を使用
- Statamic CMS:デフォルトのリッチテキストエディターとして Tiptap を使用
- shadcn minimal-tiptap:週あたり 3.14M ダウンロード
トークン削減率:約 71%(14k → 4k トークン) 防止したエラー:文書化されたエラー 7 件中 7 件(セットアップに関する重大なエラー 5 件+コミュニティのパターン 2 件) 検証項目:✅ SSR 互換性、✅ 画像アップロード、✅ Tailwind v4、✅ パフォーマンス、✅ React 19 互換性
トラブルシューティング
問題:「SSR has been detected, please set immediatelyRender explicitly to false」
解決策:useEditor() の設定に immediatelyRender: false を追加します
問題: 見出し/リストがスタイル未適用に見える
解決策: @tailwindcss/typography をインストールし、エディターコンテナに prose クラスを追加します
問題: 入力時にエディターが遅延する
解決策: 読み取り専用レンダリングには useEditor() の代わりに useEditorState() フックを使用するか、エディター設定をメモ化します
問題: 画像によって JSON が巨大になる
解決策: Image 拡張の設定で allowBase64: false を設定し、アップロードハンドラーを使用します (templates/image-upload-r2.tsx を参照)
問題: Create React App でビルドが失敗する
解決策: Vite に切り替えます - CRA は Tiptap v3 と互換性がありません。Vite のセットアップについては cloudflare-worker-base スキルを参照してください。
完全なセットアップチェックリスト
このチェックリストを使用して、セットアップを確認してください:
-
@tiptap/react、@tiptap/starter-kit、@tiptap/pmをインストールした -
useEditor()の設定でimmediatelyRender: falseを設定した -
@tailwindcss/typographyプラグインをインストールした - エディターコンテナに
proseクラスを追加した - 画像アップロードハンドラーを設定した (画像を使用する場合)
- Image 拡張で
allowBase64: falseを設定した - エディターがハイドレーションエラーなしでレンダリングされる
- 書式設定されたテキストが正しく表示される (見出し、リストなど)
- 開発サーバーが TypeScript エラーなしで実行される
- 本番ビルドが成功する
質問がありますか? 問題がありますか?
- トラブルシューティングについては
references/common-errors.mdを確認してください immediatelyRender: falseが設定されていることを確認してください- 公式ドキュメントを確認してください: https://tiptap.dev
@tiptap/pmのピア依存関係がインストールされていることを確認してください