From Idea to Code — sometimes it really does take a village

The stages we took to rebuild Qwilr’s editor

--

The basics of a text editor are just that. Basic. User types text, editor displays typed text. But to make the experience flow, to be able to ‘think’ in the editor… This takes a lot of nuance to not break the user’s groove. Creating this nuance is the culmination of hundreds of small questions being asked and answered by different disciplines across our team.

An example of this: when a user presses Enter at the end of a heading, what should happen? What are they expecting to happen? It’s fairly standard, in this case, to create a paragraph. But what to do when pressing Enter in the middle of a heading? Or at the start? All these questions need answers that also need to make sense together.

We recently overhauled Qwilr’s core editor. There were numerous aspects of our existing editor that we wanted to improve, from both an engineering and a customer perspective:

  • Make it easier to maintain the editor
  • Provide a more reliable editing experience
  • Add room in the code for extensions and further customisations to be added in
  • Easily reproduce and squash bugs
  • Provide a more intuitive experience

I’m going to dive into the last aspect — one that’s sometimes the most difficult to achieve as an engineer, and often takes a village of different perspectives and disciplines to get right.

At Qwilr, we tend to focus on merging design and engineering, with a good dollop of the experience gained from our customer support team. Throughout the process of building the editor, we kept in close communication with both teams, communicating back and forth during the development flow. These are the stages we went through:

  • Taking design to code by understanding the ideal behaviours.
  • When building the behaviours, we iterated quickly in development to provide builds for the design and support team to play with.
  • More intensive bug bashing rounds were done, in order to expose any unwanted behaviours.
  • A staged rollout was used, providing the editor to more and more of the user base each time.

Designs to code

This stage involved taking a descriptive definition of the editor’s behaviour, and turning it into a prescriptive task list we directly coded into the editor’s behaviours. Initial designs were created with a draft ‘Ideal Editing Experience’ document created by Dom, our Design Lead, which broke down the specific behaviours that would be implemented by the engineering team. Some things can get lost in translation, and to avoid this, each conversion was shared back with Design to make sure there was no miscommunication of intent.

Our “Ideal Editing Experience” doc, documenting all our decisions

The core engine of the editor also relied on this document, so we knew which levers needed to be exposed when editing.

Iterating quickly

The core editor engine was built in conjunction with the previous stage, providing behaviours the ability to subscribe to particular events and contexts, and then pull particular levers in response. We then hit the stage of building out the behaviours.

As we moved down the list of behaviours, we’d create frequent deployments to a development environment to provide Design with a usable example of how the behaviours played out in the editor. This revealed any kinks in behaviours, unresolved edge cases, and in some instances, removing the behaviour altogether

This quick iteration was critical. Some edge cases and subtle behaviours can be lost when you’re simply ‘playing around’ with the editor, as opposed to creating a document exactly like our users do.

Bug bashing

The previous development stage was a lot of back-and-forth, generally with multiple touch points between Engineering and Design per-day. As the editor’s behaviour became more fleshed out, we added in more holistic bug bashes. Getting support and other developers to work on some documentation and proposals in the new editor. Each of the isolated behaviours previously tested now needed to sing together in harmony.

This stage also involved moving some behaviours back to design, namely if they weren’t working well together, or weren’t originally considered.

Staged rollout

Over the past couple of months we’ve been rolling out the editor to increasing segments of our user base. This was a fairly standard approach, beginning with a beta group of users, who are more understanding of any bumps they may find (and importantly, communicative about reporting them back to us) then moving onto the general user base in stages.

Maintaining these touch points, regardless whether they were driven by Design, Engineering, or Support, take time. The default (or perhaps just mine) is to take the specification, do some clarifications and code designs that are shared back with the design team, then dive into the code and implementation. Then finally, and only towards the end of the process, coming up for air to show off what I’ve built. While this can seem like the easiest approach at the start, it often results in some taxing back-and-forth later in the process, when it’s harder to make the necessary changes to get the finished feature matching the initial intentions. In contrast, the extra time taken to continually iterate between to Design and Support gave a less stressful development experience and a better result than we’d otherwise built.

No dev is an island, and building complex software requires many disciplines. For building intuitive features, keeping a tight cycle with your multi-disciplinary teams is crucial so that our ‘logic’ doesn’t get in the way of what ours users actually expect — or need. Perhaps I’m just late to the party of close interactions between the various disciplines, but I can’t imagine developing any other way now.

--

--