Before you get started, you might want to check out this blog post to take a deep dive into the inner workings of the Contentful REST API and GraphQL API, how our links are returned in the response and how they can be resolved into a rich object graph.
Exploring the Rich Text field editor
Rich Text is a field type that enables authors to create rich text content, similar to traditional "what you see is what you get" (WYSIWYG) editors. The key difference here is that the Contentful Rich Text field response is returned as pure JSON rather than HTML. Additionally, it allows entries and assets within our Contentful space to be linked dynamically and embedded within the flow of the text. It offers common text formatting options such as paragraphs, lists and all that good stuff, but allows us to embed and link other references, too.
Find an example of the Rich Text field editor in the Contentful UI below. It includes several paragraphs but also links a blog post, a video embed entry, an image asset and a code block entry.
If you want to code along with the post, you can create the following content types in your Contentful space, which we will use in our examples:
The code block entry contains the following fields:
Description (short text)
Language (short text)
Code (long text displayed as a markdown field)
The video embed entry contains the following fields:
Title (short text)
Embed URL (short text)
That’s the visual structure of the Rich Text field, but how is the content — and especially the references — represented in the JSON response? What are the differences between the REST and GraphQL API responses? Let’s take a look.
Rendering Rich Text references using the REST API
We can request the data via this URL:
It returns this raw response from the REST API. This is trimmed down to show only the fields we are concerned with in this example:
We can see that the entry response contains two top-level nodes:
Inspecting the Rich Text
body field, we observe that:
items.fields.body.contentcontains a number of nodes — text nodes (with
nodeType: "paragraph") and additional nodes with the property
nodetype: "embedded-entry-block", nodetype: "embedded-entry-inline", and
nodeType: "embedded-asset-block"— with empty
Wait — the linked entries inside
items.fields.body.content are empty! Where is our data?
The actual data for the linked entries referenced in the
body.content field are in the
includes object, returned alongside the top-level
includes.Entrycontains the data for the two linked entries (the code block and the video embed)
includes.Assetincludes the data for the linked asset (the image)
What do we do now? How do we link all the data together so we can access it inside of the
body node as we would expect?
The good news is, that if we’re using a Contentful SDK to make a call to the Contentful API, those linked assets and entries in the Rich Text field will be resolved for you.
The linked entries that are returned from the API are determined by the
include parameter on the request to the API. Read more about the include parameter here.
Notice how all the data that was previously contained in a separate
includes node from the raw REST API response is now inserted beautifully into the Rich Text field response — where we would expect.
Rendering the Rich Text response from REST with linked assets and entries on the front end
There are a number of Rich Text field renderer packages available for your favorite programming languages and frameworks — check them out on GitHub here.
Let’s return to the example Rich Text field with two embedded links — a code block entry and a video embed entry — and an image asset. Most likely, we will want to display the data from these entries in particular ways for the front end, such as by using specific HTML elements, adding CSS classes, or rendering custom React components.
documentToReactComponents with an optional
options parameter, allowing us control over how our data is displayed on the page.
Notice below, that for each node in the Rich Text response, the SDK has resolved the links for us. We can access the type of entry or asset using
node.data.target.contentType.sys.id, and access the fields using
node.data.target.fields and so on.
This is where the link resolution magic of the SDK comes into play.
Don’t worry about links if you’re using an SDK and the contentful-rich-text-react-renderer! For each node in the Rich Text response, access the type of entry or asset using data.target.contentType.sys.id, and access the fields using data.target.fields and so on.
The SDK and the renderer package handles linked entries and assets beautifully for us. But how does it work when using the GraphQL API?
Rendering Rich Text references using the GraphQL API
The Contentful GraphQL API doesn’t require an SDK to handle linked entries. Understanding the concepts of links covered in this blog post helps us out massively.
To explore the GraphQL query in this example, navigate to the following URL and paste the query below into the explorer (without the
The Rich Text field response from the GraphQL API is different and contains two top-level nodes.
Here’s the GraphQL query for our blog post:
And here’s how we can query the Contentful GraphQL API using fetch:
The Rich Text field response (
blogPost.body) contains the following two top-level nodes —
json includes the Rich Text JSON tree representing whatever people put into the editor. It is to point out that this JSON structure only includes ids to possibly linked references. These references can then be queried using the
The references are not automatically resolved inside of the Rich Text JSON. This means we have to take a different approach to render and resolve links when using GraphQL.
Rendering the Rich Text response from GraphQL with linked assets and entries on the front end
We can still use
documentToReactComponents to render our Rich Text field data to the DOM, but instead of passing in an options object, we’ll need to construct the object using a custom function to process a bit of logic to resolve our links.
In order to target asset and entry data when rendering
documentToReactComponents, we can create an
assetMap (id: asset) and
entryMap (id: entry) to store data we can reference by ID.
renderOptions reaches the entry and asset types, we can access the data from the maps we created at the top of the function, and render it accordingly.
And there we have it! It’s a little more work to render our links with GraphQL, but if we understand how the SDK works, its magic and how links work across Contentful as a whole, we’re all set.
Using the GraphQL API and the contentful-rich-text-react-renderer, we have to perform the mapping of the linked entries ourselves, which we can do when defining our renderOptions and passing in the links as an additional parameter.
The power of the Contentful Rich Text field is that it is stored in pure JSON data. With the knowledge of how linked assets and entries are referenced at a content type level, you’re empowered to render the contents of your Contentful Rich Text fields, with or without SDKs or other supporting packages. Go forth and build stuff!
If you’ve got any questions about linked assets and entries in Contentful, come and join the Contentful Community Slack, where we’ll be more than happy to help!
Show us what you've built: Contentful now has a Developer Showcase where devs from the Contentful community can share their projects with others. Join in!