Rendering linked assets and entries in the Contentful Rich Text field

Illustrated image showing how rich text is rendered with JS
Published
April 14, 2021
Category

Guides

In order to understand how to render linked assets and entries inside the Contentful Rich Text field on the front end, it is crucial to understand how linked assets and entries work across Contentful as a whole. This post focuses on working with Contentful in a JavaScript ecosystem, but the principals and methods are the same across the tech stack and can be applied to your favorite programming language, too.

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

Now that we’re familiar with how Contentful returns items and their linked entries and assets, and how we can resolve the links either manually (through a lot of hard work!) or with the JavaScript SDK (that’s nice and easy), let’s look at how it works with links inside the Rich Text field.

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.

Read more about the Rich Text field here

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.

Screenshot of rich text field embedded entries

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

The following examples use JavaScript to fetch data from this example blog post. The blog post is served on an application built with Next.js — but we won’t be going into Next.js in this post.

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: items and includes.

Inspecting the Rich Text body field, we observe that:

  • items[0].fields.body.content contains a number of nodes — text nodes (with nodeType: "paragraph") and additional nodes with the property data.target.type: "Link" and nodetype: "embedded-entry-block", nodetype: "embedded-entry-inline", and nodeType: "embedded-asset-block"with empty content nodes

Wait — the linked entries inside items[0].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 items array:

  • includes.Entry contains the data for the two linked entries (the code block and the video embed)

  • includes.Asset includes 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?

Using the Contentful JavaScript SDK

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.

Under the hood, the JavaScript SDK uses the contentful-resolve-response package, which converts the flat nodes into a rich tree of data. The one limitation of the Contentful API to remember is that it will only return linked entries up to a maximum of 10 levels deep that can be resolved. However, given that our Rich Text field contains embedded entries and assets only one level deep in this example, we’re good to go.

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.

Make the same call to fetch an entry including a Rich Text field via the JavaScript SDK:

And here’s the processed JavaScript object returned from the API call via the SDK, containing the data we need for each node in the Rich Text response.:

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.

Now that we have our links and their data inside the Rich Text field where we need it in a nicely packaged JavaScript object, how do we render the HTML for each node?

Rendering the Rich Text response from REST with linked assets and entries on the front end


Contentful provides you with tools to speed up your workflow on the front end and to allow you to work with the Rich Text field data and render the nodes into HTML — Rich Text field renderers. For this example, we are going to be using the @contentful/rich-text-react-renderer to demonstrate the concepts in JavaScript and React.

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.

With the response from the REST API processed by the JavaScript SDK — which has linked the entries and assets for us — we can call 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.

TL;DR:

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 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 const and =):

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 and links. 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 links node.

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 BLOCKS.EMBEDDED_ENTRY and BLOCKS.EMBEDDED_ASSET with documentToReactComponents, we can create an assetMap (id: asset) and entryMap (id: entry) to store data we can reference by ID.

When the 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.

Take a look at this example repository on GitHub, which is a demo Next.js application that contains all of the example code in this post, and demonstrates how we can fetch this data and render the Rich Text field linked assets and entries using both the REST API with JavaScript SDK and the GraphQL API. 

Wrapping up

Using the JavaScript SDK with the REST API and the contentful-rich-text-react-renderer we can define our renderOptions without worrying about having to resolve our links. All the data we need is available via node.data.target.

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!

Start building

Use your favorite tech stack, language, and framework of your choice.

About the author

Don't miss the latest

Get updates in your inbox
Discover new insights from the Contentful developer community each month.
add-circle arrow-right remove style-two-pin-marker subtract-circle remove