⏱️ Reading time: 13 min

A documentation site today loads 1.6 MB of JavaScript just to convert text into Mermaid diagrams in SVG. Pele achieves the same with 230 kB compressed and no declared dependencies.

📑 En este artículo
  1. TL;DR
  2. What Is Pele?
  3. Why Mermaid Diagrams to SVG Matter in Technical Documentation
  4. How Pele Works Under the Hood
  5. Practical Examples with Progressive Code
  6. Getting Started: Installation and First Render
  7. Real-World Use Cases
  8. Common Mistakes and Best Practices
  9. Comparison: Pele vs Mermaid.js
  10. Going Deeper: Theming, Accessibility, and Pele’s Limits
  11. Frequently Asked Questions
    1. Does Pele Completely Replace Mermaid.js?
    2. Do Mermaid Diagrams to SVG Generated by Pele Work Offline?
    3. Does Pele Support All of Mermaid.js’s Diagram Types?
    4. Can I Use Pele with React, Vue, or Svelte?
    5. What Happens If the SVG Generated by Pele Doesn’t Look Good on Small Screens?
    6. Does Pele Work in Node.js Without a Browser?
  12. References

The library accepts the same syntax you already use in Mermaid.js, but changes how colors are painted: instead of passing a theme object and re-running the renderer, it reads CSS variables directly from the browser.

TL;DR

  • Pele renders Mermaid syntax to SVG in a 230 kB gzip bundle, versus 1.6 MB for Mermaid.js.
  • render() returns the SVG in 0.05 to 0.3 ms, versus 6 to 82 ms for Mermaid.js.
  • The –pele-bg, –pele-fg, and –pele-line variables recolor the diagram without re-rendering it.
  • Zero direct dependencies reduce the audit surface compared to Mermaid.js’s 23.
  • npm install pele enables render() in any JavaScript or TypeScript project.

What Is Pele?

Pele is an open source JavaScript library that renders Mermaid diagrams to SVG without relying on an external layout engine or a UI framework. It weighs 230 kB compressed, declares no direct dependencies, and exposes its colors as CSS variables that any stylesheet can override.

The project lives at pele.run, where the official site also works as an interactive editor: you write Mermaid syntax on the left and the resulting SVG appears on the right, with a separate panel to test color variables live.

The value proposition isn’t adding new features on top of Mermaid.js, but solving a specific problem: rendering the same diagrams with less weight and a smaller dependency surface.

The Mermaid.js bundle weighs 1.6 MB compressed versus Pele’s 230 kB. Foto de ThisisEngineering en Unsplash

Why Mermaid Diagrams to SVG Matter in Technical Documentation

Every diagram on a documentation page adds to the JavaScript the browser has to download, parse, and execute before showing anything. With Mermaid.js, that bill runs around 1.6 MB compressed and 23 direct dependencies, even if the page only shows three boxes and two arrows.

That cost weighs differently depending on the project. A tech blog with one diagram per article barely notices it. An internal tool that renders dozens of diagrams per session (an architecture viewer, a runbook editor, a documentation generator built from code) does notice it, because each render repeats the parsing and layout cost.

Pele targets exactly that case. Its gzip bundle weighs 230 kB and its render time ranges from 0.05 to 0.3 ms, versus 6 to 82 ms for Mermaid.js. The difference becomes more noticeable the more diagrams a single page has, because each diagram pays its own render time.

How Pele Works Under the Hood

The library’s core function is render(): it takes a string with Mermaid syntax and returns an object with an svg property, which is the complete SVG markup ready to insert into the DOM. There’s no intermediate configuration step or theme object to pass as a second argument.

What sets Pele apart is how that SVG defines its colors. Instead of writing attributes with fixed values calculated at render time, the SVG elements reference CSS variables, for example fill="var(--pele-fg)". The browser resolves that variable when painting, not the library when generating the SVG.

That difference is what allows switching themes without re-rendering. If the color were fixed in the attribute, switching from light to dark would require calling render() again and replacing the entire SVG in the DOM; with CSS variables, it’s enough to change the value of --pele-bg in a CSS rule.

flowchart LR
 A["Mermaid syntax"] --> B["Internal parser"]
 B --> C["Layout calculation"]
 C --> D["SVG with var(--pele-fg)"]
 D --> E(["Browser"])

The same mechanism explains why the official demo lets you change colors without the diagram being redrawn: the “SVG with var(–pele-fg)” step in the diagram above already happened once, and from then on the browser handles the repainting.

Practical Examples with Progressive Code

The first example is the equivalent of a hello world: take a simple flowchart and show it on screen.

import { render } from 'pele';

const { svg } = render(`flowchart LR
  A[Build] --> B[Test]
  B --> C[Deploy]`);

document.querySelector('#diagrama').innerHTML = svg;
console.log(svg.startsWith('<svg'));
// true

render() is a pure function: it doesn’t touch the DOM itself, it only returns text. The console.log confirms the bare minimum you’d expect from any correct SVG renderer: that the returned string starts with the <svg> tag. Inserting that string with innerHTML is up to your code, not Pele’s.

The second example adds theming. The pele class on the container is what provides context for the CSS variables that follow: without that ancestor (or without defining them on :root), the SVG falls back to the library’s default values.

.pele {
  --pele-bg: #fffcf0;
  --pele-fg: #100f0f;
  --pele-muted: #6f6e69;
  --pele-line: #100f0f;
  --pele-surface: #f2f0e5;
  --pele-surface-alt: #e6e4d9;
  --pele-border: #cecdc3;
}

.pele.oscuro {
  --pele-bg: #100f0f;
  --pele-fg: #fffcf0;
  --pele-line: #fffcf0;
}

The third example connects both pieces: a button that toggles the oscuro class on the container, without touching the SVG that render() already generated.

const contenedor = document.querySelector('#diagrama');

document.querySelector('#toggle-tema').addEventListener('click', () => {
  contenedor.classList.toggle('oscuro');
});
sequenceDiagram
    participant U as User
    participant J as Page JS
    participant C as CSS
    participant S as Rendered SVG
    U->>J: click dark mode button
    J->>C: toggles the oscuro class
    C->>S: browser repaints var(--pele-bg)
    Note over S: render is not called again

To confirm theming is actually active, inspect the element in the browser’s devtools: if a node’s fill attribute shows var(--pele-fg) instead of a fixed hex value, the variable is connected. If a fixed color shows up instead, something in the build (an aggressive CSS minifier, for example) resolved the variable ahead of time.

Mermaid.js declares 23 direct dependencies; Pele declares none. Foto de Trnava University en Unsplash

Getting Started: Installation and First Render

The only thing you need before installing Pele is Node.js and a package manager on your machine; the command is identical on Windows, macOS, and Linux.

npm install pele

If your project uses another manager, the package installs the same way with pnpm add pele, yarn add pele, or bun add pele.

With the package installed, the first complete render on an HTML page looks like this:

import { render } from 'pele';

const diagrama = `flowchart TD
  A[HTTP request] --> B{Valid cache?}
  B -- Yes --> C[Respond from cache]
  B -- No --> D[Query origin]
  D --> E[Store in cache]
  E --> C`;

const { svg } = render(diagrama);
document.querySelector('#diagrama').innerHTML = svg;

There’s no initialization step or configuration object to create before calling render(). That’s consistent with the figure of zero direct dependencies: there’s no plugin engine to configure first.

💡 Tip: combining Pele’s CSS variables with prefers-color-scheme avoids writing JavaScript for dark mode: a media query that redefines --pele-bg and --pele-fg is enough for the diagram to respect the operating system’s preference without a click listener.

Real-World Use Cases

The most direct case is any static site that already writes diagrams in Mermaid syntax inside Markdown: documentation generators, internal wikis, tech blogs. Instead of loading the full Mermaid.js bundle on every page, a build step can walk through the code blocks marked as Mermaid and call render() once per diagram, leaving the SVG already resolved in the final HTML.

Another case is internal tools that generate diagrams dynamically from data: a microservice dependency viewer, an incident runbook editor, a dashboard that draws the state of a CI pipeline in real time. There, the render time per diagram shows up in the perceived latency of the interface.

A third case is editors or extensions that show a live preview of the diagram as the user types: there, the cost of re-rendering on every keystroke is the first thing you feel if the library is heavy.

Common Mistakes and Best Practices

The most common mistake is forgetting the pele class (or whatever equivalent you define) on an ancestor of the SVG. Pele’s CSS variables aren’t global by default: if you declare them on a class that never wraps the diagram’s container, the SVG uses its default values and the color change simply doesn’t appear.

The second mistake is confusing which changes need to call render() again and which don’t. Changing a color defined as a CSS variable doesn’t need it, the browser repaints on its own. But changing the diagram’s content does require running render() again with the updated string: CSS variables resolve theming, not structure.

⚠️ Watch out: if the text you pass to render() comes from an end user and not your own code, treat it as untrusted input before inserting the result with innerHTML. An SVG can include elements like <script> or embedded event handlers; sanitizing the resulting SVG (for example with DOMPurify configured for SVG) is a reasonable precaution in any flow where you didn’t write the diagram yourself.

Finally, before assuming Pele runs the same way in a Node build script as in the browser, test it in that specific environment: the demo at pele.run shows browser usage, and confirming that render() doesn’t depend on any specific DOM API is something worth verifying in your own project before relying on it in production.

Comparison: Pele vs Mermaid.js

The table summarizes the figures that pele.run publishes comparing both libraries on the same type of diagram.

MetricPeleMermaid.js
Bundle (gzip)230 kB1.6 MB
Render time0.05 to 0.3 ms6 to 82 ms
Direct dependencies023
ThemingCSS variables, no re-renderTheme configuration object
Small screensAdapts the layoutScales the whole diagram

The small screens row matters more than it seems: adapting the layout means reorganizing nodes so they fit the available width, while scaling the whole diagram also shrinks the text, which can end up illegible on a phone screen.

Going Deeper: Theming, Accessibility, and Pele’s Limits

The CSS variables model has an accessibility advantage that isn’t obvious at first glance: since the diagram’s text remains real SVG text, not a rasterized image, a screen reader can read it and a user can select and copy it. This isn’t exclusive to Pele, Mermaid.js also emits SVG with real text, but it’s a property that gets lost if at some point in the pipeline the SVG is converted to PNG to embed it in a PDF.

The choice between adapting the layout or scaling the whole diagram on small screens is a design decision with trade-offs in both directions: reorganizing nodes keeps the text legible but can stretch the diagram a lot vertically, while scaling everything preserves the original proportions but sacrifices legibility. A narrow hierarchy adapts better to reorganizing; a wide diagram with many nodes at the same level suffers more with either strategy.

flowchart TD
 A["You need Mermaid diagrams"] --> B{"Do bundle size and dependencies matter?"}
 B -- "Yes" --> C["Pele"]
 B -- "No, already using Mermaid.js" --> D["Mermaid.js"]
 C --> E(["Final SVG"])
 D --> E

That decision also depends on how much syntax coverage you need. Mermaid.js has accumulated years of diagram types (Gantt, state, class, entity-relationship, mind maps, among others) and a large community around that extended syntax. Before migrating an entire project from Mermaid.js to Pele, it’s worth checking, diagram by diagram, whether the type you use is supported in the documentation at pele.run, rather than assuming it because both accept Mermaid syntax.

Your next step: open the interactive editor at pele.run, change the value of --pele-bg from the browser’s devtools, and confirm in the Elements tab that the <svg> still shows var(--pele-bg) instead of a fixed color.

📬 Get new articles by email

We only email about big articles (1-2 a month).

Frequently Asked Questions

Does Pele Completely Replace Mermaid.js?

Not necessarily. Pele covers the case of rendering Mermaid syntax to SVG with less weight and simpler theming, but Mermaid.js has more diagram types accumulated over the years. It’s worth checking whether the types you use are supported before migrating an entire project.

Do Mermaid Diagrams to SVG Generated by Pele Work Offline?

Yes, once the package is installed, render() runs locally: it makes no network request to convert the syntax into SVG. The result also doesn’t depend on external resources to display, unless you yourself add external images or fonts inside the diagram.

Does Pele Support All of Mermaid.js’s Diagram Types?

The official site shows flowcharts in its main demo; to confirm coverage of other types (sequence, class, Gantt, state) you need to check the project’s documentation at pele.run instead of assuming full parity with Mermaid.js.

Can I Use Pele with React, Vue, or Svelte?

Yes, because render() returns an SVG string, not a component tied to a framework. In React you can insert it with dangerouslySetInnerHTML, in Vue with v-html, and in Svelte with {@html}, always with the same sanitization precautions if the content comes from a user.

What Happens If the SVG Generated by Pele Doesn’t Look Good on Small Screens?

Pele adapts the layout on small screens instead of scaling the whole diagram, which keeps the text legible at the cost of reorganizing the nodes. If a specific diagram still looks bad, checking whether it has many nodes at the same level helps diagnose the problem.

Does Pele Work in Node.js Without a Browser?

There’s no direct confirmation of this in the project’s public documentation. Before relying on usage at build time or on the server, it’s worth testing it in that specific environment, rather than assuming that the absence of dependencies implies the absence of browser APIs.

References

  • Pele: official project site, with an interactive editor, installation API, and performance comparison against Mermaid.js.
  • Mermaid.js: official documentation of the library that defines the syntax both projects share.
  • MDN: Using CSS custom properties: reference on how the CSS variables Pele uses for theming work.

📱 Enjoying this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.

Featured image: Foto de Ferenc Almasi en Unsplash

Did it work for you? Got a different error? Say so below: questions get answered and help the next reader.

Leave a comment
Categories: Tech NewsTutorials

Andrés Morales

Developer and AI researcher. Writes about language models, frameworks, developer tooling, and open source releases. Covers ML papers, the tech startup ecosystem, and programming trends.

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

You can include code inside <code>…</code> or, for several lines, <pre><code>…</code></pre>.

This site uses Akismet to reduce spam. Learn how your comment data is processed.