jbzoo/mermaid-php
jbzoo/mermaid-php lets PHP applications generate Mermaid diagram definitions with a clean, fluent API. Build flowcharts, sequence diagrams, class diagrams, and more, then render them in docs, dashboards, or web UIs without hand-writing Mermaid syntax.
What this package is: A PHP wrapper around the Mermaid diagram DSL (flowcharts, sequence diagrams, ER diagrams, Gantt, class diagrams). Its job is to turn a Mermaid source string into a rendered artifact (SVG/PNG) or to emit the Mermaid text for client-side rendering. The distinction matters enormously for how we integrate it.
Architecture fit: Reasonable fit only as a build-time / report-generation utility, not a request-path dependency. Mermaid rendering is CPU-heavy, requires a JavaScript engine (headless Chromium via mmdc/Puppeteer is the common backend), and produces artifacts that should be cached. In a Laravel app this belongs behind a queued job or an artisan command, writing to object storage — not in a controller.
Integration feasibility: Composer install is trivial; the hard dependency is the JS/Chromium toolchain. Expect the package to shell out to Node or a bundled runtime. That means our Docker images (web, queue, CI) need Node + Chromium + fonts + sandbox flags, or a sidecar rendering service. Composer alone is not the integration.
Technical risk:
--no-sandbox, /dev/shm limits, OOM on large graphs, non-deterministic layout across versions).Key questions to answer before committing:
mmdc, a JS bridge, or a hosted API?mmdc invocation, Kroki (self-hosted multi-format renderer), or Mermaid.js in the browser?Stack fit: Good composer-level fit with Laravel — likely usable via a thin service provider or a small wrapper class of our own. Treat the package as an implementation detail behind our own DiagramRenderer interface so we can swap backends (package → mmdc → Kroki) without touching call sites. This is the single most important integration decision.
Migration path:
mmdc implementation for a release cycle.Compatibility: Pin the package version exactly and pin the underlying Mermaid/Node version in the image. Do not let Composer float this dependency. Verify PHP version support against our current runtime before merging. Verify the license header of any bundled JS assets.
Sequencing:
DiagramRenderer interface + package adapter + queued job + S3 cache keyed by hash(source + version).Maintenance: Low code footprint, non-trivial environment footprint. Budget ongoing work for base-image upkeep (Chromium CVEs, Node LTS bumps) and Mermaid major-version migrations. Single-maintainer risk means we should be prepared to fork or replace the wrapper — which is why the adapter boundary matters.
Support: Failures will surface as "the diagram is missing/broken" in generated reports, not as 500s, if we queue and cache correctly. Instrument with structured logs capturing the Mermaid source hash and renderer version so we can reproduce. Document the Mermaid subset we officially support — don't promise arbitrary DSL.
Scaling: Rendering is CPU- and memory-bound and roughly linear per diagram; it does not belong on the web tier. Scale horizontally with dedicated queue workers (or a Kroki sidecar pool). Cache aggressively by content hash — most diagrams are regenerated unchanged. Expect a cold-render cost in the hundreds of ms to low seconds depending on graph size; set queue timeouts and memory limits deliberately (headless Chromium needs more than default PHP worker memory).
Failure modes to design for:
Ramp-up: Low for a PHP developer to call; medium to operate. One engineer familiar with Composer and Laravel queues can integrate in days; someone needs to own the container/toolchain. Write a one-page runbook: how to bump Mermaid, how to reproduce a bad diagram, how to switch the adapter to the fallback backend.
Recommendation: Adopt conditionally — for internal reporting/docs generation behind a queue and cache, with an owned adapter and a proven fallback. Do not adopt as a synchronous, customer-facing dependency. If the spike shows the package only emits text or the Chromium path is unstable, implement a ~50-line mmdc adapter instead and skip the dependency.
How can I help you explore Laravel packages today?