Over the past four years, I’ve helped design Ghost, the open-source technology that allows publishers and creators to build a sustainable business with their content.

I’ve been involved in every area of the product — from memberships, to themes, to the signup flow. But throughout the years, my main focus has been on the area where people spend the most time: the editor.

A complete rewrite

Ghost’s editor is the cornerstone of our product; it's where people write, create, and publish their work.

In 2018, Ghost moved from a Markdown editor to a WYSIWYG editor. This iteration introduced "cards," which allow users to insert various types of content anywhere within their text via a card menu.

Ghost's first WYSIWYG editor in 2018

This was built in Ember.js on an open JSON-based document storage format called MobileDoc. We loved how it worked, but MobileDoc never became widely adopted, so the technology underpinning our editor became stagnant. This limited our ability to build new features, and solve frustrating core bugs (like better mobile support). As the feedback from users grew louder, we got increasingly restless.

We’ve always been proud of how minimal yet powerful the editor is, and wanted to be able to continue to deliver a high quality experience. So, we set out to rebuild it on a new stack: React and Lexical — both of which are open source frameworks developed by Meta.

Projects at Ghost typically span two to six weeks. But in this case, a larger effort was needed to open new doors. This project reflects over a year of quiet, dedicated teamwork.

Our goal was to achieve feature parity with the old editor in a small team of two engineers and a designer — Kevin (who built the original editor), Ronald and myself. For me, this involved cranking out React components and creating a design system with help of Storybook. Eventually, we launched a public beta, allowing participants to report niche bugs and help us refine the rough edges.

Along with lots of small improvements, we began adding some of our most requested features. We defined success as silence; users stop asking for a feature or how to use a feature once it has been added. The editor should be an interface that's invisible until you need it, and powerful when you do.

Custom landing pages

Historically, posts and pages in Ghost have functioned very similarly, with the primary difference being that posts could be sent by email. Understandably, people wanted more flexibility from pages. Above all, they wanted to be able to add hero sections, and encourage site subscriptions.

Given Ghost’s strength is publishing and newsletters, we weren't looking to build a full-fledged page builder like Squarespace. But we still wanted to offer people a way to achieve these things, from within the editor they know and love. The solution was surprisingly simple.

First, we added a toggle to hide the page title and adjust the margin between the top navigation, page content, and footer.

Second, we added Signup and Header cards — full width cards with various layouts, including optional subscribe forms or buttons.

These two functionalities combined unlocked endless possibilities for making pages look different, without any coding required.

Internal linking

Many of our publishers send out a weekly newsletter featuring the week's highlights. Such posts typically contain a list of links to previous posts. While this was possible, the process certainly wasn't easy. Most people resorted to searching on Google, hoping the right article would appear based on their keywords. Tab overload was a common complaint.

To help publishers put their weekly newsletters together effortlessly, we introduced internal linking. The pattern that intuitively made most sense was inspired by Notion — an inline modal that pops up when adding a link. A similar modal also appears when using the @ symbol, and when inserting a bookmark card via the /bookmark shortcut.

0:00
/0:10

TK reminders

Busy authors who file a lot of stories often make heavy use of TK as a placeholder for content which is still "to come". It's the editorial equivalent of //TODO.

We wanted to help ensure all those TK todos are finished off before tens of thousands of newsletters are flying across the internet on their way to reader inboxes.

TK's are now highlighted with a little indicator, and clicking on them selects the text for quick replacement. The editor also warns you if it detects any missing content before you publish a post. A small but much loved detail, designed to avoid frustrating mistakes.

0:00
/0:14

Emoji autocomplete

Not much explaining needed here — we've added a native emoji picker for those who enjoy using emojis in their post. 🙋‍♀️ Simply pressing : and continuing to type triggers a minimal, inline picker. We opted for a list format instead of grid to include an educational component. Seeing the shortcodes will speed up emoji insertion using a keyboard after repeated use.

Post history

During a team week in Wales last year, we began laying the groundwork for a multiplayer editor — something that MobileDoc had previously prevented. While we are still a long way away from fully supporting this, the first step was adding versioning. Now, people can view previous versions of their post, and restore past edits made by anyone.

0:00
/0:15

Originally, we intended to add diffing, but soon realised it was a massive rabbit hole that would have stopped us from shipping anything that week. Instead, we delivered 90% of the value: the ability to browse through your post's edit history, see who edited what and when, and restore any version with a single click.

Onwards and upwards

This concludes the little peek behind the curtain of the Ghost editor's development—for now. As with all products, it is never truly finished. We are currently working on adding footnotes (one of our most requested features ever) and editor customisations.

Want to give it a try? Visit the Koenig demo.

Other projects I've worked on

The Ghost team in Sitges, 2022

Want to chat? Get in touch or find me on GitHub, LinkedIn or Instagram.