payload-plugin-mermaid
v1.0.2
Published
A Mermaid diagram block for Payload CMS: server-rendered SVG via zombie-mermaid, a live admin preview, and zero client-side rendering JS shipped to the frontend.
Downloads
590
Maintainers
Readme
payload-plugin-mermaid
A Mermaid diagram block for Payload CMS: a Lexical block that stores raw Mermaid source, a live debounced preview in the admin editor, an "Open in Mermaid Live Editor" button, and a server-rendered SVG on the frontend — no client-side Mermaid rendering JS ships to your visitors.
Diagrams are laid out with zombie-mermaid, a pure-JS renderer with no DOM dependency, so rendering happens at build/request time on the server, the same way you'd render a syntax-highlighted code block.
Supported diagram types: flowchart, sequence, class, state, ER, and xychart (zombie-mermaid lays these out with dagre; gantt, pie, journey, gitgraph, and mindmap diagrams aren't supported and fall back to showing the raw source).
Install
pnpm add payload-plugin-mermaidPeer dependencies: payload (^3.0.0), react, react-dom. @payloadcms/ui
and zombie-mermaid are regular dependencies, matching Payload's own
plugin development conventions —
no exact-version pinning, no dependency-injection layer. See
Why not pin payload, or inject the hooks?
below for the reasoning.
Usage
1. Register the block
Add it to a richText field's BlocksFeature:
import { lexicalEditor, BlocksFeature } from '@payloadcms/richtext-lexical'
import { MermaidBlock } from 'payload-plugin-mermaid'
export const Posts: CollectionConfig = {
slug: 'posts',
fields: [
{
name: 'content',
type: 'richText',
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
BlocksFeature({ blocks: [MermaidBlock] }),
],
}),
},
],
}Run payload generate:importmap after adding the block — Payload's importmap
generator scans block field configs (including this one's admin.components
entries) automatically, so no manual admin-component registration is needed.
2. Render it on the frontend
Wire the block into your richText field's JSX converters:
import { Mermaid } from 'payload-plugin-mermaid'
// Generated by your own project's `payload generate:types` — not exported by
// this package. Aliased here only because it happens to share a name with
// the block config value above; no collision if you import just one of them.
import type { MermaidBlock as MermaidBlockFields } from '../payload-types.js'
import type { SerializedBlockNode } from '@payloadcms/richtext-lexical'
import type { JSXConverter } from '@payloadcms/richtext-lexical/react'
const mermaidConverter: JSXConverter<
SerializedBlockNode<MermaidBlockFields>
> = ({ node }) => (
<Mermaid diagram={node.fields.diagram} caption={node.fields.caption} />
)(Payload generates that type from the block's interfaceName:
'MermaidBlock' — via payload generate:types in your own project, once
the block is registered in your config.)
3. Import the CSS
Two plain (non-CSS-Modules) stylesheets, so they work regardless of your
bundler's CSS Modules support for packages under node_modules:
// Frontend — wherever your app loads global CSS (e.g. a root layout):
import 'payload-plugin-mermaid/mermaid.css'// Admin — a client component you register somewhere Payload always loads,
// e.g. via `admin.components.providers` in your Payload config:
import 'payload-plugin-mermaid/mermaid-preview.css'Both ship with sensibly prefixed class names
(.payload-plugin-mermaid-*) — override them from your own stylesheet if
your site's diagram styling needs to differ.
Why not pin payload, or inject the hooks?
Payload's own first-party packages (@payloadcms/richtext-lexical,
@payloadcms/storage-vercel-blob, etc.) peer-depend on payload at an exact
version — but those ship on the same monorepo release train as payload
itself. That's not the convention Payload documents or exemplifies for
independent third-party plugins: their own official plugin template
declares payload as a peer range and @payloadcms/ui as a regular
range dependency, and imports useField/useFormFields directly rather
than receiving them via dependency injection. This package follows that
convention rather than inventing a bespoke one.
License
MIT
