Updated on 2025-10-25T16:50:24.457Z
Written on 2025-02-21T08:41:10.072Z

Everybody loves Mermaid.js. If you don 't know what it is then go check it out at: https://mermaid.js.org/ . It 's the easiest way (next to copy-paste an image file) to put diagrams of all kinds on your HTML page with the simplest syntax on this planet.
Below showcases what each type of diagram looks like:
Loading diagram...
Loading diagram...
Loading diagram...
Enough with the showcases, let 's see how it 's done!
First, create a new Payload project with npx create-payload-app or integrate Payload CMS into your existing Next.js application (check out details here ). Once your Payload project is ready, install the Mermaid.js library with good old npm i mermaid . I won 't go into details on how to create collections and add an editor. You can check them all out at Payload 's official documentation .
To render Mermaid diagrams, you’ll need a dedicated client-side component. This component will parse Mermaid syntax and initialize the diagrams. Since Mermaid requires access to the DOM, this component must run only on the client side.
Mermaid will not re-render if the syntax has changed after the component is loaded. I 've been struggling for real-time render for a while but thanks to this article , I finally was able to make it work.
NOTE : if you don 't want the preview to consume too much resource on rendering, you can just add a refresh button and use onClick to remove the data-processed attribute and run mermaid.contentLoaded() instead.
This component will serve two purposes:
Now you have got the diagram renderer but there 's no way to input the data into it yet. Let 's create an input component so that you can create/edit it in Lexical
Payload’s Lexical editor supports custom blocks, allowing you to add a dedicated “Mermaid Diagram” block to your rich text fields. Configure this block to store raw Mermaid syntax and reference your client component for previewing. Let 's create a configuration that imports the input component that we just created so that you can later load it as a custom block for Lexical.
Then on the collection file, import the block above and put it in the blocks array under BlocksFeature .
When rendering whatever mutates on the client side in a Next.js, you’ll likely encounter the hydration error. This will happen to because Mermaid will only render the diagram after the component is loaded to the browser. To fix this you can either try any of these:
suppressHydrationWarning={true} to the parent element that will render the diagram. In this case it should be the <div > element with mermaid class in mermaid-renderer.tsx orFor 2, you can just create another .tsx file with the sample code below. One thing to note when creating a dynamic component is that the path here must be absolute, and the target file to import the component must export it as default (see further ).
This ensures the diagram is generated after the page loads, eliminating conflicts between serverrendered HTML and client-side DOM manipulation.
In your frontend, configure the RichText element to recognize the custom Mermaid block. Create Payload’s jsxConverters property to link the block to your dynamic client component. Then pass the jsxConverters to the RichText component on your page. This tells frontend to replace the Mermaid block with your dynamically loaded component.
You’ve now empowered your Payload CMS to handle Mermaid.js diagrams end-to-end. Content editors can create and preview visuals effortlessly, while your website delivers interactive, client-rendered diagrams without hydration issues.
This setup isn’t just for blogs—use it for documentation, project roadmaps, or data dashboards. Mermaid’s flexibility combined with Payload’s headless architecture opens endless possibilities for dynamic content.
TIP : Explore Mermaid’s theming options to match your site’s design, or add interactivity with click events. The sky’s the limit!
Now go forth and diagram all the things. 🌊