Which rich text editor framework should you choose in 2025?
Looking to integrate a WYSIWYG editor into your JavaScript app? This comparison dives into the best frameworks available, including Tiptap, Lexical, BlockNote, and Slate.
A rich text editor, sometimes referred to as a WYSIWYG (what you see is what you
get), is an essential part of many of today’s apps such as Linear, Notion,
Google Docs. Even experienced developers find choosing the right one a daunting
task that often leads to analysis paralysis. At Liveblocks, we’ve spent the last
year digging deep, providing solutions for some of the industry’s most popular
editors, and we’ve got opinions and facts, about each.
In general, these editors fall into two categories: core and
batteries-included. Your choice of editor will depend on whether you are
building a small feature like a single composer or a fully-fledged collaborative
editor with many custom features.
If you’re here for a quick recommendation, we think
the most well-rounded choice is Tiptap because it strikes a
balance between being a feature-rich editor without being overly opinionated.
Sometimes you want an opinionated editor that delivers what you need out of the
box, or a lightweight editor you can mold into your own. We encourage you to
read on to explore the potential drawbacks and advantages of other choices.
At Liveblocks, we really care about collaboration. Most editors on this list
have realtime collaboration support thanks to a wonderful CRDT library called
Yjs. When utilizing Yjs, you still need a backend service to
store your document and enable realtime collaboration.
For the scope of this article, we won’t include abandoned or unmaintained
editors like Draft.js or editors with small communities. We also won’t cover
closed-source editors like Froala. Additionally, when it comes to accessibility,
each editor will require some work especially if you add plugins, extensions, or
frontend frameworks into the mix. We’ll highlight any relevant documentation if
it exists.
Tiptap is built on top of ProseMirror, a robust yet difficult to master editor.
Tiptap abstracts away the cumbersome parts of ProseMirror, leaving an enjoyable
developer experience. It also gives you the ability to easily extend its
functionality, including an interface into its core ProseMirror plugin system.
Tiptap has a friendly MIT license and has out-of-the-box support from both
Liveblocks and Tiptap Cloud. While Tiptap is packed full of features, they are
divided into tree-shakable packages which keep the
core bundle size smaller than
Quill, Slate, and Lexical.
Extending Tiptap is
easy, with the ability to add simple nodes, marks, custom commands, and
extensions. You can also override the behavior of other extensions, making it
simple to customize them to your needs without having to fork or rewrite from
scratch.
// Adding some pre-built extensionsconst editor =useEditor({ extensions:[StarterKit,// Adds standard features, e.g. styles, quotes, listsTypography,// Adds smart typography, e.g. curly quotes, fractions liveblocks,// Adds realtime collaboration, comments, mentions],});
While most of Tiptap’s features are open-source and MIT-licensed, there are some
extensions and features called “pro” extensions which are not open source.
If you’re planning on a more advanced integration with Tiptap, you’ll most
likely need to get your hands dirty with ProseMirror, which has a steeper
learning curve. Tiptap’s command system can also take some time to get up to
speed with as it hides some complexity of ProseMirror’s transactions while
adding the ability to chain commands.
// Toggle the current selection between <p> and <blockquote><buttononClick={()=> editor.chain().focus().toggleBlockquote().run()}> 💬 Quote</button>
Tiptap relies on a schema for its data model, but unlike ProseMirror, the schema
is generated for you by the extensions you add. Most implementations will never
need to touch or even know about the schema, but it can be extremely useful for
parsing and validation of your document.
Reading documentation between ProseMirror and Tiptap can be tricky at times, but
thankfully Tiptap’s source code is easy to read and has many
examples
of working with ProseMirror’s core for more advanced plugins. Accessibility is
also somewhat poorly documented in Tiptap, whose guide essentially leaves it up
to the implementer to handle.
Another drawback is that Tiptap’s performance can slow down quite a bit if you
don’t follow a few best practices, such as avoiding traversing document state
during transactions and setting shouldRerenderOnTransaction to false when
rendering inside React.
It’s not easy to run Tiptap on the server to mutate documents. For that, you’ll
want to use ProseMirror directly, which can be tricky after getting used to the
convenience of Tiptap. Another option is to simply modify the JSON directly. At
Liveblocks, we recently
released a library to make
this a bit easier.
import{ withProsemirrorDocument }from"@liveblocks/node-prosemirror";import{ Liveblocks }from"@liveblocks/node"; const client =newLiveblocks({ secret:"sk_prod_xxxxxxxxxxxxxxxxxxxxxxxx"}); // Update the document and return the text contentconst text =awaitwithProsemirrorDocument<string>({ client, roomId:"my-room-id",},async(api)=>{// Get and execute a new transaction (tr)await api.update((doc, tr)=>{return tr.insertText("hello");}); return api.getText();});
Tiptap has extensions that support realtime collaboration backed by Yjs. There’s
also two official cloud solutions for adding realtime collaboration to your
editor, Tiptap Cloud and
Liveblocks Text Editor. Liveblocks Text Editor integrates into
all our other features, and includes realtime collaboration, live cursors,
comments, mentions, notifications, and version history with more coming soon.
BlockNote is an opinionated, batteries-included, block-based editor (like
Notion) that extends both Tiptap and ProseMirror. If you’re looking for a
block-based editor, this is a great starting point. Most of the same pros as
Tiptap make this a solid choice.
In addition to what you get from Tiptap, BlockNote provides many features
out-of-the-box, like a slash menu, floating formatting toolbar, slick
animations, and more. Unlike Tiptap, BlockNote is primarily focused on React.
While it’s possible to use it with vanilla JavaScript or other frameworks,
you’ll miss out on the benefits of the UI elements provided by BlockNote.
While BlockNote itself is completely free and open-source, some packages—such as
docx
and
PDF exporters—require
a subscription for use in closed-source products.
BlockNote has realtime collaboration support with Yjs and Liveblocks. We also
have a full first-party integration coming soon, make sure to look out for that.
Pros
Cons
Based on battle-tested Tiptap and ProseMirror.
Realtime collaboration with Yjs and Liveblocks.
Block-based editing API and UI components out-of-the-box.
(Mostly) React-only.
Heavier bundle size compared to more basic editors.
Lexical has gained a lot of popularity lately because it’s backed by Facebook
(Meta) and used in their projects. We spent several months developing comments,
mentions, version history, and realtime collaboration support for Lexical, and
our takeaway is that although Lexical has a large community and commercial
backing, it needs more time to mature before we can recommend it over Tiptap.
This isn’t surprising, as at the time of writing, it hasn’t received a 1.0
release.
If you like Lexical, need comments, collaboration, or mentions while also
avoiding some of the growing pains we discovered,
our package is a good place to
start.
One of the main issues in extending Lexical is its lack of
pure decorations—the
ability to style content without affecting the document itself. While Lexical
does have “decorator nodes,” they mutate the content of the document. This means
that features like collaborative cursors must calculate and draw HTML divs on
top of the text and listen to scroll/resize events to compensate.
Slate (Plate) and
ProseMirror (Tiptap,
Remirror, BlockNote) both have a pure decorations feature.
Without the ready-made Liveblocks package, collaboration in Lexical is also
particularly difficult. While no editor’s collaboration features are perfect
(it’s a really difficult problem to solve well), there are still quite a few
issues that cause concern. Lexical’s collaboration implementation
hardcodes
the name of the root node, making it impossible to have more than one Lexical
editor per Yjs document.
Some of the examples, like StickyNotes in the playground, get around this using
nested Lexical composers, instantiating new documents, and new
WebSocket connections
for each sticky note. This workaround would not scale in production. The good
news is that development is moving fast, and we’ve already seen many issues
resolved since we began integrating with Lexical.
Lexical’s data structure is a hierarchy of nodes and each node is overridable
and customizable. You can also add your own nodes based on one of the 4 core
node types:
Lexical’s core is framework-agnostic, but it has a first-party React integration
with its own context, called
LexicalComposer, as part of
the @lexical/react package. Most of the core plugins are then reimplemented as
children of the LexicalComposer. Lexical also allows you to run headless on a
backend without DOM, using the @lexical/headless package. This is useful for
editing documents server-side.
Slate is a customizable and powerful framework for creating rich text editors.
It’s used by Discord, Grafana, Sanity.io, Slite, and more. Slate provides
developers with complete control over the editing experience while maintaining
an intuitive design.
At Liveblocks, we also chose Slate as the default editor for our
comments composer UI
component. We chose Slate because it supports a wide range of functionalities,
including rich text formatting, complete control of the editor, custom node
types, and an acceptable bundle size. Slate is vanilla JavaScript, but a React
package exists and can be integrated with other frameworks as well.
Slate has a very well documented system for extending its functionality. You can
define custom elements, transforms, styles, and events. While Slate’s core
feature set is not as complete as some other editors, it has a very extensive
list of
examples to
show you how to add those features on your own. If you want a more opinionated
and batteries-included version of Slate, Plate is an excellent option.
Slate’s bundle size is slightly larger than Tiptap and there aren’t quite as
many plugins/extensions in the ecosystem, leaving it up to you to implement some
features.
Quill is a powerful editor that has been used by many popular apps like Slack,
LinkedIn, Figma, Zoom, Miro, and Airtable. Quill has been stagnant in recent
years; however, its version 2, released in April 2024, is a rewrite that focuses
on fixing many of the issues which caused some developers to move on. Quill 2
has also been rewritten in TypeScript. Quill’s document model is called
Parchment, and users can use it to define their own “blots” that describe
attributes, blocks, embeds, and anything else. This is a similar concept to
ProseMirror’s schemas, nodes, and marks.
Quill is licensed under the permissive BSD-3-Clause license, making it ideal for
both personal and commercial use. Quill is backed by Slab, a commercial company,
and also has a very strong community on GitHub. Before April’s release, it had
only received a few updates in the previous few years. We’ll keep an eye on
Quill to see if its comeback is sustained.
Quill does not require a specific framework, so it can be seamlessly integrated
into various frameworks such as React.
Like Lexical, Quill lacks pure decorations, which allow you to style content
without modifying the document model. This is useful for things like
search/replace, collaborative cursors, etc. An entire library called
quill-cursors exists just to overcome this limitation by placing DOM elements
on top of the editor.
Quill can be made collaborative by using Yjs and
y-quill with an optional backend like
Liveblocks. Quill also has an Elixir-based operational transform backend called
Delta.
Pros
Cons
Good documentation.
Framework-agnostic and React-specific packages.
Yjs realtime collaboration support.
Simple delta format.
Fewer out-of-the-box features and plugins haven’t yet updated to Quill 2
Lack of pure decorations.
Somewhat less active development and a smaller community.
ProseMirror powers Tiptap, Remirror, BlockNote, and others. It is one of the
most battle-tested editors out there. ProseMirror relies on a schema for its
data structure and has a clear separation of concerns in its codebase. The main
ingredients of a ProseMirror editor are
state,
view,
model, and
transforms, which are individual
packages that can be imported on their own. In addition to these modules, you
will also need a schema and at least the
prosemirror-example-setup
just to get going.
For this reason, unless you’re a purist, masochist, or both, we recommend
starting with one of the excellent ProseMirror-based editors such as Tiptap,
Remirror, or BlockNote. However, if you’re going to be modifying any of the
aforementioned editors, it’s definitely worth learning how ProseMirror works.
Thankfully, stellar documentation and an
active community make this easier.
Plate is built on top of Slate and adds a host of features like UI, dozens of
prebuilt plugins, and entire templates. This is an impressive upgrade over Slate
if you’re looking for a more opinionated “batteries-included” editor.
Plate also maintains a large amount of flexibility with its plugins, so you can
choose to incorporate block-based editing, floating toolbars, mentions,
comments, and AI features. Most of these advanced features will require some
additional work to implement, such as a backend to store comments. While Plate
is free and open-source under the MIT license, it also offers a paid template
with lifetime access for a fixed price.
One drawback to Plate is that most of its functionality—such as plugins,
primitives, and components—is React-only. Another drawback is that, at the time
of writing, collaboration is only possible through Hocuspocus. However, there’s
no technical reason for this, and it wouldn’t be too difficult to add support
for other Yjs providers such as Liveblocks.
Let us know if you’d like us to build a
compatible package backed by Liveblocks!
Pros
Cons
Extensive library of plugins.
Server-side editing support.
Templates to help you get started fast.
React-only.
Collaboration is only available through Hocuspocus.
Heavier bundle size compared to more basic editors.
Remirror is a project very similar to Tiptap that takes a more opinionated and
batteries-included approach, with over 30 plugins, React hooks, i18n, and a11y
accessibility. It is built on top of ProseMirror, just like Tiptap, and has a
friendly MIT license.
It is one of the few editors that explicitly states its support of a11y and
accessibility. Now at version 3, it’s considered a stable and mature editor.
Drawbacks compared to Tiptap are that its community is a bit smaller, with
slower updates, and most of its functionality is React-only. Additionally, the
bundle sizes of Remirror and its extensions tend to be larger than Tiptap.
Editor.js is a well-established block-based rich text editor that is actively
maintained with a large community. Editor.js offers many plugins (called Tools)
and a modern design. The data structure consists of blocks, inlines, and tunes.
The core API has a few extra features that other editors don’t have built-in,
such as tooltips. The editor itself is framework-agnostic, and there are many
community-made plugins and wrappers for almost every framework, as well as
backend frameworks and CMS integrations.
The biggest drawback to Editor.js is the lack of any kind of realtime
collaboration support, which we believe is crucial to most modern apps. There
are a few PRs and some unmaintained attempts at Yjs support, but nothing that’s
part of the core product. Due to its opinionated and feature-rich nature, the
package size is also quite large, even without the useful plugins.
CKEditor has an impressive feature set, and the editor itself dates back more
than 20 years! The current version, CKEditor 5, is very modern and easy to use.
CKEditor also features a plugin system and support for Angular, React, Vue,
Next, and more. CKEditor is a solid choice as long as you are aware of the
drawbacks of a GPL-2 license, which may require you to open-source derivative
works. Of course, CKSource sells you a non-GPL license
as well as cloud services for realtime collaboration. CKEditor’s cloud pricing
is based on “editor loads”.
Many of its features are behind a paywall, such as markdown, media embeds,
mentions, comments, and even multi-level lists. The extensive list of paywalled
features and restrictive license are a blocker to our recommendation. However,
if you need a white-glove solution and are willing to pay, it may be worth
looking into.
Like CKEditor, TinyMCE is also over 20 years old and also under the GPL-2
license. Despite its age, it’s well supported and actively maintained. Their
cloud service also prices based on editor load. TinyMCE is available for vanilla
JavaScript, React, Vue, and Angular.
The list of features is comparable to CKEditor, and many of TinyMCE’s
plugins—such as markdown, mentions, comments, and even advanced typography—are
behind the paywall. We couldn’t find a way based on the documentation to modify
documents on the backend.