
tiptap
Build rich text editors with Tiptap - headless editor framework with React and Tailwind v4. Covers SSR-safe setup, image uploads, prose styling, and collaborative editing. Use when creating blog editors, comment systems, or Notion-like apps, or troubleshooting SSR hydration errors, typography issues, or image upload problems.
- Installs
- 478
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/jezweb/claude-skills --skill tiptap- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads tiptap automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Tiptap Rich Text Editor
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)
Quick Start (5 Minutes)
1. Install Dependencies
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/pmis 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.
2. Create SSR-Safe Editor
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: falsefor Next.js/SSR apps (prevents hydration mismatch) - Without this, you'll see: "SSR has been detected, please set
immediatelyRenderexplicitly tofalse" - This is the #1 error reported by Tiptap users
3. Add Tailwind Typography (Optional but Recommended)
npm install @tailwindcss/typography
Update your tailwind.config.ts:
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
.tiptapselector
The 3-Step Setup Process
Step 1: Choose Your Integration Method
Option 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:
- 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 setuptemplates/common-extensions.ts- Extension bundletemplates/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
Step 2: Configure Extensions
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:
- Set
allowBase64: falseto prevent huge JSON payloads - Use upload handler pattern (see templates/image-upload-r2.tsx)
- Extension order matters - dependencies must load first
Step 3: Handle Image Uploads (If Needed)
Pattern: 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:
- Immediate user feedback (preview)
- No database bloat from base64
- Works with Cloudflare R2
- Graceful error handling
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
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)
Known Issues Prevention
This skill prevents 7 documented issues:
Issue #1: SSR Hydration Mismatch
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
Issue #2: Editor Re-renders on Every Keystroke
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)
Issue #3: Tailwind Typography Not Working
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
Issue #4: Image Upload Base64 Bloat
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
Issue #5: Build Errors in 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
Issue #6: ProseMirror Multiple Versions Conflict
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.
Issue #7: EditorProvider vs useEditor Confusion (Community-sourced)
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} />
}
Configuration Files Reference
Tailwind Prose Styling (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;
}
}
Why these settings:
proseclasses provide consistent formattingdark:prose-inverthandles dark mode automatically- Custom overrides use semantic Tailwind v4 colors
Common Patterns
Pattern 1: Collaborative Editing with 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,
}),
],
})
When to use: Real-time multi-user editing (Notion-like)
See: templates/collaborative-setup.tsx for full example
Pattern 2: Markdown Support
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
Pattern 3: Form Integration with 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>
)
}
When to use: Blog posts, comments, any form-based content
Using Bundled Resources
Scripts (scripts/)
No executable scripts for this skill.
Templates (templates/)
Required for all projects:
templates/base-editor.tsx- Minimal React editor componenttemplates/package.json- Required dependencies
Optional 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 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
References (references/)
references/tiptap-docs.md- Key documentation linksreferences/common-errors.md- Error troubleshooting guidereferences/extension-catalog.md- Popular extensions list
When Claude should load these: Troubleshooting errors, exploring extensions, understanding API
Advanced Topics
Custom Extensions
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
Slash Commands
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
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 dependencyreact@^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 stylingyjs@^13.6.0- Collaborative editing backendreact-medium-image-zoom@^5.2.0- Image zoom functionality
Official Documentation
- Tiptap: https://tiptap.dev
- Installation Guide: https://tiptap.dev/docs/editor/installation/react
- Extensions: https://tiptap.dev/docs/editor/extensions
- API Reference: https://tiptap.dev/docs/editor/api/editor
- shadcn minimal-tiptap: https://github.com/Aslam97/shadcn-minimal-tiptap
- Context7 Library ID: tiptap/tiptap
Package Versions (Verified 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"
}
}
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
Troubleshooting
Problem: "SSR has been detected, please set immediatelyRender explicitly to false"
Solution: Add immediatelyRender: false to your useEditor() config
Problem: Headings/lists look unstyled
Solution: Install @tailwindcss/typography and add prose classes to editor container
Problem: Editor lags when typing
Solution: Use useEditorState() hook instead of useEditor() for read-only rendering, or memoize editor configuration
Problem: Images make JSON huge
Solution: Set allowBase64: false in Image extension config and use upload handler (see templates/image-upload-r2.tsx)
Problem: Build fails in Create React App
Solution: Switch to Vite - CRA incompatible with Tiptap v3. See cloudflare-worker-base skill for Vite setup.
Complete Setup Checklist
Use this checklist to verify your setup:
- Installed
@tiptap/react,@tiptap/starter-kit,@tiptap/pm - Set
immediatelyRender: falseinuseEditor()config - Installed
@tailwindcss/typographyplugin - Added
proseclasses to editor container - Configured image upload handler (if using images)
- Set
allowBase64: falsein 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?
- Check
references/common-errors.mdfor troubleshooting - Verify
immediatelyRender: falseis set - Check official docs: https://tiptap.dev
- Ensure
@tiptap/pmpeer dependency is installed
FAQ
What does the tiptap skill do?
Build rich text editors with Tiptap - headless editor framework with React and Tailwind v4. Covers SSR-safe setup, image uploads, prose styling, and collaborative editing. Use when creating blog editors, comment systems, or Notion-like apps, or troubleshooting SSR hydration errors, typography issues, or image upload problems.
How do I install tiptap?
Run npx skills add https://github.com/jezweb/claude-skills --skill tiptap in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/tiptap/ (personal) or .claude/skills/tiptap/ (project).
Which AI agents can use tiptap?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is tiptap safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains tiptap?
It is published by jezweb in jezweb/claude-skills. It has 478 recorded installs.
More from jezweb/claude-skills
shadcn-ui
jezweb/claude-skills
Install and configure shadcn/ui components for React projects. Guides component selection, installation order, dependency management, customisation with semantic tokens, and common UI recipes (forms, data tables, navigation, modals). Use after tailwind-theme-builder has set up the theme infrastructure, when adding components, building forms, creating data tables, or setting up navigation.
color-palette
jezweb/claude-skills
Generate complete, accessible colour palettes from a single brand hex. Produces 11-shade scale (50-950), semantic tokens, dark mode variants, Tailwind v4 CSS output, WCAG contrast checks. Use whenever the user supplies a brand hex and asks for a palette, mentions setting up a design system, wants Tailwind theme colours from a brand colour, or asks to check colour accessibility / contrast.
tailwind-theme-builder
jezweb/claude-skills
Set up Tailwind v4 + shadcn/ui themed UI with dark mode. Install deps, configure CSS variables via @theme inline, wire dark mode toggle, verify. Use whenever the user mentions Tailwind v4, setting up Tailwind theming, shadcn/ui colours, dark mode, or troubleshooting colours not working, tw-animate-css errors, @theme inline conflicts, @apply breaking after upgrade, or v3 → v4 migration issues.
wordpress-elementor
jezweb/claude-skills
Edit Elementor pages and manage templates on WordPress sites via browser automation (for visual / structural changes) or WP-CLI (for safe text replacements). Use whenever the user wants to edit an Elementor page, update text in Elementor widgets, apply or manage Elementor templates, or make content changes to pages built with the Elementor page builder.
ux-audit
jezweb/claude-skills
Walk through a live web app AS a real user to find usability + behavioural bugs that static reviews miss. REQUIRES proof of interaction (typing, clicking, sending, observing) before any verdict — a sweep that didn't interact terminates with verdict 'Incomplete'. Walks threads, exercises every element, runs the multi-pane stress matrix, visual polish sweep, component perfection checklist, automated a11y (axe-core), pragmatic performance budget (LCP/CLS/INP), scenario battery (11 scenarios), and stress recipes including the real-flavour data battery. Hard gates: console errors/warnings = 0, network 5xx = 0, layout collapse = 0, axe Critical/Serious = 0, perf budget green. Audit-the-audit meta-check rejects rushed reports. Each finding has reproduction steps, evidence path, and suspected code location. Trigger with 'ux audit', 'walkthrough', 'qa sweep', 'audit the app', 'dogfood this', 'check all pages', 'find what's broken', 'stress the UI'.
tailwind-v4-shadcn
jezweb/claude-skills
Set up Tailwind v4 with shadcn/ui using @theme inline pattern and CSS variable architecture. Four-step pattern: CSS variables, Tailwind mapping, base styles, automatic dark mode. Prevents 8 documented errors. Use when initializing React projects with Tailwind v4, or fixing colors not working, tw-animate-css errors, @theme inline dark mode conflicts, @apply breaking, v3 migration issues.
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.