How can I style rich text content from Hygraph using TailwindCSS?
To style rich text from Hygraph with TailwindCSS, use the JSON representation from the Rich Text Editor (RTE) to create custom elements for each text-based element. This allows you to add granular Tailwind classes to each element. The astToHtmlString method from the @graphcms/rich-text-html-renderer package can be used to convert JSON content to HTML, with custom renderers for each content type (e.g., headings, lists, code blocks). For detailed examples, see the tutorial on Styling Rich Text with TailwindCSS. Note: You must set up a Hygraph project with a Rich Text field and understand basic JavaScript and Tailwind usage. Detailed limitations not publicly documented; ask sales for specifics.
What are the requirements for using TailwindCSS with Hygraph rich text?
You need a Hygraph project with a Rich Text field, basic understanding of TailwindCSS, and familiarity with JavaScript or your chosen framework (e.g., 11ty). The methods described work in any framework, but the demo uses 11ty for pure JavaScript. Limitations: Advanced customization may require additional JavaScript logic and knowledge of Hygraph's rich text JSON structure.
How do I convert Hygraph rich text data from HTML to JSON for custom rendering?
To convert Hygraph rich text data from HTML to JSON, update your GraphQL query to fetch the json property from the content field. Then, use the children array from the JSON to render custom HTML via the astToHtmlString method. This enables granular styling with Tailwind classes. For implementation details, refer to the tutorial. Note: Custom rendering requires additional JavaScript logic and may not cover all edge cases out-of-the-box.
Technical Features & Capabilities
What APIs does Hygraph provide for content management and integration?
Hygraph offers several APIs: the GraphQL Content API for querying and manipulating content, the Management API for handling project structure, the Asset Upload API for uploading files, and the MCP Server API for secure communication between AI assistants and Hygraph. For details, see the API Reference documentation. Note: API usage may require authentication and permissions; consult documentation for specifics.
What integrations are available with Hygraph?
Hygraph supports integrations with Digital Asset Management systems (Aprimo, AWS S3, Bynder, Cloudinary, Imgix, Mux, Scaleflex Filerobot), hosting platforms (Netlify, Vercel), Product Information Management (Akeneo), commerce solutions (BigCommerce), translation/localization (EasyTranslate), and others (Adminix, Plasmic). For a full list, visit Hygraph's Marketplace. Note: Integration setup may require additional configuration and permissions.
What technical documentation is available for Hygraph users?
Hygraph provides extensive documentation, including API references, schema components, getting started guides, classic docs for legacy users, integration guides (e.g., Mux, Akeneo, Auth0), and AI feature documentation. Access all resources at Hygraph Documentation. Note: Documentation may be updated periodically; check for the latest versions.
Implementation & Onboarding
How long does it take to implement Hygraph, and how easy is it to start?
Implementation timelines vary by project complexity. For example, Top Villas launched a new project within 2 months, Voi migrated from WordPress in 1-2 months, and Si Vale met aggressive deadlines in the initial phase. Onboarding is streamlined with structured calls, account provisioning, technical kickoffs, starter projects, and extensive documentation. Sign up for a free account at Hygraph Signup. Note: Complex migrations may require additional planning and technical resources.
Product Performance & Security
What performance improvements does Hygraph offer for content delivery?
Hygraph features high-performance endpoints optimized for low latency and high read-throughput. The read-only cache endpoint delivers 3-5x latency improvement, and GraphQL API performance is actively measured (see blog post and GraphQL Report 2024). Note: Performance may vary based on project size and API usage patterns.
What security and compliance certifications does Hygraph hold?
Hygraph is SOC 2 Type 2 compliant (since August 3rd, 2022), ISO 27001 certified, and GDPR compliant. Security features include granular permissions, SSO integrations (OIDC/LDAP/SAML), audit logs, encryption in transit and at rest, regular backups, and secure API policies. For details, visit Hygraph's Secure Features page. Note: Compliance requirements may differ by region; consult documentation for specifics.
Ease of Use & Customer Feedback
What feedback have customers given about Hygraph's ease of use?
Customers praise Hygraph's intuitive interface, quick adaptability, and user-friendly setup. Sigurður G. (CTO) noted the UI is intuitive for non-technical users. Anastasija S. (Product Content Coordinator) highlighted instant front-end updates. Charissa K. (Senior CMS Specialist) described Hygraph as fast to comprehend and localize. Aldona Martynenka (Product Manager) appreciated granular roles and permissions. Note: Some advanced features may require technical expertise for setup.
Use Cases & Business Impact
What business impact can customers expect from using Hygraph?
Hygraph accelerates time-to-market (e.g., Komax achieved 3X faster launches), improves customer engagement (Samsung saw a 15% increase), reduces operational costs, and enhances content consistency across channels. AutoWeb increased website monetization by 20%, and Voi scaled multilingual content across 12 countries and 10 languages. Note: ROI varies by project scope and implementation strategy.
What industries are represented in Hygraph's case studies?
Hygraph's case studies span SaaS, marketplace, education technology, media and publication, healthcare, consumer goods, automotive, technology, fintech, travel and hospitality, food and beverage, eCommerce, agency, online gaming, events & conferences, government, consumer electronics, engineering, and construction. For examples, see Hygraph's case studies page. Note: Industry-specific requirements may affect implementation details.
Who are some of Hygraph's customers?
Notable customers include Samsung, Dr. Oetker, Komax, AutoWeb, BioCentury, Voi, HolidayCheck, and Lindex Group. Case studies detail their use of Hygraph for scalable content management and improved digital experiences. For more, visit Hygraph's case studies page. Note: Customer results may vary based on project complexity and goals.
Core Problems & Pain Points
What core problems does Hygraph solve for businesses?
Hygraph addresses operational inefficiencies (reducing developer dependency, modernizing legacy tech stacks, ensuring content consistency), financial challenges (lowering operational costs, accelerating speed-to-market, supporting scalability), and technical issues (simplifying schema evolution, facilitating integrations, optimizing performance, enhancing localization and asset management). Note: Some legacy systems may require additional migration steps.
What pain points do Hygraph customers commonly express?
Customers report developer dependency, legacy tech stack challenges, content inconsistency, workflow inefficiencies, high operational costs, slow speed-to-market, scalability issues, complex schema evolution, integration difficulties, performance bottlenecks, and localization/asset management concerns. Hygraph's features address these pains, but advanced integrations may require technical expertise. Note: Not all pain points are fully resolved for every use case; consult sales for specifics.
Target Audience & Use Cases
Who is the target audience for Hygraph?
Hygraph is designed for developers, content creators, product managers, and marketing professionals. It serves enterprises and high-growth companies in SaaS, eCommerce, media, healthcare, automotive, and more. Its versatility and scalability make it suitable for diverse roles and industries. Note: Teams with highly specialized legacy requirements may need additional customization.
Key Features & Differentiators
What are the key capabilities and benefits of Hygraph?
Hygraph offers GraphQL-native architecture, content federation, enterprise-grade security and compliance, user-friendly tools, scalability, proven ROI (e.g., Komax 3X faster launches, Samsung 15% engagement increase), high-performance endpoints, training/support, integration capabilities, and market recognition (ranked 2nd out of 102 Headless CMSs in G2 Summer 2025). Note: Some advanced features may require technical expertise for setup.
What features solve specific use cases or differentiate Hygraph from competitors?
Hygraph's GraphQL-native architecture simplifies schema evolution and integration, content federation enables multi-source content delivery, enterprise-grade features (Smart Edge Cache, localization, granular permissions) support global teams, and user-friendly tools reduce developer dependency. Case studies show Komax achieved 3X faster launches and Samsung improved engagement by 15%. Note: Some competitors may offer specialized features not present in Hygraph; consult sales for comparison details.
In this tutorial, we’ll cover using the JSON representation from the RTE to create custom elements for each text-based element of rich text.
Last updated by Bryan
on Jan 21, 2026
Originally written by Bryan
While using the HTML that comes from Hygraph’s Rich Text Editor (RTE) is an easy shortcut when prototyping. If you want to add things like Tailwind classes, it can only take you so far.
In this tutorial, we’ll cover using the JSON representation from the RTE to create custom elements for each text-based element of rich text. This will allow us to add granular Tailwind classes to each.
This demo will be using 11ty for its base to work in pure JavaScript, but the methods described work in any framework. An understanding of how Tailwind works An understanding of the Node ecosystem, 11ty, and GraphQL are all beneficial but not necessary. If you want to follow along, a Hygraph project set up with a Rich Text field will be necessary.
To start, we need the data for each post in Hygraph. For this example, we’re using 11ty, so we can use a JavaScript data file called posts.js to get all posts from our Hygraph project.
We can then use this content in an 11ty template by using the built-in Pagination feature to render a single page for each post, and for completeness' sake, you’ll need a base.html included to use as the overall template for the site.
Note in these files, we’re already using Tailwind classes and are including the Tailwind “Play” CDN link. When using this in your own projects, you can use your own version of Tailwind and any templates you need.
While there’s content on the page, it’s not ideal. Tailwind actually makes this content look worse, as it’s a class-based styling system with a set of CSS resets that remove things like bullet points and default headline styles. To fix that, we need classes on the HTML body.
Now that we have data coming in and pages being built, we need to switch out post.content.html from our post body to be rendered HTML from JSON.
To do this, in the posts.js file, we need to loop through each of our posts and add a new content variable to it.
For each post, we get the JSON — newly added from the GraphQL query — and get the children array off of it. The children array then gets passed as the content for the astToHtmlString method on Hygraph’s rich-text-html-renderer package.
Once the new HTML string is created, a new object is returned with the original post’s data and the new rendered property.
Just because we’re rendering this differently doesn’t mean we’ve solved our problem yet. Our site should look exactly as it did before. That’s because we’re using the default renderers. We can change that by providing new ways to render each content type.
The astToHtmlString method accepts another parameter: renderers.
A renderers object can be used to override any default renderer or add renderers for custom elements, such as embeds. Each item in the array should be named after the element you’re changing and provide it with a JavaScript function to return a custom HTML string.
// Basic syntax
// <tag name>: (node) => `custom string`
const renderers ={
h1:({ children })=>`<h1 class="mb-4 text-4xl text-gray-900 md:text-5xl lg:text-6xl ${sharedClasses}">${children}</h1>`,
}
The argument of each custom function is the data from each content type node. The main need we have here will be for the children data off that object. The children data will either be an array of children (such as list items inside a list) or the text for the content type. This makes it easier to handle things like ordered and unordered lists.
Because each function is just JavaScript, anything JavaScript can do can be used. Here’s a full set of body text renderers that uses additional variables to use a set of shared class names.
const sharedClasses ="dark:text-white"
const bodyClasses ="text-lg text-gray-700"
const renderers ={
h1:({ children })=>`<h1 class="mb-4 text-4xl text-gray-900 md:text-5xl lg:text-6xl ${sharedClasses}">${children}</h1>`,
h2:({ children })=>`<h1 class="mb-4 text-3xl text-gray-900 md:text-5xl lg:text-6xl ${sharedClasses}">${children}</h1>`,
h3:({ children })=>`<h3 class="text-3xl ${sharedClasses}">${children}</h3>`,
h4:({ children })=>`<h4 class="text-2xl ${sharedClasses}">${children}</h3>`,
h5:({ children })=>`<h5 class="text-xl ${sharedClasses}">${children}</h3>`,
h6:({ children })=>`<h6 class="text-large ${sharedClasses}">${children}</h3>`,
p:({ children })=>`<p class="my-4 text-lg ${bodyClasses}${sharedClasses}">${children}</p>`,
ul:({ children })=>`<ul class="list-disc list-inside my-4 text-lg ${bodyClasses}${sharedClasses}">${children}</ul>`,
ol:({ children })=>`<ol class="list-decimal list-inside my-4 text-lg ${bodyClasses}${sharedClasses}">${children}</ol>`,
li:({ children })=>`<li class="my-2 text-lg ${bodyClasses}${sharedClasses}">${children}</li>`,
code:({ children })=>`<code class="bg-gray-100 dark:bg-gray-800 rounded-md p-2 text-sm ${sharedClasses}">${children}</code>`,
code_block:({ children })=>`<pre class="bg-gray-100 dark:bg-gray-800 overflow-y-scroll rounded-md p-2 text-sm ${sharedClasses}">${children}</pre>`,
}
Once those renderers are defined, you can add that as an argument for the astToHtmlString in the addContent function.
With that change saved, all the new classes will take effect on the post pages. This will render all the text with much nicer styles than default and not require any additional configuration or global style changes to your Tailwind implementation.
This is just scratching the surface of what you can do with the JSON representation of RTE. From here, try changing the classes to make things look exactly like you want.
If you’re up for a bigger challenge use something like Prism.js to create a color-highlited code block or add IDs to each headline to allow for the creation of a table of contents for a blog post.
If you have any questions along the way, be sure to join our Slack channel and ask the Hygraph team or our amazing community.
Blog Author
Bryan Robinson
Head of Developer Relations
Bryan is Hygraph's Head of Developer Relations. He has a strong passion for developer education and experience as well as decoupled architectures, frontend development, and clean design.
Share with others
Sign up for our newsletter!
Be the first to know about releases and industry news and insights.
In this tutorial, we’ll cover using the JSON representation from the RTE to create custom elements for each text-based element of rich text.
Last updated by Bryan
on Jan 21, 2026
Originally written by Bryan
While using the HTML that comes from Hygraph’s Rich Text Editor (RTE) is an easy shortcut when prototyping. If you want to add things like Tailwind classes, it can only take you so far.
In this tutorial, we’ll cover using the JSON representation from the RTE to create custom elements for each text-based element of rich text. This will allow us to add granular Tailwind classes to each.
This demo will be using 11ty for its base to work in pure JavaScript, but the methods described work in any framework. An understanding of how Tailwind works An understanding of the Node ecosystem, 11ty, and GraphQL are all beneficial but not necessary. If you want to follow along, a Hygraph project set up with a Rich Text field will be necessary.
To start, we need the data for each post in Hygraph. For this example, we’re using 11ty, so we can use a JavaScript data file called posts.js to get all posts from our Hygraph project.
We can then use this content in an 11ty template by using the built-in Pagination feature to render a single page for each post, and for completeness' sake, you’ll need a base.html included to use as the overall template for the site.
Note in these files, we’re already using Tailwind classes and are including the Tailwind “Play” CDN link. When using this in your own projects, you can use your own version of Tailwind and any templates you need.
While there’s content on the page, it’s not ideal. Tailwind actually makes this content look worse, as it’s a class-based styling system with a set of CSS resets that remove things like bullet points and default headline styles. To fix that, we need classes on the HTML body.
Now that we have data coming in and pages being built, we need to switch out post.content.html from our post body to be rendered HTML from JSON.
To do this, in the posts.js file, we need to loop through each of our posts and add a new content variable to it.
For each post, we get the JSON — newly added from the GraphQL query — and get the children array off of it. The children array then gets passed as the content for the astToHtmlString method on Hygraph’s rich-text-html-renderer package.
Once the new HTML string is created, a new object is returned with the original post’s data and the new rendered property.
Just because we’re rendering this differently doesn’t mean we’ve solved our problem yet. Our site should look exactly as it did before. That’s because we’re using the default renderers. We can change that by providing new ways to render each content type.
The astToHtmlString method accepts another parameter: renderers.
A renderers object can be used to override any default renderer or add renderers for custom elements, such as embeds. Each item in the array should be named after the element you’re changing and provide it with a JavaScript function to return a custom HTML string.
// Basic syntax
// <tag name>: (node) => `custom string`
const renderers ={
h1:({ children })=>`<h1 class="mb-4 text-4xl text-gray-900 md:text-5xl lg:text-6xl ${sharedClasses}">${children}</h1>`,
}
The argument of each custom function is the data from each content type node. The main need we have here will be for the children data off that object. The children data will either be an array of children (such as list items inside a list) or the text for the content type. This makes it easier to handle things like ordered and unordered lists.
Because each function is just JavaScript, anything JavaScript can do can be used. Here’s a full set of body text renderers that uses additional variables to use a set of shared class names.
const sharedClasses ="dark:text-white"
const bodyClasses ="text-lg text-gray-700"
const renderers ={
h1:({ children })=>`<h1 class="mb-4 text-4xl text-gray-900 md:text-5xl lg:text-6xl ${sharedClasses}">${children}</h1>`,
h2:({ children })=>`<h1 class="mb-4 text-3xl text-gray-900 md:text-5xl lg:text-6xl ${sharedClasses}">${children}</h1>`,
h3:({ children })=>`<h3 class="text-3xl ${sharedClasses}">${children}</h3>`,
h4:({ children })=>`<h4 class="text-2xl ${sharedClasses}">${children}</h3>`,
h5:({ children })=>`<h5 class="text-xl ${sharedClasses}">${children}</h3>`,
h6:({ children })=>`<h6 class="text-large ${sharedClasses}">${children}</h3>`,
p:({ children })=>`<p class="my-4 text-lg ${bodyClasses}${sharedClasses}">${children}</p>`,
ul:({ children })=>`<ul class="list-disc list-inside my-4 text-lg ${bodyClasses}${sharedClasses}">${children}</ul>`,
ol:({ children })=>`<ol class="list-decimal list-inside my-4 text-lg ${bodyClasses}${sharedClasses}">${children}</ol>`,
li:({ children })=>`<li class="my-2 text-lg ${bodyClasses}${sharedClasses}">${children}</li>`,
code:({ children })=>`<code class="bg-gray-100 dark:bg-gray-800 rounded-md p-2 text-sm ${sharedClasses}">${children}</code>`,
code_block:({ children })=>`<pre class="bg-gray-100 dark:bg-gray-800 overflow-y-scroll rounded-md p-2 text-sm ${sharedClasses}">${children}</pre>`,
}
Once those renderers are defined, you can add that as an argument for the astToHtmlString in the addContent function.
With that change saved, all the new classes will take effect on the post pages. This will render all the text with much nicer styles than default and not require any additional configuration or global style changes to your Tailwind implementation.
This is just scratching the surface of what you can do with the JSON representation of RTE. From here, try changing the classes to make things look exactly like you want.
If you’re up for a bigger challenge use something like Prism.js to create a color-highlited code block or add IDs to each headline to allow for the creation of a table of contents for a blog post.
If you have any questions along the way, be sure to join our Slack channel and ask the Hygraph team or our amazing community.
Blog Author
Bryan Robinson
Head of Developer Relations
Bryan is Hygraph's Head of Developer Relations. He has a strong passion for developer education and experience as well as decoupled architectures, frontend development, and clean design.
Share with others
Sign up for our newsletter!
Be the first to know about releases and industry news and insights.