Tiptap best practices and tips
This guide covers best practices and common pitfalls to avoid when working with Tiptap and Liveblocks.
Always include StarterKit or Doc & Paragraph extensions
The Tiptap
StarterKit
extension is required for Tiptap to function properly. It provides essential
node types that every Tiptap editor needs, specifically the Doc and
Paragraph nodes. Alternatively you can include only the
Doc and
Paragraph
extensions.
Why StarterKit is required
Tiptap documents must have a root Doc node and at least one Paragraph node
to maintain a valid document structure. Without these core nodes, the editor
will not work correctly and synchronization will fail.
What StarterKit includes
In addition to the required Doc and Paragraph nodes, StarterKit also
includes commonly used extensions like:
- Text formatting (Bold, Italic, Strike, Code)
- Block types (Heading, Blockquote, CodeBlock, BulletList, OrderedList, ListItem)
- Horizontal rule and hard break
- History (undo/redo) (This must be disabled to work with Liveblocks)
If you need more control over which extensions are included, you can configure StarterKit to disable specific extensions:
However, you should never disable the doc or paragraph options, as these
are required for the editor to function.
Disable server-side rendering with immediatelyRender: false
When using Tiptap with server-side rendering (SSR) frameworks like Next.js, you
should always set immediatelyRender: false in your useEditor hook. Tiptap
should never be rendered on the server.
Why disable server-side rendering?
Tiptap is a client-side editor that relies on browser APIs and the DOM. When rendered on the server, it can cause:
- Hydration mismatches between server and client
- Errors related to missing browser APIs
How to disable server-side rendering
Set immediatelyRender: false in your useEditor configuration:
This ensures that Tiptap is only rendered on the client side, avoiding any server-side rendering issues.
Enable content validation
Tiptap has a schema that defines the structure of your document. By default, Tiptap does not validate content against this schema. When invalid content is present, it will silently break synchronization without any error messages.
This can happen when:
- Extensions are added or removed from the editor
- The schema changes between different versions of your application
- Users collaborate on documents with different editor configurations
How to enable content validation
Always enable content validation by setting enableContentCheck: true and
implementing an onContentError handler:
This ensures that:
- Invalid content is detected early
- Collaboration is disabled to prevent data corruption
- The editor is made read-only to prevent further changes
- The issue is logged for debugging
- Users are notified of the problem
Use initialContent instead of content
When setting default content for your Tiptap editor, always use
initialContent
on
useLiveblocksExtension
instead of content on useEditor. Using content will cause the content to
be appended to the document every time the page loads or the component
re-renders.
The problem with content
The content option in Tiptap sets the editor content every time the editor is
initialized. When using Liveblocks, this means the content will be added to
the existing document rather than replacing it, causing duplication:
Use initialContent instead
The initialContent option sets a flag internally and only sets the content the
very first time the document is empty. This prevents duplication:
Support multiple editors with the field option
If you want to display multiple Tiptap editors on the same page, use the
field option
with a unique identifier for each editor. This ensures that each editor
synchronizes to its own section of the Yjs document.
Without the field option, both editors would synchronize to the same location
in the document, causing conflicts and data loss.
Never use extensions with binary data
Never use Tiptap extensions that store binary data (such as base64-encoded images) directly in the document. Binary data will be synchronized across all clients and can fill up your Liveblocks room extremely quickly, leading to:
- Increased bandwidth usage
- Slower synchronization
- Higher storage costs
- Potential rate limiting
Common pitfall: Image extension
The official Tiptap
Image extension has an
allowBase64 option. This option is defaulted to false, and it should
never be set to true.
Recommended approach
Instead of storing images as base64 in the document:
- Upload images to a file storage service (e.g., AWS S3, Cloudflare R2, Vercel Blob)
- Store only the URL in the document
- Reference the URL in your image nodes
Prevent users from losing unsaved changes
To prevent users from accidentally losing their work when closing the browser
tab or navigating away, enable the
preventUnsavedChanges
option:
This will display a browser confirmation dialog when users try to leave the page with unsaved changes, helping prevent accidental data loss. Learn more.