Skip to main content

reflex-mermaidjs

mermaid-js diagrams for Reflex: flowcharts, sequence, class, state, ER, gantt, mindmap, architecture, C4, sankey, kanban, venn, wardley, railroad and 30+ other diagram types, generated from text the way markdown is.

  • Wraps mermaid 12.0.0 (ELK layout bundled), plus the tidy-tree layout and ZenUML plugins
  • Every mermaid option as a typed prop: theme, look (classic / handDrawn / neo), layout, security_level, theme_variables, raw config...
  • appearance="dark" automatic dark themes (same behaviour as mermaid.live)
  • Pan & zoom (wheel, drag, double-click to fit) with a floating toolbar and optional dotted grid
  • Events: on_render, on_error, on_node_click, on_zoom_change
  • Python actions: zoom_in, zoom_out, set_zoom, fit_view, reset_view, fullscreen, export_png, export_svg, copy_svg, get_svg
  • Icons: Iconify logos and mdi bundled, any other Iconify pack by name, Font Awesome fa: icons
  • KaTeX math ($$...$$) in labels
  • rx.markdown integration: ```mermaid fences become diagrams
  • Share helpers in pure Python: mermaid_live_url, deserialize_state (mermaid.live pako: links), mermaid_ink_url, kroki_url
  • 36 diagram types of sample diagrams (get_diagram_examples()), the same set mermaid.live offers

Installation

pip install reflex-mermaidjs
# or
uv add reflex-mermaidjs

Requires Python 3.11+ and reflex>=0.10.0 (Reflex 0.10 dropped Python 3.10). npm dependencies (mermaid, plugins, icons) are installed automatically by Reflex.

Quick start

import reflex as rx
from reflex_mermaidjs import mermaid


def index() -> rx.Component:
    return mermaid(
        """flowchart TD
    A[Christmas] -->|Get money| B(Go shopping)
    B --> C{Let me think}
    C -->|One| D[Laptop]
    C -->|Two| E[iPhone]
    C -->|Three| F[fa:fa-car Car]""",
        theme="forest",
    )


app = rx.App()
app.add_page(index)

The diagram text can be passed positionally or as chart=, and can be a state var — the diagram re-renders when it changes.

Live editing with state, pan & zoom and events

import reflex as rx
from reflex_mermaidjs import mermaid, export_png, fit_view


class State(rx.State):
    code: str = "sequenceDiagram\n    Alice->>Bob: Hi Bob\n    Bob-->>Alice: Hi Alice"
    diagram_type: str = ""
    error: str = ""

    @rx.event
    def set_code(self, value: str):
        self.code = value

    @rx.event
    def rendered(self, event: dict):
        self.diagram_type = event["diagram_type"]
        self.error = ""

    @rx.event
    def failed(self, event: dict):
        self.error = event["message"]

    @rx.event
    def clicked(self, event: dict):
        return rx.toast.info(f"Clicked {event['node_id']}")


def index() -> rx.Component:
    return rx.hstack(
        rx.text_area(value=State.code, on_change=State.set_code.debounce(250), width="40%", rows="20"),
        rx.vstack(
            mermaid(
                State.code,
                id="diagram",
                appearance=rx.color_mode_cond("light", "dark"),
                pan_zoom=True,
                grid=True,
                node_click=True,
                error_mode="keep-last",
                on_render=State.rendered,
                on_error=State.failed,
                on_node_click=State.clicked,
                height="600px",
                width="100%",
            ),
            rx.hstack(
                rx.button("Fit", on_click=fit_view("diagram")),
                rx.button("PNG", on_click=export_png("diagram", "diagram.png")),
                rx.text(State.diagram_type),
            ),
            width="60%",
        ),
    )

Props

Prop Type Description
chart str Diagram definition (front matter and %%{init}%% directives are supported)
config dict Raw MermaidConfig passed to mermaid.initialize
theme default, base, dark, forest, neutral, neo, neo-dark, redux, redux-dark, redux-color, redux-dark-color, null Theme
look classic, handDrawn, neo Visual look
layout str dagre, elk, elk.stress, elk.force, elk.mrtree, elk.radial, elk.box, elk.rectpacking, tidy-tree...
security_level strict, loose, antiscript, sandbox loose enables click callbacks and HTML labels
theme_variables / theme_css dict / str Theme customisation (most useful with theme="base")
font_family, font_size, hand_drawn_seed, dark_mode, html_labels, wrap, max_text_size, max_edges, deterministic_ids, log_level Same as the mermaid options
appearance light, dark With no explicit theme, dark uses the dark variant of each diagram type's default theme
tidy_tree bool Register the tidy-tree layout (default True)
zenuml bool Register ZenUML eagerly (it is auto-registered when the text starts with zenuml)
font_awesome bool Load Font Awesome CSS for fa: icons (default True)
icon_packs list[str | dict] Iconify packs. logos and mdi are bundled; other names load from jsDelivr; or {"name": ..., "url": ...}
pan_zoom bool Wheel zoom + drag pan. The component fills its box, so give it a height (defaults to 480px)
show_controls, controls_position bool, top-right... Floating toolbar (fit, zoom out, zoom in, 100%, fullscreen)
min_zoom, max_zoom, zoom_step, max_fit_zoom float Zoom limits
fit_on_render bool | "auto" auto fits on first render and when the diagram type/size changes a lot
grid bool Dotted background grid (color via the --mermaid-grid-color CSS variable)
center bool Center the SVG in static mode
debounce int Debounce re-renders in ms
error_mode inline, keep-last, none How parse errors are shown
click_callbacks list[str] Callback names used in click node callback directives, routed to on_node_click
node_click bool Emit on_node_click for any node click

Events

Event Payload
on_render {svg, diagram_type, render_id, render_ms}
on_error {message, line, expected}
on_node_click {node_id, callback, label, args}
on_zoom_change {zoom, x, y} (debounced)

Python actions

Any diagram with an id can be driven from event handlers or triggers. They return rx.call_script events:

from reflex_mermaidjs import zoom_in, zoom_out, set_zoom, fit_view, reset_view, fullscreen
from reflex_mermaidjs import export_png, export_svg, copy_svg, get_svg, get_png_data_url

rx.button("PNG", on_click=export_png("diagram", "diagram.png", scale=2, background="transparent"))
rx.button("Send SVG to Python", on_click=get_svg("diagram", State.receive_svg))

Markdown

from reflex_mermaidjs import markdown_with_mermaid, mermaid_component_map

markdown_with_mermaid(State.text, mermaid_props={"theme": "neutral"})
# or merge with your own map
rx.markdown(State.text, component_map={**mermaid_component_map(), "h1": my_h1})

Non-mermaid code fences keep the regular rx.code_block highlighting.

Sharing helpers

from reflex_mermaidjs import mermaid_live_url, mermaid_ink_url, kroki_url, deserialize_state

mermaid_live_url(code, {"theme": "dark"})  # https://mermaid.live/edit#pako:...
mermaid_ink_url(code, fmt="img", image_type="png")  # server-rendered image
kroki_url(code, "svg")
state = deserialize_state("https://mermaid.live/edit#pako:eNp...")  # {"code": ..., "mermaid": ...}

Icons

mermaid("""architecture-beta
    group api(logos:aws-lambda)[API]
    service db(logos:postgresql)[Database] in api
    service server(logos:python)[Server] in api
    db:L -- R:server""")

mermaid(
    chart,
    icon_packs=["logos", "mdi", "fa7-brands", {"name": "custom", "url": "https://example.com/icons.json"}],
)

Demo app

The mermaidjs_demo/ app is a mermaid.live-style editor built with this component:

  • Live editor — code editor with line numbers, config tab (theme/look/layout/security selectors + JSON), all sample diagrams, history, share dialog (mermaid.live / mermaid.ink / kroki links, import a mermaid.live link, Python and Markdown snippets), PNG/SVG export, hand-drawn/grid/pan-zoom toggles, dark mode
  • Gallery — every diagram type rendered live
  • Features — themes, looks, layouts, theme variables from state, data-driven charts, events and actions, markdown, icons, math, ZenUML, error handling
  • API — props table generated from the source
uv sync --all-groups
cd mermaidjs_demo
uv run reflex run

Development

uv sync --all-groups

uv run pytest                   # tests
uv run ruff check .             # lint
uv run ruff format .            # format
uv run bandit -c pyproject.toml -r . -ll   # SAST

uv run python -m reflex_base.utils.pyi_generator custom_components/reflex_mermaidjs  # regenerate .pyi stubs
uv build                        # builds dist/ (sdist + wheel)

The same checks run in CI on every push and pull request — see the Quality and Security workflows. Releases are tag-driven and documented in RELEASING.md; the security posture of the component is documented in SECURITY.md.

License

MIT © Ernesto Crespo

Metadata

Release files for reflex-mermaidjs 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for reflex-mermaidjs 0.2.1
File Size Uploaded Provenance
reflex_mermaidjs-0.2.1.tar.gz 48.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for reflex-mermaidjs 0.2.1
File Interpreter ABI Platform
reflex_mermaidjs-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 94.8 kB

Release files / reflex_mermaidjs-0.2.1.tar.gz

Download URL reflex_mermaidjs-0.2.1.tar.gz
Size 48.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9958a9f9729d10eaa65424a7c7d587e2a8cdcd0f144fa0cede28210c31ffdc0f
BLAKE2b-256 checksum
How to use checksums
b87cb3b5606cafa60f6691c96d665d0ce36ae92058547f9e58286feb219f297d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / reflex_mermaidjs-0.2.1-py3-none-any.whl

Download URL reflex_mermaidjs-0.2.1-py3-none-any.whl
Size 46.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
31fbb2a9e96fab78155ba92098732b483f56b648bec034629375f6b932d36433
BLAKE2b-256 checksum
How to use checksums
b8b9d3bbddb4c41b8e9a3117584012a1e62cf688b228da97c730ba7ba9acd366
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for reflex-mermaidjs 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page