Launch HN: Tiptap (YC S23) – Toolkit for developing collaborative editors
Building editor interfaces like Notion or Google Docs in your web app takes a lot of work and time. Our open source tools and cloud services let you build collaborative content editing faster—in days or weeks, rather than months or years. And this is just for the editor. If you want real-time collaboration or other advanced features like version history in your editor, the overall workload quickly escalates—you will need a robust and serious backend infrastructure that requires even more time to set up and maintain. This doesn’t make sense for most frontend developers or most startups.
We spent eight years as a digital agency developing applications with complex content editing functionality. We learned the hard way how limited the existing editors were. After building Tiptap as a headless editor framework with an extension-based architecture, we needed to allow multiple users to edit content simultaneously, which got complicated. There was no simple solution that could be integrated quickly. So we built that too.
The Tiptap editor is based on the JS framework ProseMirror, which is a good foundation for editors. The learning curve for ProseMirror is steep because it's complicated to understand and lacks simple APIs and documentation. It takes a lot of code around ProseMirror to develop a modern user experience. We’ve taken care of that for you.
Tiptap is headless, so it will work with whatever frontend or design you have in mind—we make no assumptions about your UI. You can use it to develop block-based editors like Notion, classic interfaces like Google Docs, or whatever you need. It's also framework agnostic, so you can use it with React, Vue, etc., or vanilla JavaScript. And it's highly customizable through our extension architecture. We also provide an API to access ProseMirror's internals through Tiptap if you want to dig deep into the core.
Adding real-time collaboration to your editor is as easy as installing and configuring an extension. Our collaboration backend, called Hocuspocus, uses Yjs. This is a widely used implementation of CRDTs (conflict- free replicated data type). Hocuspocus makes it easy to set up a Node.js websocket server to handle communication between multiple peers to synchronize data. Like the Tiptap editor, Hocuspocus is designed to be extensible according to your needs. Also, Hocuspocus can work independently of Tiptap with other editors like Lexical or Slate.
An earlier version of Tiptap got discussed a couple years ago at https://news.ycombinator.com/item?id=26901975. We’ve been enjoying wider adoption since then. For example, Substack uses Tiptap for their editor that allows creators to write content on substack.com, and YC uses Tiptap in their Bookface forum (which is basically HN for YC alums).
With the Tiptap Cloud, we offer managed backend services if you don't want to build and maintain every feature yourself. For real-time collaboration, we provide a cloud infrastructure with multiple datacenter regions where you can deploy Hocuspocus. The Tiptap AI integration beta is a service where you connect your OpenAI API key to our backend and install the Tiptap editor AI extension to get AI writing experience in your editor. Here’s a demo: https://ai-demo.tiptap.dev/
We i...
104 comments
[ 9.7 ms ] story [ 218 ms ] thread> We are all constantly building products on other products, given a license that allows for that, without contributing work or money to the products.
This type of attitude is pretty harmful for open source. Folks (especially companies) should support their key dependencies where they can.
"Converse curiously; don't cross-examine."
"Assume good faith."
If you wouldn't mind reviewing https://news.ycombinator.com/newsguidelines.html and sticking to those rules, we'd be grateful. I took a quick look at your previous comments and didn't see any pattern of guideline breakage (thank you!), so this should be easy to fix.
I don’t appreciate your attempt to paint me as a liar to make your company look better.
We know the technologies we rely on, but we also know how important it is to find a sustainable way to maintain an open source project. For a popular project that a lot of other people rely on, this means getting money for development. Since Tiptap is also open source, we can see how the big players are using our project, and sponsor tiny amounts or nothing. We try to do it better than they do, because open source is definitely in our DNA, as it was in our previous work as a digital agency, and now since a few weeks with our focus on Tiptap.
A few years ago I evaluated rebasing Notion’s editor on various editor frameworks. ProseMirror came out at the top of my list, but I wasn’t sure how to rank TipTap.
Having more batteries included is good, but I’ve found that layers of abstraction can really get in the way. For example if I need to fix a bug with Android Gboard input, without a framework I can exactly control the DOM structure and input handling, but the downside is no one fixes the bug for me. With ProseMirror, I’d need to tunnel through 1 layer of abstraction and/or patch 1 layer of abstraction. With Tiptap, maybe I’d need to fork-and-patch both you and ProseMirror? Each layer also increases our maintenance liability. If the ProseMirror author decides to retire or take the library in a direction that doesn’t work for us, then we need to fork and maintain it. If both you and the ProseMirror do that, we have more code we need to maintain.
Ultimately I decided adopting a library was too risky, and opted to improve our native ComtentEditable handling. Because our product’s selling point is an editor, we want to control our own destiny.
For others who can afford a library but still need to weigh the risks of that abstraction stack, can you share some insights?
Think of it like this... you're basically only coupling yourself to ProseMirror. That's the schema you're storing in your database. TipTap is a set of libraries that you can use for your web app etc... but if you ever find it insufficient, you're free to role your own thing.
ProseMirror has been around for a long time and is unlikely to be going anywhere, but having a company with VC funding using it as its base helps ensure that if ProseMirror got abandoned, it'd likely get picked back up by TipTap or some other interested party.
Even if you're building your own editor, unless your editor has a need that ProseMirror's schema doesn't account for or solve it makes sense to use it.
On the contrary, the company with VC may be a bummer after some years and the VC wanted to get ROI: prices started to increase (or appear), change of strategy and abandon/remix the tool, close the store…
Being free and open source surely helps.
I think the future of an open source project and the company behind it really depends on the founders. If open source is really in their DNA, they will fight for it. If everything goes wrong, at least the open source code will remain. The closed code will most likely disappear with the company.
Thanks for your feedback! We really need people like you to point out when things are going in the wrong direction. It's often a difficult balance between making money and giving back to the community. So we need your outside perspective!
With Tiptap we are trying to make it easy to build modern editors. The demands on the usability of an editor are getting higher and higher because of tools like Notion. Building a tool like this from scratch is pretty hard. That's why we used Prosemirror as a solid foundation, but in our daily work of developing editors for our projects we came to the point that we really need an additional layer of abstraction to reduce recurring code that you don't want to write over and over again. Yes, with our layer we made some decisions about how an editor framework should behave, but with our extension-based architecture in Tiptap, which ProseMirror also has, you can extend both layers separately.
As a contributor to the previous version of Tiptap, and as a developer that built extensions into it, I encountered the exact same problem of having to learn two different APIs while trying to build more advanced features.
Out-of-the-box libraries like Tiptap are great when their extensions or components fully cover your use case. But when you need to customize or own the code itself, the secondary abstraction becomes leaky and you start to fight against it.
Because I was building a note-taking app, I spent most of the time working on the rich text editor. Eventually, I just ripped the bandaid off and wrote a new library that was architected off Tiptap but was a thinner abstraction on top of ProseMirror.
With hindsight, I can definitively say that was the better personal choice. The last time I used Tiptap was in 2020, and since then its API has evolved to a point where my knowledge is way outdated. On the flip side, ProseMirror has been extremely stable, improving with a non-breaking typescript rewrite. Digging into the internals of ProseMirror, learning how it has been built and maintained, contributed massively to how I write code today.
That being said, the journey of moving off Tiptap to ProseMirror took a couple of months for a junior dev. So I can understand how a market for it exists. My only wish for Tiptap now is for it to reduce its API overhead on ProseMirror, and instead build more advanced ProseMirror-compatible plugins that require a backend. Collaborative editing (comments, annotations), version control and schema migration, etc are all exercises normally left up to the developer that can be solved by Tiptap well.
Congrats, any plan on supporting code/monaco and autocompletion? We had to rebuild it ourselves on top of yjs and gpt4 for windmill.dev and would have happily built it on a service if it existed.
The only issue I have encountered with it that I haven't solved yet (I think there are multiple potential paths) is validating/sanitizing data with it.
To parse the content and turn it into raw text requires instantiating TipTap and all the attendant plugins. So even if I want to do a server side check for something like minimum character count, I have to 'decode' the JSON etc...
I know it's not the focus, but something that makes that easier would be nice. And something I could easily add to a Schema checker like Joi or Zod.
Do you mind expanding on this? I've been comparing the two and found the lexical data model easier to understand.
* I did not like that it was an alternative to a different Facebook rich text editor (draft.js)
* Very React focused (makes sense, it's a Facebook/Meta project) - even applying concepts. Here's an excerpt from their site: "If you've used React Hooks before, you can think of $ functions as being something that follows a similar pattern. These are functions that show their intent as to where they can or cannot be used."
I don't want to use React Hooks or things designed to be like React Hooks.
* Newer and less features/polished. Looking at their official project site, there's way less features already available. That means more custom code you have to write.
* No standard schema/for formatting rich content
https://gitlab.com/gitlab-org/gitlab/-/issues/231725
https://gitlab.com/gitlab-org/gitlab/-/issues/273238
[1] https://github.com/ueberdosis/tiptap/tree/develop/tests
I see that as an issue with React though, not TipTap. It’s a great editor and I love that it’s headless.
It's really a great and flexible editor, with a couple of rough corners, but overall the only serious alternative to the above-mentioned editors. And since it has a sensible licensing model it is an overall good choice.
It might be somewhat similar to the "details" extension, but they were also drag and droppable. The drag and drop support was also somewhat subpar compared with TinyMCE, I ended up using vue.draggable.next to solve the issues, but this added a layer of huge complexity.
Then there was an issue that the UniqueID is a Pro extension and it would have been required for properly storing the document. I now see that pro extensions are free, after registration, but I'm not sure if it was always like this, I think it was coupled to a GitHub sponsorship back then (maybe around August 2021). For a side project which would then sit at rest for some months this wasn't feasible. I think I implemented a custom UniqueId to get around this, but I haven't touched the project for over a year.
About 2 months ago I was thinking about rewriting it in React and see if I could turn it into something, but I haven't found the time.
I hope you'll find the time to continue your project.
If I had one request, it would be instead of making me jump from $0 to $150 a month, have a usage-based model similar to OpenAI or Firebase, with functionality so I could cap costs to say $15 a month.
To be honest, we’re still thinking about pricing and I’m sure there will be updates in the (hopefully near) future.
Personally, I’m a big fan of usage-based pricing because it’s the fairest approach. We are also thinking about splitting the price tiers into different modules, e.g. for OpenAI integration, collaboration, maybe support and so on. I said “hopefully in the near future” above because it’s going to be a huge amount of work for us to change that (for example, we have to change our payment provider) and we’re currently focused on other things like implementing new features that our users are asking for most.
What do you think about module-based pricing (in combination with usage-based pricing)?
- collaborative editing
- offline editing
- faster loads with sw caching
- git history
- end-to-end encryption.
It's taken me forever to build these, and the code's still not where I want it to be. If you had modules for these that I could pay for, I totally would.
(psst, we're also hiring!)
Would be great to hear any tips or pains you encountered!
I was just playing around with Tiptap last week and build a (very dumb) AI rephrasing app here: https://authored.co. Took a bit to get used to the ProseMirror API, but was a fun experience!
fyi, BlockNote aims to be a bit more batteries-included (comes with UI and block-based editing) - in case headless text-editing libraries are a bit too much work / steep learning curve.
The APIs and AST syntax have been very straightforward to work with. Congrats on the launch!
Shameless plug for some ProseMirror FOSS ecosystem contributions I've recently made:
A commit-based collab plugin that's far more performant under heavily active client loads than stock. I'm a fan of YJS, but not a fan of state-based CRDT layer on top of ProseMirror for my use cases. Wrote about this here: https://stepwisehq.com/blog/2023-07-25-prosemirror-collab-pe... .
I also translated the core ProseMirror projects of model, transform, and test-builder to C# so you can build robust backends in a C# monolith. All tests on those projects have been translated as well. Wrote about this here: https://stepwisehq.com/blog/2023-07-17-announcing-prosemirro... .
Hope to release more FOSS projects along the way; lot of taking from ProseMirror compared to what's given back IMHO(not targeted at TipTap which provides a lot of value). I've got some stuff geared towards minimizing keystroke-to-paint latency which I hope to write about soon. Ideally we will reach a point where we contribute funds to the ProseMirror project.
Cheers!
ducks
I think it would need to clearly be worth the cost. I'm having a hard time imagining use-cases my users would have, and matter enough, that would necessitate it over the commit based backend..
I spent quite a bit of time as an FTE building out a robust-ish and efficient Yjs backend POC. This included refactoring the ProseMirror Yjs bindings into a proper TypeScript project, and specializing them for some funky use-cases. At the end of it all my personal takeaways were:
* State-based CRDT isn't great when you want a central authority in the mix anyway and are fundamentally trying to work with operations
* The exchange rate between ProseMirror's currency, steps, and some other replication strategies building blocks is too high
* ProseMirror should add the concept of range-relocation to its mappings; this is a bit of an aside but it would help retain user intent when reconciling concurrent edits involved in block relocations
As a concrete example for others imagine a knowledge base editor. You want allow certain users ONLY to comment and you want to enforce this on the backend. There are a number of ways this could be implemented but you may want the UX of optimistically allowing them to make that edit in the FE and then submit the ProseMirror steps to the backend. This will typically involve two fundamental ProseMirror steps(of which there are only a few) to set an attribute and set a mark on a node range.
You can relatively easily inspect the submitted changes to verify only the allowed operations are occurring, and authorize the user for them.
However Yjs just cares about syncing state so the documents end up equivalent, and its efficient diff format doesn't really have the info you'd need to determine what's going on. You'd need to have the actual document model loaded, and then diff the docs before/after to figure out exactly what happened. And/or patch into the Yjs binding diff algorithm which works surprisingly well but doesn't produce minimal changes and can often "over edit" the document model.
So something that was relatively simple with ProseMirror steps has become a huge thing with Yjs. And for what?
All that to say, Automerge is supposedly operation based so in theory it sounds like a better route for use cases involving a central authority(which is most if I'm speculating) and want to do extra processing on document operations.. But it'd need to bring a lot to the table to offset the time investment..
[1] https://github.com/vlcn-io/cr-sqlite
[1] https://github.com/vlcn-io/cr-sqlite#approach-1-history-free...
It should be lighter than tiptap.
A friend of mine has been using TipTap extensively with his web app and convinced me to look into it a few months ago.
Word doc imports and exports are a really important piece for me and I saw they're in the "Proof of Concept" stage of your idea pipeline.
Do you have any idea when this'll be ready? I'd be happy to help test the feature if it can help!
I see from your home page and pricing page (https://tiptap.dev/pricing) that you've switched from wording that says "You are free to do whatever you want, TipTap is licensed under MIT" (with support for premium paid plugins), to TipTap being free* (no Credit Card required), and no mention of the MIT license.
This makes me extremely worried that you are eventually going to go the TinyMCE / Froala / CKEditor route, which has made me very hesitant to now use these editors.
I completely understand that WYSIWYG editors are extremely hard to maintain, but on the flipside I now am worried about all the projects I've added / started to add TipTap to. Can you help assuage this worry? Will the core plugin remain free and MIT licensed forever, and not reliant on some sort of usage model outside of premium plugins?
[1] https://news.ycombinator.com/item?id=36959404
We have had quite a long and rough ride in search of a stable rich text editor. We began with Quill.js then migrated to TinyMCE and then finally settled on Prosemirror. Unfortunately, contenteditable is still absolutely horrible on web browsers, especially mobile ones.
Tiptap is a good choice if you are looking for a framework agnostic and thin abstraction over Prosemirror. However, if you are primarily working with React you should go with Remirror[1]. Tiptap's APIs are heavily inspired by Remirror (almost a duplicate in some places). Remirror takes the edge on the maturity and stability of the API and extensions. The sheer number of utilities offered by them to simplify Prosemirror's APIs is astounding. And trust me, you will need a lot of those utilities eventually. Prosemirror is not an easy API - really, really well designed but not easy.
In the end, though, its Prosemirror that's doing all the heavy lifting. And no matter how many abstractions you put on it, you will have to get really, really close in with Prosemirror's internals. Tiptap or Remirror do not make that any easier or harder aside from the initial bootstrapping.
[0] https://notesnook.com
[1] https://remirror.io
---
Edit: almost forgot this but the only real selling point of Tiptap is their extensive documentation.
The good news, though, is that it's really simple to mix and match Tiptap and Remirror since both of them use Prosemirror internally.
[1] https://github.com/nytimes/react-prosemirror
We believe that a good editor needs not only a frontend, but also easy-to-use backend services that we try to integrate as seamlessly as possible. With our framework-agnostic approach, we support more than just React.
Related, I recently started rebuilding the post editor on IndieHackers.com to use Tiptap. Enjoying it so far. I wish your documentation had a few more examples, and better English in some places. But its high quality was part of what attracted me to Tiptap in the first place. I'd love to see y'all continuing to iterate and improve on it!
We love being part of the open source community, but as I mentioned in another answer, a project like this can't be sustained without the business side in mind. The whole project has been bootstrapped by us in addition to our work at our digital agency. With YC we can focus on the project and develop an ecosystem and harden our open source core, which will always be free for everyone in the future.
We don't have an exit plan, but we have a lot of ideas for more features and want to respond to the community's feedback.
Your PR fixing our bad English in our markdown documentation is always welcome ;) Thank you for your valuable feedback!
[1] https://github.com/williamw520/tiptab
It’d be great to have an 80% use-case coverage for common components.
I’ll call out this wrapper for TipTap + MUI I stumbled on that’s been a nice addition. https://github.com/sjdemartini/mui-tiptap