Using Pele to render
Mermaid diagrams
Our first Pele sample was a three-node Mermaid flowchart: Draft → Review → Publish. It rendered in Node.js without opening a browser. When we added a pink-and-green Mermaid theme, the SVG stayed gray.
Pele uses its own layout and CSS variables for colors. If you are moving diagrams into a documentation site, check those details before replacing the renderer everywhere.
Get an SVG on disk first
Pele is an MIT-licensed JavaScript library developed for Obsidian. It accepts Mermaid text and returns SVG. The official playground is enough for a quick look; for a documentation build, start with a small local example you can inspect.
We used Pele 1.6.0. It requires Node.js 20 or newer and declares no runtime dependencies. Install that version in a project directory:
npm install --save-exact pele@1.6.0
Save this as render-diagram.mjs:
import { writeFile } from "node:fs/promises";
import { render } from "pele";
const source = `flowchart LR
A[Draft] --> B[Review] --> C[Publish]`;
const { svg, type, width, height } = render(source);
await writeFile("diagram.svg", svg, "utf8");
console.log(type, width, height);
Run node render-diagram.mjs. It writes diagram.svg; our run printed flowchart 360 64. This is the SVG it produced:
The same source measured 364 × 64 in Chrome. Node used Pele’s built-in text-width estimate, while the browser measured the text with canvas. That small difference is a reason to check the final page with the font you intend to use.
The Mermaid theme did not carry over
We put this directive above the flowchart, expecting pink nodes and green text:
%%{init: {"theme":"base","themeVariables":{"primaryColor":"#ff00f1","primaryTextColor":"#00ff01"}}}%%
The output was byte-for-byte identical to the SVG without that directive. Pele does not apply Mermaid’s theme or themeVariables colors. The fix is to set Pele’s CSS variables on the inline SVG or its container:
.diagram {
--pele-bg: #151d2b;
--pele-fg: #edf4ff;
--pele-line: #cbd8ee;
--pele-surface: #26374d;
--pele-border: #91abd2;
background: var(--pele-bg);
padding: 20px;
}
Changing these colors in our browser experiment did not require another render. An explicit diagram style behaved differently: style A fill:#ff00f1,color:#00ff01 retained its fixed colors. If a node refuses to follow your dark theme, check for a style in the source that overrides it.
Fonts need more care than colors because they affect layout. The theming documentation explains how to refresh a mounted diagram after a font change or pass the font to render().
Open the exported file on its own
Our dark preview looked right inside the page. Loaded through an img, the raw SVG reverted to the default light colors: the file no longer had the page’s CSS variables to inherit.
Embedding the five color variables on the SVG root, then adding a background rectangle, kept the dark colors in the standalone image. Both files decoded in Chrome. If you need the downloaded image to look like the preview, the colors and background need to travel with it.
Check the saved file before converting it to PNG or adding it to a document. Charts can use additional series colors, and custom fonts or images need separate checks. Our export experiment covered this small flowchart. The existing SVG to PNG converter is an option once your standalone SVG looks right.
A few other things to check before switching
For one docs maintainer, the appeal was simpler integration. On Hacker News, 9dev reported migrating their project’s diagrams to Pele, replacing a mix of Mermaid, pan/zoom and dark-theme workarounds. They linked their documentation in the comment. Another reader, nkmnz, tried a couple of diagrams and “couldn’t see any major differences in the layout.” These are individual reports, not a comparison across many diagrams.
The layout caveat has a concrete example. In issue #3, Spenhouet supplied a shared-store flowchart and SVG comparisons reporting excess crossings between subgraphs in Pele 1.6.0, along with a proposed fix. We have not rerun that benchmark. It makes a complex fan-in diagram a more useful migration check than our three-node flowchart.
A narrow layout can change the diagram’s direction. Our flowchart LR became vertical with maxWidth: 320, going from 360 × 64 to 105 × 256 in Node.js. Set autoDirection: false if the horizontal arrangement matters:
const result = render(source, {
maxWidth: 320,
autoDirection: false,
});
That version stayed horizontal but was still 336 pixels wide. You may need scaling or scrolling. For a live page, mount() handles container resizes; with render(), your application handles them.
| In the source | What happened in our test |
|---|---|
| click with an HTTPS URL | The result’s links array retained the URL. |
| click with a JavaScript callback | The diagram rendered, but the callback was not retained. |
| A colored HTML span | The text remained; the span and its color style did not. Bold text and a line break became SVG tspan elements. |
| ZenUML | Rejected with unsupported-diagram. |
Also catch errors from render(). Our unclosed flowchart label passed supports() and then failed to render. The first function checks whether a diagram type is available, not whether the entire source is valid.
For an existing docs site, we would try the diagrams with the most styling and interaction first. Those are the examples most likely to expose a migration problem. Keep the original sources and compare their actual outputs against the compatibility notes. When displaying an error, use textContent; the message can quote source text. Custom icon markup and navigation also need attention, as explained in the security reference.
How other projects are using Pele
Replacing the renderer is only part of a migration. These projects show the work around it: streamed input, theme changes and exported documents. We checked the linked PRs, source files and project documentation on October 18, 2026. These are source reviews; our own execution results are in the test notes below.
Outline: diagrams in documents
The merged PR moves theme colors into CSS variables, keeps rendered SVG in a session cache and gives printing a light palette. Switch themes, revisit a document and open print preview. Those are separate paths through a docs app.
Lobe UI: streaming Mermaid
The merged PR keeps the last valid SVG while incomplete streamed text fails to parse; reports the real error when streaming ends. A half-written diagram should not replace a readable preview with an error on every chunk.
BookStack community module: document exports
The community module renders on the server, resolves SVG color variables for export and rasterizes the result to PNG for PDF. Test the exported document. A browser preview alone will not show what a server-side PDF renderer receives.
Scotty: diagrams in chat replies
The merged PR keeps the diagram in an img, writes its palette into the SVG and passes the figure width to the renderer. An SVG image cannot inherit the host page’s variables. Narrow screens also need a layout decision.
sphinx-pele: Python documentation
This development extension accepts reStructuredText directives, MyST Mermaid fences and external .mmd files. The reviewed code leaves source text in non-HTML builds. Confirm the output format you need; an HTML extension does not automatically provide rendered PDF diagrams.
For an existing app, we would follow the case closest to its output. The BookStack module is relevant to PDF delivery; Lobe UI is relevant to an answer that arrives in chunks. Their performance figures and release availability need separate verification—we have not used these projects as a speed benchmark.
Test notes
We ran 15 inputs with Pele 1.6.0 on Node.js 22.23.1: 13 produced SVG, including our flowchart, sequence, ER and Gantt samples; ZenUML and a malformed flowchart were rejected. Producing SVG did not mean every feature survived, as the callback example shows. The theme and standalone-image checks ran in Chrome.
Tested . These were small functional examples, not a complete Mermaid compatibility suite or a speed comparison. Source code and license: obsidianmd/pele.