H
o
m
e

Implementing Contentful

April 21, 2019

This is an image. Foobar.

Why Contentful?

You know how the new Reddit started using a fancy pants text editor, as opposed to the old markdown editor? Contentful essentially has that same fancy pants editor. It's very friendly for people of all backgrounds, technical or not.

I have some plans to make a community blog where my friends (who wouldn't need any coding experience) could write and contribute posts. Contentful is the key to accomplishing that.

Integrating Contentful content alongside existing Markdown

The first 9 posts of https://coffeecodeclimb.com have been markdown, stored in the same project repo. This post that you're reading right now is the first post that isn't markdown, and isn't stored in the project repo. As far as simply implemented Contentful, Gatsby's gatsby-source-contentful plugin docs have been really good. However, I before completly rewriting my blog to take only Contentful content, I wanted to see if I could have both coexist. I realized there was a lot more hacking & fiddling to be done, which turned out to be a pretty dope learning experience.

1. Make the Content Model mimic existing Frontmatter format

The frontmatter of my first 9 posts have a specific format that kind of defined how data from my blog posts got passed around in the project. Contentful has a content model, which as the name suggests, defines your content's structure (similar to frontmatter). In order to avoid as much unnecessary rewriting as possible, I needed to make the content model mimic my existing frontmatter as closely as possible. They both have fields like title, description, tags, etc, so all I had to do next was reuse existing code.

2. Update GraphQL queries

Installing gatsby-source-contentful and updating my gatsby-config.js introduced many handy new GraphQL Types definitions and Queries (or Schema definitions for Queries - I don't fully understand GraphQL terms yet).

Below, adding the allContentfulBlogPost field was one example of many updates I needed to make to the GraphQL queries in my project. The existing allMarkDownRemark field asks the built-in GraphQL endpoint for the first 2000 markdown blog posts. For all the frontmatter___tags that I've ever used in my frontmatter, it returns a group object that contains the fieldValue and totalCount of each.

a code snippet for first-contentful-post

In order get all the tags & counts that I've used in my Contentful posts as well, I just reused the query with minimal renaming. allContentfulBlogPost is one of the newly-introducted, and built-in, Queries that I was able to access.

3. Finagle some Rich Text

Here's a screen shot of the old way I wrote blog posts - Markdown

Markdown: the old way of writing a blog post

... and here's a screenshot of how I'm writing this blog post - Rich Text

Rich Text: The new way of writing a blog post.

So I set up everything I needed for my project to fetch and render my Contentful posts on my blog. For the most part all the text rendered properly, out-of-box, but the images did not. I needed to reference the contentful/rich-text docs, which honestly wasn't the best developer experience. I frantically console.log'd and trial-and-error'd my way creating a custom renderer for my Contentful rich-text images. The arguments that I was passing to an imported function, documentToReactComponents(), looked like this:

arguments that I passed to documentToReactcomponents

4. Extend site features to include Contentful posts

This part was quite fun! I needed to extend some site features, such as Next/Previous posts and Tag rendering, to also account for the new posts coming from Contentful.

One tricky task was getting the tags used in both Markdown and Contentful posts and rendering them alphabetically, and with their total count. (See https://coffeecodeclimb.com/tags) This felt like a computer science puzzle. The tags get queried-for via GraphQL and are returned as an array of objects: [{fieldValue: "apple", totalCount: 4}, ...]. Some fieldValues would be the same for both Markdown and Contentful posts, and in that case I would want to sum their totalCount, and eventually return a new array of the same shape, sorted, and summed. I had a lot fun shopping for Lodash functions while contemplating how to solve this problem.

In the end I didn't use any Lodash helpers, but I did discover some new ones, like _.union that I started using elsewhere. Also, my brother ended up giving me some advice on how to solve the problem:

sort both arrays by fieldValue

compare the first element of each array

If they are the same

Remove both of them, and add an element to the result array with total count of the two elements summed

If they are not the same, take the smaller tag and remove it, add to the result array

This is what I came up with.

Helper function to join MarkdownRemark & Contentful tags

Anyways...

Writing about this has been a challenge.

It has never been my forté. I want to get better at reasoning, vocalizing my logical, reflecting on written code, and writing about what I wrote. I guess this will come with time, and methodical mileage. So for now, I'll just keep writing and getting less bad at it.

If you made it this far, please do leave a comment below!

Tags: contentfulcmsgatsbycodeblogrich textgraphqlmarkdown
Kevin Wang

A blog by Kevin Wang. Jazz Guitarist → Barista → Healthcare Startup Potato → Rock Climber → Front End Engineer