> 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/_mcp/server. # Getting started with Rich Text > A guide to getting started with Rich Text in your Contentful app | Enabling the Rich Text | Render the response in HTML ## Enabling the Rich Text * Select the desired content type from the **Content model** tab. * Create a new field by clicking **Add field** and select Rich Text as the field type.  ## Customize the formatting options Customization assists in selecting relevant options for the authors in the toolbar while using the [Rich Text](/concepts/rich-text) editor. It can be done with an API call or on the web app. ### Customization with an API call A content type using Rich Text can be customized by making a [Content Management API (CMA) call](/references/content-management-api/overview). For example, following is the API call to only allow paragraphs and specific formatting in them: ```json { "id": "YOUR_CONTENT_TYPE_ID", "name": "Rich Text Field", "type": "RichText", "validations": [ { "enabledNodeTypes": ["paragraph", "text"], "message": "Please choose a valid node type (should be a paragraph or text)." }, { "enabledMarks": ["bold", "italic"], "message": "Please remove any extraneous document markup - only bold and italics are supported." } ] } ``` Similarly, to limit the type of content types that an author could hyperlink to: ```json { "id": "YOUR_CONTENT_TYPE_ID", "name": "Rich Text Field", "type": "RichText", "validations": [ { "enabledNodeTypes": ["paragraph", "text", "entry-hyperlink"], "message": "Please choose a valid node type (should be a paragraph, hyperlink or text)." }, { "nodes": { "entry-hyperlink": [ { "linkContentType": ["page"], "message": "You can only hyperlink to Pages." } ] } } ] } ``` Refer to the [CMA reference](/references/content-management-api/overview) to learn more about the other available validation options. ### Customization on web app To customize the field on the web app: * Select the desired content type from the **Content model** tab. * Edit the Rich Text field's **Settings** and select the relevant formatting options.  ## Render the response in HTML The content added to the Rich Text field can be consumed from the API response and rendered further in the desired application. Rendering the API response (a JSON object) is not easy and requires effort to be converted to HTML. Hence, helper functions are created that allow to: * Render all the contents of a JSON response to HTML. * Apply a custom rendering function to an embedded entry. * Apply a custom rendering function to a default node, like a heading or a link, thereby applying personalized style and logic to the markup of an application. ### Use-cases around rendering the API response #### Add custom CSS classes to HTML elements Following is an example of adding CSS classes to paragraph tags in JavaScript in order to alternate their background color: ```js import React from 'react'; import ReactDOM from 'react-dom'; import { BLOCKS } from '@contentful/rich-text-types'; import { documentToReactComponents } from '@contentful/rich-text-react-renderer'; const richTextDocument = { nodeType: 'document', data: {}, content: [ { nodeType: 'paragraph', content: [ { nodeType: 'text', marks: [], value: 'I am an odd paragraph.', data: {}, }, ], data: {}, }, { nodeType: 'paragraph', content: [ { nodeType: 'text', marks: [], value: 'I am even.', data: {}, }, ], data: {}, }, ], }; const options = { renderNode: { [BLOCKS.PARAGRAPH]: (node, children) => (
{children}
), }, }; function paragraphClass(node) { const className = 'odd'; //alternate logic for 'odd' | 'even' return className; } const rootElement = document.getElementById('root'); ReactDOM.render( documentToReactComponents(richTextDocument, options), rootElement ); // ->I am an odd paragraph.
// ->I am even.
``` #### Link to entries Following is an example of how to render links to entries: ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import { INLINES } from '@contentful/rich-text-types'; import { documentToReactComponents } from '@contentful/rich-text-react-renderer'; const richTextDocument = { nodeType: 'document', data: {}, content: [ { nodeType: 'paragraph', content: [ { nodeType: 'entry-hyperlink', data: { target: { sys: { type: 'Link', linkType: 'Entry', id: '3vNbx1hjcsESSICSu2KuWs', }, }, }, content: [ { nodeType: 'text', marks: [], data: {}, value: "I'm linking to an entry", }, ], }, ], data: {}, }, ], }; const options = { renderNode: { [INLINES.ENTRY_HYPERLINK]: (node, children) => { // If you are using contentful.js client library, the referenced entry is resolved // automatically and is available at `node.data.target`. const referencedEntry = getEntryWithId(node.data.target.sys.id); return {children}; }, }, }; function getEntryWithId(entryId) { const mockEntry = { fields: { slug: 'entry-slug', }, }; return mockEntry; } const rootElement = document.getElementById('root'); ReactDOM.render( documentToReactComponents(richTextDocument, options), rootElement ); // I'm linking to an entry ``` #### Render custom widgets Following is an example to render a custom widget, such as a Carousel, within your flow of text, in JavaScript: ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import { BLOCKS } from '@contentful/rich-text-types'; import { documentToReactComponents } from '@contentful/rich-text-react-renderer'; const richTextDocument = { nodeType: 'document', data: {}, content: [ { nodeType: 'embedded-entry-block', data: { target: { sys: { type: 'Link', linkType: 'Entry', id: '3vNbx1hjcsESSICSu2KuWs', }, }, }, content: [], }, ], }; const options = { renderNode: { [BLOCKS.EMBEDDED_ENTRY]: (node) =>