Open-source project
excalidraw/mermaid-to-excalidraw avatar
excalidraw/mermaid-to-excalidraw

mermaid-to-excalidraw: turning Mermaid text into hand-drawn style scenes

Generate Excalidraw diagrams from Mermaid

904 stars137 forksTypeScriptMIT

At a glance

What is it?
The @excalidraw/mermaid-to-excalidraw package parses a Mermaid diagram definition and returns Excalidraw elements and files, so a text diagram becomes a sketch you can move around. It is aimed at diagrams that people edit by hand afterwards, it only honours a handful of Mermaid config options, and the published version has moved well past the last tagged release.
Who is it for?
mermaid-to-excalidraw fits a team that keeps diagrams as Mermaid text in a repository but wants the output to look hand-drawn and to remain editable in Excalidraw, and who is willing to accept a limited set of Mermaid configuration options. It does not fit a project that needs the full Mermaid configuration surface or a faithful reproduction of Mermaid's own layout.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One function returns elements and files

The public API is a single function, and its signature tells you most of what you need to know:

ts
parseMermaidToExcalidraw(diagramDefinition: string, config?: MermaidConfig)

The first argument is the Mermaid diagram definition, the second is the Mermaid config, and the second is optional. The config parameter exists for cases where you want to pass a custom config to Mermaid itself, and the documentation is explicit about a limitation: the package only supports some of the config params. The call is asynchronous and it returns an object with two fields, elements and files, which is the part worth noticing. Elements are the shapes that make up the scene, and files are the separate assets the scene references. A caller that expects a single array of elements will get it wrong, and the example in the documentation is written to show both being handed to the renderer:

ts
import { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw";

try {
  const { elements, files } = await parseMermaidToExcalidraw(
    diagramDefinition,
    {
      themeVariables: {
        fontSize: "25px",
      },
    }
  );
  // Render elements and files on Excalidraw
} catch (e) {
  // Parse error, displaying error message to users
}

The try and catch is not decorative either. The function rejects when Mermaid cannot parse the definition, so a user typing a diagram into a form needs an error path.

Only five config options are honoured

The supported configuration surface is small enough to read in one pass, and the options come with their defaults and their types documented. startOnLoad is a boolean that decides whether the diagram starts automatically when the page loads, and it defaults to false. The flowchart option is an object with a single curve key, whose value is either linear or basis and which defaults to linear. themeVariables takes a fontSize string, defaulting to 20px, and this is the one that visibly changes the output, since the text in the scene is sized from it. Then there are two limits, maxEdges for the maximum number of edges to be rendered, defaulting to 500, and maxTextSize for the maximum number of characters to be rendered, defaulting to 50000. Those last two are the ones to know about, because they are guard rails on the size of a diagram rather than cosmetic switches, and a large flowchart will hit one of them.

Running the playground takes two commands

Working on the package itself is a yarn project with a small script set. Install the dependencies and start the development playground:

bash
yarn
bash
yarn start

The build command is separate:

bash
yarn build

The package manifest shows how those commands are wired. The build script removes the dist directory and then compiles the TypeScript project in src with tsc, and the package publishes only the dist folder, with the main entry pointing at the compiled index.js and the types at index.d.ts. The module is declared as an ES module. The dev and start scripts both run Vite against the playground directory in development mode, which is why the playground and the development server are the same thing, and there is a separate build:playground script that type checks the playground project before building it. A published live playground is also available at the project pages, so you can try a diagram without installing anything.

Visual tests, not just unit tests

The test setup is the interesting part of the repository layout, because this is a library whose output is a picture. The scripts include a plain vitest run for code tests and a coverage variant, and then three separate visual test commands, one to run them, one to update the snapshots and one to start a visual test development server:

bash
yarn test:visual

The visual tests are driven by Playwright, with a playwright.config.ts at the root, and they live in a visual-tests directory with its own Vite config. The snapshots are what make this meaningful for a diagram converter, because a change in how a flowchart is laid out will alter the rendered image rather than any assertion value, and a screenshot comparison catches that where a unit test on the element list would not. The documentation notes that the visual test dev server is usually better to use than the playground for this kind of work, which is a sensible piece of advice when you are checking whether a Mermaid change moved a box. The unit test side uses vitest with a vitest.config.ts and a jsdom environment, and the code tests are linted with eslint run at zero warnings.

The package version has moved past the release tags

Here is a detail that matters if you pin dependencies or read release notes to work out what changed. The package manifest declares the version as 2.2.2, and the dependencies on Mermaid and the Mermaid parser are recent, with mermaid at 11.x and @mermaid-js/parser at 0.6.x. The published release tags tell a different story. The list is v1.1.0 from 2024-07-10, v1.0.0 from 2024-05-20 and v0.3.0 from 2024-04-07, and there is nothing newer among the tags. So the code on the default branch is two major versions ahead of the newest tag, and the release notes attached to the tags describe a much older state of the package. The last push was on 2026-10-21, so the work is current. The practical implication is that a CHANGELOG entry may not tell you what changed in the version you are about to install, and that the tagged releases are not a good guide to the current API. The MIT licence field on the repository and the LICENSE file at the root are unambiguous, so redistribution is not the concern here, keeping track of versions is.

Mermaid handles the parsing, Excalidraw handles the drawing

It helps to be clear about which half of the problem this package solves, because the name suggests more than it does. The dependency list is the answer. Mermaid itself is a dependency, along with the standalone Mermaid parser, and the markdown-to-text helper from the Excalidraw organisation is there to flatten label text. That means Mermaid is doing the layout work, deciding where nodes and edges go and in what order, and this package is translating that result into Excalidraw's element format. The Excalidraw application itself appears only as a development dependency, which is consistent with a library that produces data rather than rendering it. The consequence is that the geometry you get is Mermaid's geometry, re-skinned, and it will not be identical to what Mermaid itself draws. The distinctive Excalidraw look comes from the hand-drawn style of the elements, and that is the reason to use this rather than embedding an SVG of the Mermaid output, since the output is a set of editable objects rather than a picture.

Adding a diagram type is a documented exercise

The scope of the package is bounded by what Mermaid can parse, and the project has a dedicated documentation page for adding support for a new diagram type, which tells you that the boundary is a real design decision rather than an accident. The set of supported diagrams is therefore whatever the pinned Mermaid version handles, filtered through what the converter implements. The repository structure backs this up. The src directory holds the library, the playground directory holds the demo application, the tests directory holds the unit tests, and the visual-tests directory holds the screenshot comparisons, with an images directory at the root for assets and a separate tsconfig.common.json shared between the root and the playground project. There is also a REMINDERS.md file at the root, which is the kind of artefact that tells you the project keeps working notes about the work in progress. For a user, the practical question is simpler: if the diagram type you need is not in the list of supported Mermaid types, the answer is not in this package, and the Mermaid to image route is the one that will cover everything Mermaid supports.

Editorial conclusion

mermaid-to-excalidraw fits a team that keeps diagrams as Mermaid text in a repository but wants the output to look hand-drawn and to remain editable in Excalidraw, and who is willing to accept a limited set of Mermaid configuration options. It does not fit a project that needs the full Mermaid configuration surface or a faithful reproduction of Mermaid's own layout. Before adopting it, read the returned elements and files rather than assuming a single object comes back, and pin the version you use, because the package manifest is at 2.2.2 while the newest release tag is v1.1.0 from 2024.

Frequently asked questions

How do I convert a Mermaid diagram to Excalidraw?

Call parseMermaidToExcalidraw with the diagram definition string and an optional config, await it, and use the elements and files it returns to render the scene in Excalidraw. The call rejects when the definition cannot be parsed, so handle the error case.

Which Mermaid config options does mermaid-to-excalidraw support?

Only a few: startOnLoad for auto-starting, a flowchart option with a curve setting of linear or basis, themeVariables with a fontSize, maxEdges for the maximum number of edges, and maxTextSize for the maximum number of characters. The documentation states that the package only supports those config params.

How do I run the mermaid-to-excalidraw playground locally?

Run yarn to install the packages, then yarn start to launch the development playground, which the manifest wires to Vite in development mode. The build command is yarn build, which clears the dist directory and compiles the TypeScript project in src.

Does mermaid-to-excalidraw have visual regression tests?

Yes. Three scripts handle them: yarn test:visual runs the Playwright visual tests, yarn test:visual:update updates the snapshots, and yarn test:visual:dev starts a visual test dev server, which the documentation says is usually better than the playground for that work.

Official sources

  1. excalidraw/mermaid-to-excalidraw on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/excalidraw-mermaid-to-excalidraw.svg)](https://hysenlabs.com/projects/excalidraw-mermaid-to-excalidraw)

Was this useful?