Maintaining a multi-page, content-filled website today can be an extremely challenging and time-consuming task. The discrepancy between what the business team wants on the page versus what the development team can publish posed a challenge to us. Content Management System, or, CMS as it is more popularly referenced, provides a solution to this glaring problem by eliminating that bottleneck between content creation and content deployment. A CMS completely abstracts the process for non-developers in an extremely user-friendly way allowing them to publish content with some ctrl+c, ctrl+v magic and a few mouse clicks. With a CMS, there is no need to worry about the website's infrastructure.

Why Ghost?

At Blue Sky Analytics, when we first started publishing blogs on our website, we chose self-hosting Ghost for all our blogging needs. Ghost is a “headless” CMS, which means that it is a CMS that mainly exists to serve as a database. Ghost, according to their own advertising, primarily focuses on publishing blogs and other similar content. It was an easy choice to make initially compared to other CMS options like WordPress for a number of reasons. First, Ghost is very fast and lightweight since it focuses on blogging and thereby keeps its design minimalistic. Secondly and most importantly, with Ghost being a headless CMS, it can be seamlessly integrated into our website, which adopts the JAMstack architecture. Lastly, it has excellent documentation and support. Simply speaking, the blogs in Ghost were directly fetched via the API and populated in GraphQL.

The publishing and development flow on ghost

The publishing and development flow on ghost

Problems with Ghost

Although I’ve built up Ghost to be a be-all and end-all to our content publishing needs, it came with its fair share of problems that became quickly apparent.

  • The most glaring issue we noticed was the colossal amount of time that was wasted in copying the blogs that were initially on Notion and then pasting them into Ghost. The formatting would be completely skewed, and each line would have to be manually corrected to ensure that the blog had the correct styles.

  • Reviewing the first draft of any of the blogs was an impossible task because formatting and deploying the blogs on ghost would directly affect the website in production. There was no concept of first publishing the content to a staging environment to test and review the content.

  • Ghost also doesn’t have any native commenting support, which again creates a bottleneck when blogs need to be reviewed and/or edited.

  • We chose to self-host the CMS, and therefore, it was not worth the time to build a system for images in our blogs when we can just copy and paste the images into our cloud image-management repository Cloudinary.

However, this quickly became a chore to do, and along with the issues that were already plaguing us, we started to look at other options that would make the publishing process more efficient.

Notion - to the rescue?

At this point, we were already using Notion as a repository to store first drafts and other catalogue content. Notion, initially, was a simple note-taking and project management application. But, with the Notion API released, bringing with it the flexibility to build and manage a custom CMS, it became an option that we had to consider. There was no longer a need to self-host a CMS, thereby eliminating the cost entirely. With the Notion API continually evolving, we soon ghosted, well, Ghost, and started considering if Notion could solve all our current blogging issues. Notion natively provides the option to comment on content, and this reduces the time to review and edit drastically. The publishing process itself became efficient, with all content being written, managed, and reviewed in the same location. The bottlenecks between the publishing team and the platform team all but evaporated.

Notion and website architecture

Notion and website architecture

Content can now be managed in one location with relevant metadata to allow for selective deployment in staging or production environments. It also gives us a great deal of freedom and flexibility during frontend development, both in terms of performance and general infrastructure. Abstracting code became much easier, and uploading images individually to Cloudinary was no longer necessary. This became a process that we could now automate with not much effort.

How notion solved our CMS problems

How notion solved our CMS problems

Notion isn’t a perfect solution

With all that being said, the Notion API comes with its own set of problems. Initially, when the first iteration of the API was released, the documentation was atrocious. We spent more time on Stack Overflow and GitHub Issues trying to figure out solutions to bugs rather than consulting the API documentation because of how unreadable it was. During this time, it was an arduous task to find what we wanted, and we experienced something that every developer dreads: StackOverflow did not have the answers to our queries.

StackOverflow did not have the answers to our queries

StackOverflow did not have the answers to our queries

However, once the next version was released, the API dramatically improved with better documentation and many more options like more block types. Data that is fetched through the Notion API is in the form of what Notion calls “blocks”, for instance, a paragraph block, a heading block, and so on. It is very similar to the way HTML elements are defined. Due to the fledgling nature of the API, we had to rely on third-party libraries to convert these blocks into a format we wanted, like notion-to-md for a markdown format and then convert the markdown using markdown-it HTML format. We also had issues with embeds which exists to this day. Although Notion has an embed block, It fails to generate embeds for sites like YouTube, for example. This resulted in us writing code to handle youtube embeds. To compound these issues, there aren’t many libraries available in the first place. Additionally, there aren’t any gatsby plugins that help with sourcing notion content either. The ones available are deprecated, and we ended up writing a plugin of our own. Although, I consider that a positive as there is a lot of room for developers with little to no experience in working on open-source projects to develop a lot of cool plugins that support the Notion API.

Conclusion

On the whole, the switch from Ghost to Notion has been a very positive experience for the whole team in terms of performance, efficiency, and flexibility. Of course, using the Notion API hasn’t been perfect, but it has been a perfect choice for our blogging needs.