# Rich Text field

Learn more about Hygraph's Rich Text field.

## Overview

The `RichText` field type is an advanced String field that returns your content in 4 different formats by default: `raw`, `HTML`, `markdown`, and `text`. `JSON` is also available when embeds are enabled.

The Rich Text field renders an advanced `textarea` with tools to add headings, links, tables, images, lists, etc.

When a Rich Text field is added to your model, it will automatically generate the following types:

```graphql
type RichText {
  raw: RichTextAST!
  html: String!
  markdown: String!
  text: String!
  json: RichTextAST!
}
```

## Rich Text data

Let's talk about Rich Text data in more detail.

- **Raw:** `raw` AST (Slate Nodes) offers complete control over how nodes are presented to the user.
- **JSON:** `JSON` representations of RTE allows as much control as `raw` does, but offers the possibility of creating embeds.

  **Note:**
  `RichText` will include the field `JSON` in addition to `raw` only if Rich Text Embeds are enabled. Both `JSON` and `raw` are aliases, but if you have embeds enabled you should ideally use `JSON`.

- **HTML:** `HTML` can be used with a Rich Text renderer for customization purposes. While rendering the HTML of your rich text is simple, it doesn't offer great customization.
- **Markdown:** `Markdown` - like `HTML` - can be used for customization. While `markdown` is easier to read and write - specially for users without a technical background - it's not as expressive as `HTML`. To present `markdown` on a page, you'll need a `markdown` parser that will convert `markdown` to `HTML`.
- **Text:** `text` is mostly used for excerpts, as links, images, and even line breaks are removed.

### Use Cases

- **Raw:** Use `raw` when you want to control the rendered output using our render libraries.
- **JSON:** Use `JSON` for the same as `raw` but when you also need embeds.
- **HTML / Markdown:** Use these when you need to make customizations and want to insert pre-built `HTML` or `markdown` into an app.
- **Text:** Use `text` when you want to provide the text as data to a script, such as making full-text search.

### Examples

This section takes a simple Rich Text piece with a title, a paragraph, a link, and bold text, and offers its `JSON`, `HTML`, `Markdown`, and `Text` representations.

  **JSON**

```
"json": {
          "children": [
            {
              "type": "heading-one",
              "children": [
                {
                  "text": "Example Rich Text Copy"
                }
              ]
            },
            {
              "type": "paragraph",
              "children": [
                {
                  "text": "This is a regular paragraph, including a "
                },
                {
                  "href": "https://hygraph.com/docs",
                  "type": "link",
                  "children": [
                    {
                      "text": "hyperlink"
                    }
                  ]
                },
                {
                  "text": " and "
                },
                {
                  "bold": true,
                  "text": "bold text"
                },
                {
                  "text": "."
                }
              ]
            }
          ]
        }
```

  
  **HTML**

```
"html": "<h1>Example Rich Text Copy</h1><p>This is a regular paragraph, including a <a title=\"https://hygraph.com/docs\" href=\"https://hygraph.com/docs\">hyperlink</a> and <strong>bold text</strong>.</p>"
```

  
  **Markdown**

```markdown
"markdown": "# Example Rich Text Copy\n\nThis is a regular paragraph, including a [hyperlink](https://hygraph.com/docs \"https://hygraph.com/docs\") and **bold text**.\n"
```

  
  **Text**

```text
"text": "Example Rich Text Copy\\nThis is a regular paragraph, including a \\nhyperlink\\n and \\nbold text\\n."
```


## Rich Text embeds

**Note:**
If Rich Text Embeds are enabled, `RichText` will include the field `JSON` in addition to `raw`.

For example, we can query all of those on our `RichText` field type `content`:

  **Request**

```graphql
{
  posts {
    content {
      raw
      html
      markdown
      text
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "posts": [
      {
        "content": {
          "raw": {
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "text": "GraphQL CMS"
                  }
                ]
              }
            ]
          },
          "html": "<p>GraphQL CMS</p>",
          "markdown": "GraphQL CMS\n",
          "text": "GraphQL CMS"
        }
      }
    ]
  }
}
```


### Embed assets

You can also embed [Assets](https://hygraph.com/docs/api-reference/assets/embedded-types) and other models inside Rich Text as **block, inline or link embeds**.

![Rich Text Asset Embeds UI](https://hygraph.com/images/docs/api-reference/schema/rich-text-embeds.png)

**Note:**
You can find out how to enable Rich Text embeds in our [field configuration](https://hygraph.com/docs/api-reference/schema/field-configuration#rich-text-fields-only-embed-options) docs.

### Rich Text embeds & API types

With Rich Text Embeds enabled, your API will have some new types added. The name of your field will be now a type appended by `RichText`, and `RichTextEmbeddedTypes` inside your schema.

For example, if you had the model `Post` and field `content`, the types generates would be `PostContentRichText`, and `PostContentRichTextEmbeddedTypes` respectively.

The `PostContentRichText` type will look like the following:

```graphql
type RichText {
  json: RichTextAST!
  html: String!
  markdown: String!
  text: String!
  references: [PostContentRichTextEmbeddedTypes!]!
}
```

The `references` field will be a union relation to the types you embedded, for example `Asset`.

You should use the `references` field when querying `JSON` to get the `URL` (with any [transformations](https://hygraph.com/docs/api-reference/assets/transformations), `handle`, or any of the [Asset fields](https://hygraph.com/docs/api-reference/schema/system-fields#asset-fields).

  **Query**

```graphql
{
  posts {
    content {
      json
      html
      markdown
      text
      references {
        __typename
        ... on Asset {
          url
          handle
        }
      }
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "posts": [
      {
        "content": {
          "json": {
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "text": "Hygraph Rich Text Embeds"
                  }
                ]
              },
              {
                "type": "embed",
                "nodeId": "cko2lq2u0031r0844xnvurz05",
                "children": [
                  {
                    "text": ""
                  }
                ],
                "nodeType": "Asset"
              },
              {
                "type": "paragraph",
                "children": [
                  {
                    "text": ""
                  }
                ]
              }
            ]
          },
          "html": "<p>Hygraph Rich Text Embeds</p><div data-gcms-embed-type=\"Asset\" data-gcms-embed-id=\"cko2lq2u0031r0844xnvurz05\"></div><p></p>",
          "markdown": "Hygraph Rich Text Embeds\n\n\n",
          "text": "Hygraph Rich Text Embeds\\n\\n",
          "references": [
            {
              "__typename": "Asset",
              "url": "https://media.graphassets.com/xSIoGkATQybd8S2SgA5Q",
              "handle": "xSIoGkATQybd8S2SgA5Q"
            }
          ]
        }
      }
    ]
  }
}
```


The `HTML` response will return `gcms-embed-type` and `gcms-embed-id` data attributes for the embedded types. A block embed is returned as `div` and an inline embed as `span` with a `data-gcms-embed-inline` attribute. A link embed is returned as an `a`-tag with a `data-gcms-embed-id` and `data-gcms-embed-type` attribute.

  **Block**
    ```html
    <div
      data-gcms-embed-type="Asset"
      data-gcms-embed-id="cko2lq2u0031r0844xnvurz05"
    ></div>
    ```
  
  **Inline**
    ```html
    <span
      data-gcms-embed-type="Author"
      data-gcms-embed-id="ckwyytv5k003s0791zitq6alu"
      data-gcms-embed-inline
    ></span>
    ```
  
  **Link**
    ```html
    <a
      data-gcms-embed-id="cl0sa2kc50sb80axsu0kcaeaa"
      data-gcms-embed-type="Post"
    >
      link text
    </a>
    ```
  

Hygraph uses [Slate 0.5](https://docs.slatejs.org) for `RichTextAST`.

**Note:**
If you are programmatically creating content entries with Rich Text, you should use the [<code>@graphcms/html-to-slate-ast</code>](https://github.com/hygraph/rich-text/tree/main/packages/html-to-slate-ast) package.

## Mutations for Rich Text fields

When creating or updating entries, ensure your mutation payload matches the schema type shown in the API Playground. For localized models or fields, you must include a locale property. Incorrectly structured payloads are a common cause of <code>Invalid payload / could not transform RichText</code> errors.

**Note:**
Even if the field allows embeds, the structure remains the same. Always send an object containing a `children` array.

### Create rich text fields

Provide the AST object directly. Do not wrap it in a property such as `raw` or `json`.

  **Create rich text field**
    ```graphql
    mutation {
      createPost(
        data: {
          content: {
            children: [{type: "paragraph", children: [{text: "This is old."}]}]
          }
        }
      ) {
        id
        content {
          json
          html
        }
      }
    }
    ```
  
  **Result - Create rich text field**
    ```json
    {
      "data": {
        "createPost": {
          "id": "cmgqebp1hxdqm07w0fgaj7u7g",
          "content": {
            "json": {
              "children": [
                {
                  "type": "paragraph",
                  "children": [
                    {
                      "text": "This is old."
                    }
                  ]
                }
              ]
            },
            "html": "<p>This is old.</p>"
          }
        }
      }
    }
    ```
     

### Update rich text fields

Provide the AST object directly. Do not wrap it in a property such as `raw` or `json`.

  **Update rich text field**
    ```graphql
    mutation {
      updatePost(
        where: {id: "cmgqe9mbzxqx607uu4uzrde44"}
        data: {
          content: {
            children: [{ type: "paragraph", children: [{ text: "This is new." }] }]
          }
        }
      ) {
        id
        content {
          json
        }
      }
    }
    ```
  
  **Result - Update rich text field**
    ```json
    {
      "data": {
        "updatePost": {
          "id": "cmgqe9mbzxqx607uu4uzrde44",
          "content": {
            "json": {
              "children": [
                {
                  "type": "paragraph",
                  "children": [
                    {
                      "text": "This is new."
                    }
                  ]
                }
              ]
            }
          }
        }
      }
    }
    ```
     

### Create rich text fields with locale

Provide the AST object directly. Do not wrap it in a property such as `raw` or `json`.

  **Create rich text field with locale**
    ```graphql
    mutation {
      createPost(
        data: {
          localizations: {
            create: [
              {
                locale: de
                data: {
                  content: {
                    children: [
                      { type: "paragraph", children: [{ text: "Das ist alt." }] }
                    ]
                  }
                }
              }
            ]
          }
        }
      ) {
        id
        localizations(locales: [de]) {
          locale
          content {
            raw
          }
        }
      }
    }
    ```
  
  **Result - Create rich text field with locale**
    ```json
    {
      "data": {
        "createPost": {
          "id": "cmgqem7eoym1d07uu2ezhlj5t",
          "localizations": [
            {
              "locale": "de",
              "content": {
                "raw": {
                  "children": [
                    {
                      "type": "paragraph",
                      "children": [
                        {
                          "text": "Das ist alt."
                        }
                      ]
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    }
    ```
     

### Update rich text fields with locale

Provide the AST object directly. Do not wrap it in a property such as `raw` or `json`.

  **Update rich text field with locale**
    ```graphql
    mutation {
      updatePost(
        where: { id: "cmgqem7eoym1d07uu2ezhlj5t" }
        data: {
          localizations: {
            update: [
              {
                locale: de
                data: {
                  content: {
                    children: [
                      { type: "paragraph", children: [{ text: "Das ist neu." }] }
                    ]
                  }
                }
              }
            ]
          }
        }
      ) {
        id
        localizations(locales: [de]) {
          locale
          content {
            raw
          }
        }
      }
    }
    ```
  
  **Result - Update rich text field with locale**
    ```json
    {
      "data": {
        "updatePost": {
          "id": "cmgqem7eoym1d07uu2ezhlj5t",
          "localizations": [
            {
              "locale": "de",
              "content": {
                "raw": {
                  "children": [
                    {
                      "type": "paragraph",
                      "children": [
                        {
                          "text": "Das ist neu."
                        }
                      ]
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    }
    ```
     

## Use JSON representation of RTE for customization

You can work with the **Rich Text field** to take the data that the editors put in Hygraph, and manipulate it for display in the front end.

The following example shows data available on a blog post, with the Rich Text content in `HTML` and `markdown`:

 **Query**

```graphql
query MyQuery($id: ID, $slug: String) {
  values: post(where: { id: $id, slug: $slug }) {
    title
    slug
    id
    content {
      html
      markdown
    }
  }
}
```

 
 **Variables**

```json
{
  "id": "clbdn2fjithnl0amxwm8wtell"
}
```

 
 **Result**

```json
{
  "data": {
    "values": {
      "title": "Test",
      "slug": "test",
      "id": "clbdn2fjithnl0amxwm8wtell",
      "content": {
        "html": "<h1>Lorem Ipsum</h1><h4>&quot;Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...&quot;</h4><h5>&quot;There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain...&quot;</h5><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc interdum mauris libero. Aliquam in iaculis nibh. Duis sagittis, orci sit amet hendrerit pellentesque, velit felis lobortis purus, vitae finibus libero risus quis ipsum. Curabitur in malesuada odio. Quisque quis metus quis augue lacinia euismod vel quis orci. Fusce condimentum ultricies mollis. Morbi et ultricies augue. Integer massa libero, elementum nec ante at, blandit auctor risus. Nulla et dignissim turpis. Vivamus pharetra turpis eu sem maximus egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In a pulvinar dui. Etiam varius justo quis purus hendrerit, sed tristique ex pulvinar. Integer vel lobortis magna. Suspendisse potenti. Morbi faucibus sem eget enim posuere, vitae vestibulum felis sodales.</p><p>Fusce suscipit sed dolor eu convallis. Nulla et velit ut lacus ullamcorper varius vel sit amet justo. Nullam condimentum dolor a ligula placerat, vitae sagittis elit efficitur. Donec ac elit fermentum, vehicula dui eget, condimentum ante. Aenean in nisl faucibus neque feugiat suscipit. Aenean sit amet facilisis ante, sed semper ipsum. Proin id nulla odio. Maecenas condimentum placerat laoreet. Aliquam at sodales tortor. Nam tortor dui, maximus nec imperdiet ut, bibendum vel felis. Duis hendrerit vulputate finibus. In hac habitasse platea dictumst. Pellentesque sed posuere ex. Nullam metus erat, finibus nec ultricies nec, egestas sed ipsum.</p><p>Nulla varius mauris sed justo egestas, eu dictum urna dictum. Aenean varius dui convallis vehicula suscipit. In hac habitasse platea dictumst. Nullam euismod vel dui ac blandit. Suspendisse potenti. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed vitae lorem lacinia, mollis risus volutpat, malesuada risus. Maecenas lacinia sem in odio vestibulum, at dictum metus finibus. Morbi turpis tellus, egestas eu molestie nec, sagittis ac enim. Morbi facilisis finibus odio, eget consequat ipsum porttitor non. Nunc risus ipsum, congue blandit lacus eu, lacinia hendrerit nulla. Donec congue suscipit velit, a aliquet dolor venenatis nec. In eget ullamcorper massa. Ut efficitur felis vel rhoncus sollicitudin.</p>",
        "markdown": "# Lorem Ipsum\n\n#### \"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...\"\n\n##### \"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain...\"\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc interdum mauris libero. Aliquam in iaculis nibh. Duis sagittis, orci sit amet hendrerit pellentesque, velit felis lobortis purus, vitae finibus libero risus quis ipsum. Curabitur in malesuada odio. Quisque quis metus quis augue lacinia euismod vel quis orci. Fusce condimentum ultricies mollis. Morbi et ultricies augue. Integer massa libero, elementum nec ante at, blandit auctor risus. Nulla et dignissim turpis. Vivamus pharetra turpis eu sem maximus egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In a pulvinar dui. Etiam varius justo quis purus hendrerit, sed tristique ex pulvinar. Integer vel lobortis magna. Suspendisse potenti. Morbi faucibus sem eget enim posuere, vitae vestibulum felis sodales.\n\nFusce suscipit sed dolor eu convallis. Nulla et velit ut lacus ullamcorper varius vel sit amet justo. Nullam condimentum dolor a ligula placerat, vitae sagittis elit efficitur. Donec ac elit fermentum, vehicula dui eget, condimentum ante. Aenean in nisl faucibus neque feugiat suscipit. Aenean sit amet facilisis ante, sed semper ipsum. Proin id nulla odio. Maecenas condimentum placerat laoreet. Aliquam at sodales tortor. Nam tortor dui, maximus nec imperdiet ut, bibendum vel felis. Duis hendrerit vulputate finibus. In hac habitasse platea dictumst. Pellentesque sed posuere ex. Nullam metus erat, finibus nec ultricies nec, egestas sed ipsum.\n\nNulla varius mauris sed justo egestas, eu dictum urna dictum. Aenean varius dui convallis vehicula suscipit. In hac habitasse platea dictumst. Nullam euismod vel dui ac blandit. Suspendisse potenti. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed vitae lorem lacinia, mollis risus volutpat, malesuada risus. Maecenas lacinia sem in odio vestibulum, at dictum metus finibus. Morbi turpis tellus, egestas eu molestie nec, sagittis ac enim. Morbi facilisis finibus odio, eget consequat ipsum porttitor non. Nunc risus ipsum, congue blandit lacus eu, lacinia hendrerit nulla. Donec congue suscipit velit, a aliquet dolor venenatis nec. In eget ullamcorper massa. Ut efficitur felis vel rhoncus sollicitudin.\n"
      }
    }
  }
}
```


Hygraph automatically serializes the content into `HTML` and/or `markdown` that the front end can simply display. **This does not allow customization**.

Instead of these two things, you can get the JSON representation, which will display as `JSON AST` in a tree with nested levels.

 **Query**

```graphql
query MyQuery($id: ID, $slug: String) {
  values: post(where: { id: $id, slug: $slug }) {
    title
    slug
    id
    content {
      json
    }
  }
}
```

 
 **Variables**

```json
{
  "id": "clbdn2fjithnl0amxwm8wtell"
}
```

 
 **Result**

```json
{
  "data": {
    "values": {
      "title": "Test",
      "slug": "test",
      "id": "clbdn2fjithnl0amxwm8wtell",
      "content": {
        "json": {
          "children": [
            {
              "type": "heading-one",
              "children": [
                {
                  "text": "Lorem Ipsum"
                }
              ]
            },
            {
              "type": "heading-four",
              "children": [
                {
                  "text": "\"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...\""
                }
              ]
            },
            {
              "type": "heading-five",
              "children": [
                {
                  "text": "\"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain...\""
                }
              ]
            },
            {
              "type": "paragraph",
              "children": [
                {
                  "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc interdum mauris libero. Aliquam in iaculis nibh. Duis sagittis, orci sit amet hendrerit pellentesque, velit felis lobortis purus, vitae finibus libero risus quis ipsum. Curabitur in malesuada odio. Quisque quis metus quis augue lacinia euismod vel quis orci. Fusce condimentum ultricies mollis. Morbi et ultricies augue. Integer massa libero, elementum nec ante at, blandit auctor risus. Nulla et dignissim turpis. Vivamus pharetra turpis eu sem maximus egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In a pulvinar dui. Etiam varius justo quis purus hendrerit, sed tristique ex pulvinar. Integer vel lobortis magna. Suspendisse potenti. Morbi faucibus sem eget enim posuere, vitae vestibulum felis sodales."
                }
              ]
            },
            {
              "type": "paragraph",
              "children": [
                {
                  "text": "Fusce suscipit sed dolor eu convallis. Nulla et velit ut lacus ullamcorper varius vel sit amet justo. Nullam condimentum dolor a ligula placerat, vitae sagittis elit efficitur. Donec ac elit fermentum, vehicula dui eget, condimentum ante. Aenean in nisl faucibus neque feugiat suscipit. Aenean sit amet facilisis ante, sed semper ipsum. Proin id nulla odio. Maecenas condimentum placerat laoreet. Aliquam at sodales tortor. Nam tortor dui, maximus nec imperdiet ut, bibendum vel felis. Duis hendrerit vulputate finibus. In hac habitasse platea dictumst. Pellentesque sed posuere ex. Nullam metus erat, finibus nec ultricies nec, egestas sed ipsum."
                }
              ]
            },
            {
              "type": "paragraph",
              "children": [
                {
                  "text": "Nulla varius mauris sed justo egestas, eu dictum urna dictum. Aenean varius dui convallis vehicula suscipit. In hac habitasse platea dictumst. Nullam euismod vel dui ac blandit. Suspendisse potenti. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed vitae lorem lacinia, mollis risus volutpat, malesuada risus. Maecenas lacinia sem in odio vestibulum, at dictum metus finibus. Morbi turpis tellus, egestas eu molestie nec, sagittis ac enim. Morbi facilisis finibus odio, eget consequat ipsum porttitor non. Nunc risus ipsum, congue blandit lacus eu, lacinia hendrerit nulla. Donec congue suscipit velit, a aliquet dolor venenatis nec. In eget ullamcorper massa. Ut efficitur felis vel rhoncus sollicitudin."
                }
              ]
            }
          ]
        }
      }
    }
  }
}
```


**Warning:**
Remember that `Richtext` will only include the field `JSON` if Rich Text embeds are enabled for the model you're using.

As you can see in the `results` tab of the above query, this breaks up the initial data into a `JSON` representation that a renderer can understand.

This allows you to take that data and manipulate it in order to override any default renderer or add renderers for custom elements, creating a custom display logic for your front end.

You will do this by creating an `HTML` element containing the manipulated data, which will then be rendered via the `astToHtmlString` method that's available on our [Rich Text HTML renderer](https://github.com/hygraph/rich-text/tree/main/packages/html-renderer). We also have a [React version](https://hygraph.com/blog/hygraph-react-rich-text-renderer) of this.

**Note:**
Click [here](https://hygraph.com/blog/styling-rich-text-tailwindcss) to access a detailed example on <b>how to style Rich Text using TailwindCSS</b>.

By styling your Rich Text fields, you can either customize how your Rich Text will display throughout your website, or even have multiple types of Rich Text fields that do different things.

## Resources

- [Hygraph's Rich Text editor:](https://hygraph.com/docs/developer-guides/content/rich-text-editor) Hygraph's UI Rich Text field feature walkthrough.
- [Styling Rich Text with TailwindCSS:](https://hygraph.com/blog/styling-rich-text-tailwindcss) Detailed tutorial on how to use the `JSON` representation from the RTE to create custom elements for each text-based element of Rich Text.
- [Introducing the Hygraph React Rich Text Renderer:](https://hygraph.com/blog/hygraph-react-rich-text-renderer) Blog post on how to render Hygraph documents using Rich Text in your application easily using our available packages.
- [Rich Text editor UI guide:](https://hygraph.com/docs/developer-guides/content/rich-text-editor) Guide on how to use Hygraph's Rich Text editor in the content editor of your project.
