# Pele renders Mermaid 12.1.0 diagrams to SVG synchronously, with its own layout and CSS-variable theming

> Pele turns Mermaid text into themeable SVG with no runtime dependencies. This article covers the render and mount calls, the split entry points for bundle size, the CSS variables and what Mermaid compatibility does and does not mean.

**obsidianmd/pele** — Renders Mermaid diagrams faster than you'd run from a volcano! 🌋 

- Repository: https://github.com/obsidianmd/pele
- Website: https://pele.run
- Stars: 4,368 · Forks: 132
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-30 · Language: en
- Canonical page: https://hysenlabs.com/projects/obsidianmd-pele

## render() is synchronous and hands back an svg string

Pele renders Mermaid diagrams to SVG. It is small, synchronous, has no runtime dependencies, and uses CSS variables for colors and fonts. Install it with:

```sh
npm install pele
```

The core call takes Mermaid text and returns an object with an svg property:

```ts
import { render } from 'pele';

const { svg } = render(`flowchart LR
  A[Mermaid text] --> B[SVG]`);

document.querySelector('#diagram').innerHTML = svg;
```

Because render is synchronous, there is no promise to await and no async setup step. You put the string into the page yourself, here through innerHTML. That is also where the security section matters, since you are inserting generated markup into a document. The front page points to pele.run/api for options and error handling, and does not list the error cases itself.

## mount() reads fonts from CSS and follows the container width in a browser

In a browser, mount() renders into an element, reads fonts from CSS, and adapts the layout to the container width:

```ts
import { mount } from 'pele';

mount(document.querySelector('#diagram'), text);
```

The difference from render is who owns the DOM write. With render you get a string and decide what to do. With mount, Pele writes into the element and measures it, which is why it is a browser-only call.

A CDN route exists for pages without a bundler. The script tag loads pele.global.js from jsdelivr at major version 1, and a loop mounts every pre.mermaid element:

```html
<script src="https://cdn.jsdelivr.net/npm/pele@1/dist/pele.global.js"></script>
<script>
  for (const el of document.querySelectorAll('pre.mermaid')) pele.mount(el, el.textContent);
</script>
```

The @1 range means the CDN serves whatever 1.x is current, so a page can change behaviour without any edit on your side.

## The main entry point includes every diagram type, so a small bundle needs pele/core

The default import from pele carries every diagram type. A project that draws only flowcharts pays for the rest unless it changes entry point. Two routes cut the initial bundle.

The first registers individual types through pele/core:

```ts
import { register, render } from 'pele/core';
import flowchart from 'pele/diagrams/flowchart';

register(flowchart);
```

The second loads types on demand through pele/lazy, with an async call:

```ts
import { renderAsync } from 'pele/lazy';

const { svg } = await renderAsync(text);
```

There is a trade here. renderAsync gives up the synchronous behaviour that is Pele's selling point, and pele/core means a diagram type you forgot to register is a type you cannot draw. The package.json exports map shows the entry points: the root, ./core, ./lazy, ./diagrams/*, ./global and ./package.json. The front page does not list the names of the individual diagram modules, so check pele.run for them.

## Theming is ten CSS variables plus eight series colors, applied without re-rendering

Colors and fonts come from CSS variables set on the diagram or on a parent element:

```css
.pele {
  --pele-bg: #fffcf0;
  --pele-fg: #100f0f;
  --pele-muted: #6f6e69;
  --pele-line: #100f0f;
  --pele-surface: #f2f0e5;
  --pele-surface-alt: #e6e4d9;
  --pele-border: #cecdc3;
  --pele-accent: #205ea6;
  --pele-font: sans-serif;
  --pele-radius: 4px;
}
```

Charts use --pele-series-1 through --pele-series-8. Colors adapt to theme changes without being re-rendered, so switching a page between light and dark does not trigger a new render call. The practical gain is that a theme switch is a CSS change.

The listed values form a light palette. Dark mode values are not given on the front page, so you write them yourself. Pele's Theming page at pele.run/theming covers all variables, fonts and class names, and this article cannot vouch for the ones not shown above.

## Mermaid 12.1.0 syntax is the target, but the layout and visual style are Pele's own

Pele supports every diagram type built into Mermaid 12.1.0, and targets that syntax with its own layout and visual style. Read the second half carefully. A diagram that parses in both tools will not necessarily look the same, and nothing on the front page promises matching node positions or spacing.

Compatibility is checked at the parser level. The parsers are tested against Mermaid's parser specs and with differential fuzzing. The specs under tests/compat and the grammar files beside them come from Mermaid, which is also MIT licensed.

The version is pinned in the wording. Syntax added to Mermaid after 12.1.0 is outside the claim, and the front page does not say how Pele handles it. If your diagrams come from authors using a newer Mermaid, test them first.

Security is a separate promise: Pele escapes diagram text, filters links and styles, and limits source and output size. Handling untrusted diagrams, displaying errors and supplying icons are covered at pele.run/security, not in the README.

## bench:mermaid needs Node 22, downloads Mermaid from unpkg and looks for Chrome in /Applications

The development commands are:

```sh
npm install
npm test
npm run build
npm run bench
```

npm run bench:mermaid is the comparison script. It times Pele and Mermaid.js in headless Chrome on the same diagrams and compares bundle sizes. It needs Node 22 or later, fetches Mermaid 12.1.0 from unpkg, and takes -- --mermaid <version> for another release. The CHROME environment variable must be set if Chrome is not in /Applications, which is a macOS path, so Linux and Windows contributors set it every time.

The README publishes no benchmark numbers. The tagline promises speed, and the only way to see a figure is to run the script yourself.

The documentation site and playground live in website/ and use Node 24 and pnpm 12. With nvm, the steps are cd website, nvm use, pnpm install and pnpm dev. After that, npm run test:website from the repository root checks the playground. Parser testing is described in CONTRIBUTING.md.

## Three releases on 26 October 2026 and a license field GitHub could not read

package.json is at version 1.12.0, and the recent releases are 1.10.1, 1.11.0 and 1.12.0, all published on 26 October 2026. The last push to main was on 24 October 2026, and the repository is not archived. Three releases in one day means the version number moves fast. Pin an exact version in production.

The author field reads kepano. The license appears as NOASSERTION in the repository metadata, while both the README and package.json say MIT. The LICENSE file is in the repository, so read it to confirm the terms before redistributing.

Published files are limited to dist, LICENSE and README.md, so tests, scripts and website are not in the npm package. The prepublishOnly script runs typecheck, tests and build in that order. SECURITY.md and AGENTS.md sit beside CONTRIBUTING.md in the root.

## Conclusion

Pele suits a front end that wants Mermaid diagrams as SVG without Mermaid.js, and that can live with a layout and visual style that are Pele's own. It does not suit a team that needs output pixel-identical to Mermaid. Before switching, render your real diagrams in the playground at pele.run and check the output against what Mermaid.js gives you.

## FAQ

### How do I install Pele?

Run npm install pele. Pages without a bundler can load pele.global.js from the jsdelivr CDN at https://cdn.jsdelivr.net/npm/pele@1/dist/pele.global.js.

### Which Mermaid version does Pele support?

Pele supports every diagram type built into Mermaid 12.1.0 and targets that syntax with its own layout and visual style.

### Does Pele have runtime dependencies?

No. Pele is small, synchronous and has no runtime dependencies. It uses CSS variables for colors and fonts.

## Sources

- [Issues](https://github.com/obsidianmd/pele/issues)
- [obsidianmd/pele on GitHub](https://github.com/obsidianmd/pele)
- [Project website](https://pele.run)
- [README](https://github.com/obsidianmd/pele/blob/main/README.md)
- [Releases](https://github.com/obsidianmd/pele/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/obsidianmd-pele
