> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/developers/docs/_mcp/server.

# Rendering Contentful Rich Text with Javascript

> This article details how to use Contentful's JavaScript client library and the rich text html renderer to render rich text fields as html

Contentful offers many tools to help you work with our [Rich Text](/concepts/rich-text) feature. This guide is meant to help put the pieces together and provide resources for learning more. It focuses majorly on Contentful's [client library](https://github.com/contentful/contentful.js), [rich-text-html-renderer](https://github.com/contentful/rich-text/tree/master/packages/rich-text-html-renderer), and [rich-text-react-renderer](https://github.com/contentful/rich-text/tree/master/packages/rich-text-react-renderer) to render your Rich Text fields with HTML.

## Prerequisites

You should already have:

* a space
* a CDA token
* at least one content type with a rich text field
* at least one entry of that content type
* Node (at least v8) and NPM installed
* knowledge of installing tools using the command line.

## Getting Started

To create a space, check [CMA reference](/references/content-management-api/overview). To learn about retrieving tokens, refer to [Authentication](/references/authentication).

For content using rich text, refer to this [Getting Started with Rich Text guide](/tutorials/general/getting-started-with-rich-text-field-type).

## What is rich text?

Rich text is a new JSON format for handling complex content structures in a strongly typed manner. It is represented by the rich text field in Contentful.

## Working with a rich text property in Contentful JS client libraries

1. Install the Contentful client library and rich text html renderer:

```
npm install --save contentful @contentful/rich-text-html-renderer
```

2. Use the Contentful client library to retrieve an entry containing rich text

```javascript
import * as contentful from 'contentful';
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';

const client = contentful.createClient({
  space: '<space_id>',
  environment: '<environment_id>', // defaults to 'master' if not set
  accessToken: '<content_delivery_api_key>',
});

client.getEntry('<entry_id>'); // asynchronous, returns promise
```

3. Invoke the rich text html renderer when the entry resolves

```html
<!DOCTYPE html>
<html>
  <head>
    <script
      src="https://cdn.jsdelivr.net/npm/contentful@7.0.5/dist/contentful.browser.min.js"
      charset="utf-8"
    ></script>
    <script>
      var exports = {}; // quick fix because 'exports' is not defined in rich-text bundle below
    </script>
    <script
      src="https://cdn.jsdelivr.net/npm/@contentful/rich-text-html-renderer@12.0.0/dist/rich-text-html-renderer.es5.min.js"
      charset="utf-8"
    ></script>

    <script>
      const client = contentful.createClient({
        space: '<space_id>',
        environment: '<environment_id>', // defaults to 'master' if not set
        accessToken: '<content_delivery_api_key>',
      });

      client
        .getEntry('<entry_id>')
        .then((entry) => {
          const rawRichTextField = entry.fields.body;
          return documentToHtmlString(rawRichTextField);
        })
        .then((renderedHtml) => {
          // do something with html, like write to a file
          console.log(renderedHtml);
          document.getElementById('rich-text-body').innerHTML = renderedHtml;
        })
        .catch((error) => console.log(error));
    </script>
  </head>
  <body>
    <p>Here is my rendered rich text:</p>
    <div id="rich-text-body"></div>
  </body>
</html>
```

## Customized rendering

The rich text html renderer also accepts custom renderers as optional parameters.

```javascript
import { BLOCKS, MARKS } from '@contentful/rich-text-types';
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';

const document = {
  nodeType: 'document',
  data: {},
  content: [
    {
      nodeType: 'paragraph',
      data: {},
      content: [
        {
          nodeType: 'text',
          value: 'Hello',
          data: {},
          marks: [{ type: 'bold' }],
        },
        {
          nodeType: 'text',
          value: ' world!',
          data: {},
          marks: [{ type: 'italic' }],
        },
      ],
    },
  ],
};

const options = {
  renderMark: {
    [MARKS.BOLD]: (text) => `<custom-bold>${text}<custom-bold>`,
  },
  renderNode: {
    [BLOCKS.PARAGRAPH]: (node, next) =>
      `<custom-paragraph>${next(node.content)}</custom-paragraph>`,
  },
};

documentToHtmlString(document, options);
// -> <custom-paragraph><custom-bold>Hello</custom-bold><u> world!</u></custom-paragraph>
```

You can find more examples and a list of accepted custom renderers in the [documentation](https://github.com/contentful/rich-text/tree/master/packages/rich-text-html-renderer) for the html renderer library.

## Customized rendering in React

The [React](/sdks/javascript/tutorials/react-tutorial) renderer as well as html-renderer accepts renderers as optional parameters.

```javascript
import React from 'react';
import ReactDOM from 'react-dom';

import { BLOCKS, MARKS } from '@contentful/rich-text-types';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';

const richTextDocument = {
  nodeType: 'document',
  data: {},
  content: [
    {
      nodeType: 'paragraph',
      data: {},
      content: [
        {
          nodeType: 'text',
          value: 'Hello',
          data: {},
          marks: [{ type: 'bold' }],
        },
        {
          nodeType: 'text',
          value: ' world!',
          data: {},
          marks: [{ type: 'italic' }],
        },
      ],
    },
  ],
};

const Bold = ({ children }) => <span className="bold">{children}</span>;

const Text = ({ children }) => <p className="align-center">{children}</p>;

const options = {
  renderMark: {
    [MARKS.BOLD]: (text) => <Bold>{text}</Bold>,
  },
  renderNode: {
    [BLOCKS.PARAGRAPH]: (node, children) => <Text>{children}</Text>,
  },
};

const rootElement = document.getElementById('root');
ReactDOM.render(
  documentToReactComponents(richTextDocument, options),
  rootElement
);

// -> <p class="align-center"><span class="bold">Hello</span><u> world!</u></p>
```

You can find more examples in the [documentation](https://github.com/contentful/rich-text/tree/master/packages/rich-text-react-renderer) for the React renderer library.

## Migrating from markdown to rich text

If you already have markdown fields, you can use the [rich text from markdown](https://github.com/contentful/rich-text/tree/master/packages/rich-text-from-markdown) package. It automatically converts many specific markdown nodes to rich text, with the option of adding a callback for unsupported nodes. See the documentation for the package for more examples and the list of supported markdown nodes.

## Future integrations

You may have noticed all our rich text tools can be found in our [github repository for rich text](https://github.com/contentful/rich-text). We plan to add more rich text integrations in the future. They will all be made available in this same, central location.

## Next steps

* [Learn about Contentful's Rich Text field type](/concepts/rich-text)
* [Build a React application powered by Contentful](/sdks/javascript/tutorials/react-tutorial/)
* [Get started with the JavaScript client library](/sdks/javascript/tutorials/using-js-cda-sdk/)