The Evolution of Witful: The Editor

In this series of articles we go through the evolution of several key components of Witful. We cover topics ranging from the more user-facing features like search and our rich text editor, to the services which power Witful behind the scenes like GCP and Google’s suite of Firebase products. My aim is to give Witful users, and product builders more generally, a sense of where we came from, why we made some of the product decisions we made, and where we’re headed.

The Beginning

When I joined the small Lyons, CO tech consultancy Real Kinetic back in late 2019 I was to be the first full-time employee working on a fledgling, internally built product called OnPoint. Its aim was to do exactly that – keep you on-point – in meetings, and more generally in your workday. It was a way to organize the complexity of managing relationships, taking meeting notes, and staying on top of action items. It was for people whose day is largely driven by their calendar.

OnPoint (a previous iteration of Witful)

OnPoint–later renamed Witful–was the answer to the surprising lack of tools focused on meeting-centric note taking. It was born of necessity out of a team focused on something else entirely. (Like many other great products: Slack, an internal chat tool created by a gaming company; Basecamp, internal project management tool for a web design firm.)

The Prototype

I was a bit surprised to discover that the centerpoint of the app – the note editor – was plaintext. There was no bold, italic, or underline formatting, no links, headers, or quotes, and most glaringly no lists. Dashes were our poor man’s lists. To-dos or action items were created by adding “!!” to a sentence. When you clicked the action item’s checkbox to complete it we’d change the “!!” to a “!*”. This is what we call Advanced Alien Technology™.

It was common any given day I was working on Witful to hear “Man I wish we had proper lists” or “It’s pretty painful to not have clickable links in my note”. Clickable links, you know… the little blue text thingys. Aka Hyperlinks, the raison d’être of HTML, basically the mana of the internet.

The MVP

Bill Gates once asked “How many f*cking programmers in this company are working on rich text editors?!” (supposedly). I’m not entirely surprised, we’re talking about the man running the company responsible for one of the most popular word processing programs in existence.

Rich text is an interesting kind of beast. I think we as a society really take it for granted, especially in web apps. It often sits invisibly within any given application, not a luxury but a fundamental necessity, table stakes for any note taking app. The expectation being the clickity-clacks your keyboard makes when pressing Ctrl and B will invariably result in the selected text looking thicker, louder, more emboldened. 

It wasn’t always so easy, as it is in say Google Docs, Microsoft Word, or basically any app that allows you to type longform into a box on your screen. The ability to Slack message your coworker about the crazy thing your boss just said with italicized emphasis probably involves more technological black magic than sending a spaceship to the moon. 

Luckily, I’d had experience in my previous job integrating a rich text editor w/ Elm, the same frontend language / framework Real Kinetic was using in Witful, and pretty much the whole reason I was hired (being probably the only Elm developer within a 1000 mile radius at the time). I began by researching the current state of open-source javascript-powered rich text editors and wrote down my findings:

Quill

  • Pros: I had prior experience with this. Widely used and battle tested by many. e.g., Slack, LinkedIn, Salesforce, Asana. Decent documentation and examples. Straightforward and batteries included – lists, bold, italics, underline, links, etc. Good cross-browser and mobile-device support.
  • Cons: Not easy to customize or extend. The creator seemed to have lost interest in the project long ago. The view layer is deeply coupled to the schema or “shape” of the rich text data. Confusing, Java style OOP, with lots of inheritance.

Prosemirror

  • Pros: Much more extensible, more of a toolkit than an editor. Has been around a while and used by some big hitters (Atlassian).
  • Cons: Complex API and steep learning curve. Very object-oriented Javascript— I prefer a functional programming style. It felt like getting an MVP rich text editor would take weeks or months, and we just couldn’t justify that kind of investment at the time.

Draft.js

  • Pros: Created and maintained by Facebook. Uses React.
  • Cons: Buggy on mobile devices. Seemed like the project/codebase wasn’t getting the attention it needed. It’s since been announced that it will soon be going into “maintenance mode” and is being replaced by Facebook’s new project Lexical.

Slate

  • Pros: Very extensible. Great plugin API. Good documentation and examples. Active project maintenance and development. Clean API. A compelling set of core principles for why the project was started. Written in Typescript. Very FP style codebase, no use of the word “class” anywhere. Basically schemaless, left to the user how the rich text should be structured. No coupling to any particular view layer, but includes a separate package (slate-react) to make rendering in the browser straightforward.
  • Cons: Barebones, no batteries included. You had to roll everything yourself, bold, italic, and, worst of all, lists (we’ll get to that later). Very similar to Prosemirror in that it would have taken many weeks to get something working. Frequent breaking changes to the API and some performance issues (circa 2019-2020; those have since been resolved).

I presented my findings to the team and ultimately recommended that we go with Quill. We wired the editor into Elm using a Custom Element-wrapped version of Quill and had things working within an afternoon. We shipped to production (app.witful.com) soon after.

I must say I was honored, as such a new member of the team, to have been trusted with the task of making a decision which might save or cost the company potentially months of development time. Despite my excitement to play with something like Prosemirror or Slate, I knew the basic editor features we needed at the time couldn’t justify the implementation costs. Quill probably ended up saving us a ton of time and money, despite the need to migrate off of Quill to something more advanced at a later date.

Production ready

It all began at a hackathon in the mountains of Breckenridge, March of 2021. The Witful team had in mind what we knew would really differentiate us. We would go from a note taking app simply linked to your calendar–which was great to be sure–to creating a whole new effortless “it just does the right thing at the right time” workflow.

It essentially boiled down to this: “Talk to @John Doe about @Sam Jones’ genius marketing idea in #next meeting”.

We wanted action items like the above to intelligently surface in that next meeting (or perhaps a specific meeting or series of meetings) w/ John Doe. 

Later, in a meeting w/ John, you’d open a Witful note and bam! you’d see the action item sitting there, reminding you to bring up the idea Sam had two weeks prior. You’d be able to click on the action item to navigate back to the original note it was created in, allowing you to see the surrounding context, jogging your memory of the details surrounding Sam’s original ideas. You’d be able to check the action item off in your current meeting w/ John and create a sort of thread or work stream. Ideas and action items would be linked across meetings and people, threads of connected content for your projects and relationships. A traversable graph of context with provenance.

Today’s information flow in Witful

I knew the Quill editor wasn’t gonna make this easy. We needed to have full control of the shape of the rich text format, as well as the way it was rendered. We spent the weekend in Breckenridge whiteboarding “Action Items 2.0”, poking around in Quill, Slate, and Prosemirror. We prototyped how using @ and # mentions could link notes to each other.

We walked away that weekend knowing, indeed, we needed to part ways with Quill. I was pretty amped to give Slate a go as I’d been quite impressed with the progress the project had made since I’d last looked at it a year prior. The API was very clean. A project known as slate-plugins (now called plate) also provided a wealth of reference for how to implement more complex features like @ and # mentions.

Little did I know The List™ would be the bane of my existence for the next several weeks. Implementing a functioning list with all the behavior one might expect (dash + space, tab, shift-tab, copy-paste) proved incredibly tedious and downright depressing at times. I was definitely questioning my decision to cheerlead Slate to the team. I worried that I was wasting piles of money on an editor that would produce hundreds of hours of debugging costs just in its list implementation alone.

Thankfully, patch by patch, we were able to get a functioning list, of both the bulleted and numbered varieties. We feature-flagged the new editor in Witful, enabling it for internal users only, and eventually migrated all existing users to the new editor. It was all quite humorous really, I’d spent countless late nights and weekends coding up the move from Quill to Slate, and in the end, none of our users noticed the change once we flipped the switch. The editor experience was basically unchanged.

Now that we had the new editor in place, it was time to start the journey towards Action Items 2.0, the “Talk to @person in #meeting” killer feature of Witful. We’re excited to keep building it out, making it feel more and more seamless and fluid.

So stay tuned for the next post in this series where we’ll go over the evolution of Witful’s search capabilities, from a naive prototype, to usable MVP, and then proudly production ready.