An Article CMS Prototype

Using Github, React, Next.js, Draft.js and GraphQL

Thomas Preusse
Project R
5 min readMar 23, 2017

--

Building a new publication — as we’re doing at Project R right now—from scratch is challenging. Finding a CMS solution is one of the big challenges.

Conventional wisdom seems to suggest to build upon an existing solution, ideally bought from or maintained by an consultancy specialising on a specific system.

But once you give away the creation process of your content, innovation becomes harder. Design and concept tends to become limited to what’s already possible in pre-built systems. Building integrations and bridges consumes essential development time.

Let’s Prototype a Flexible System

The system should evolve the front end and editing interface together. Have a single definition of how something looks and works and then use it across the board. It should track changes over time, just like code, content should be attributable. The content should be stored in a simple, human-readable format. Mass modifications should be possible and lock-in avoided.

To accomplish this and implement it within a few days or weeks instead of months or years one needs to utilize existing tools and pick them wisely.

Markdown and Git Based Versioning

Markdown is an easy-to-read and easy-to-write plain text format. It can be checked into Git and produces understandable diffs. One can easily update a directory of markdown files with search and replace in a text editor.

I will use GitHub for this prototype. They offer OAuth, a REST API, and even an early access GraphQL API. I ended up not using the GraphQL API yet. Instead I’ve defined my own GraphQL schema and fetch the data with the npm package github-api on the server.

An alternative would be to use a self hosted GitLab, which replicates most of GitHub’s functionality ;)

This idea is not new, it has been implemented by a creative engineering team in Washington DC several years ago: github.com/prose.

The Framework

Don’t start writing apps from scratch. Use something universal — allowing for shared components between server, client and the editor. React is the logical choice: it offers server and client side rendering, allows to declare reusable components and is flexible enough to integrate almost anything.

The framework Next.js on top helps writing complete apps with server rendering, code splitting and full interactivity with zero hassle. No webpack config required.

To access the GraphQL endpoint effortlessly I base the prototype off the Next.js with Apollo example.

The Editor

Now the main challenge is to bring the universal components to a content editable editor. The goal is an editor experience as smooth as Medium but with more advanced capabilities like charting and interactive personalization.

Draft.js is a rich text editor framework for React. Getting started is very simple:

There is also quite an ecosystem around it: DraftJS Plugins layers a composable plugin system on top with existing implementations of essential functionality. There are impressive open source editors build upon Draft.js, namely Medium Draft and Megadraft. Facebook itself uses it for status updates and notes.

I started off by using Medium Draft and was able to get a fully working system after a week. This included login with GitHub, the editor with all basic text styles and images, serialization to markdown, committing to and loading data from GitHub.

Writing an article with an image

But it didn’t feel quite right, I barely touched the Draft.js API. I wanted to dig deeper and decided to re-implement the same with DraftJS Plugins. While doing so I noticed an interesting case, the image with a caption:

Left: Facebook Notes, right: Megadraft
Left: Medium Draft, right: the real thing

It’s implemented differently everywhere, only Medium Draft went through the hassle to keep it in the natural Draft.js editor flow. Focus is weird and unclear in all Draft.js implementations, none of them feel as good as the real thing.

I ended up implementing my own image with a caption as a DraftJS plugin. But I didn’t manage to make an improvement over Medium Draft with a reasonable time effort.

My conclusion is: Draft.js is built for status messages and is great at it. But using it for articles is a stretch. If an image with a caption is already hard to implement, implementing a personalized chart with editable texts would be hell.

Ian Storm Tayler summarizes the issues with Draft.js well in his explanation why he created Slate (transformed to bullet points for clarity):

• lots of the logic around the schema is hardcoded in “core” and difficult to customize
• the transform API is complex to use and not suited to collaborative editing in the future
• serialization isn’t considered by the core library in a nice way
• the flat document model made certain behaviors impossible
• lots of the API feels very heavy to work with

I couldn’t agree more and I’m looking forward to exploring Slate in depth.

Open Source

The whole prototype is open source and available at github.com/orbiting/cms-draft.

The next steps:

  • Replace Draft.js with Slate
  • Tackle Publication Management

About Project R

Project R is a cooperative in Switzerland to foster journalism. The cooperative is currently working on building an independent digital magazine which will be fully open source. Learn more at project-r.construction.

--

--