Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mermaid Php Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and verify

composer require jbzoo/mermaid-php --dev

Check composer.json for the PHP constraint (jbzoo packages are typically PHP 8.1+ with strict_types and no Laravel coupling), then confirm the package's binary is exposed:

ls vendor/bin | grep -i mermaid

Where to look first, in order

  1. README.md — the canonical list of supported diagram types and the fluent/array builder API. This is the source of truth for method names.
  2. tests/ — jbzoo packages ship heavy PHPUnit suites; the tests are effectively the API documentation for edge cases (escaping, options, CLI flags).
  3. src/ — look for the diagram builder classes (flowchart/sequence/class/ER/Gantt) and whether raw-script output (__toString()) is separated from rendering (mmdc/Node).
  4. vendor/bin/mermaid --help — if a CLI ships, it is the fastest way to test syntax without touching app code.

First use case (15 minutes)

Generate a deployment/checkout flowchart into a docs file, don't render yet:

use JBZoo\Mermaid\Mermaid; // verify namespace in src/

$chart = Mermaid::flowchart()
    ->direction('LR')
    ->node('start', 'Checkout')
    ->node('pay', 'Charge card')
    ->node('ok', 'Order paid')
    ->edge('start', 'pay')
    ->edge('pay', 'ok', 'success');

file_put_contents(base_path('docs/checkout.mmd'), (string) $chart);

Prove the source string is valid by pasting it into the Mermaid Live Editor once. Only after that wire up server-side rendering — rendering is the part that drags in Node, Chromium and CI concerns, so keep it out of your first loop.

Implementation Patterns

1. One class per diagram, checked into the repo

Treat diagrams like migrations: a small class returning a diagram object, a generated .mmd committed alongside, and the render as a build artifact.

final class CheckoutDiagram
{
    public function build(): mixed
    {
        return Mermaid::flowchart()
            ->direction('LR')
            // ...
            ;
    }
}

This gives you code review on diagram changes, git diff on the source, and a single place to update when a flow changes.

2. Artisan command + drift check in CI

class GenerateDiagramsCommand extends Command
{
    protected $signature = 'docs:diagrams';

    public function handle(): int
    {
        foreach (config('diagrams') as $name => $class) {
            file_put_contents(
                base_path("docs/diagrams/{$name}.mmd"),
                (string) app($class)->build()
            );
        }
        return self::SUCCESS;
    }
}

Then in CI: php artisan docs:diagrams && git diff --exit-code docs/diagrams — fails the build when code changed but diagrams didn't. Cheap, and it catches the common failure mode of stale architecture docs.

3. ER diagram straight from the Laravel schema

The highest-value day-to-day use: derive erDiagram from Schema::getTables() / getColumns() (native in Laravel 11+, doctrine/dbal on older versions). Loop tables → emit entities, loop columns → attributes, loop foreign keys → relations. Run it on a schedule and commit the result; it stays accurate for free and replaces hand-drawn schema images in onboarding docs.

Similarly: generate stateDiagram-v2 from a state machine config, sequenceDiagram from your HTTP kernel/event-listener map, classDiagram from selected domain classes.

4. Split rendering strategies — don't force Node everywhere

  • Interactive/local docs (Blade): emit the raw mermaid script into a <pre class="mermaid"> block and let mermaid.js render in the browser. Zero server dependencies, works offline in the repo. Use a Blade component so the CDN/version pin lives in one file.
  • Static SVG/PNG (README, PDF, slides, PR artifacts): server-side render via the package's mmdc/CLI renderer in CI only. Keep it out of the request path — it's seconds, not milliseconds.

5. Cache renders by content hash

If you render server-side inside any automated flow, key the output file on sha1($script . $rendererVersion . $theme) and skip the subprocess on hit. This turns a multi-diagram docs build from ~30s into ~1s on the common path.

6. Test the script, not the SVG

$this->assertStringContainsString('pay -->|success| ok', (string) $diagram);

SVG output embeds generated IDs, timestamps and renderer-version-dependent markup — snapshotting it produces permanently flaky tests. Snapshot the .mmd string (normalize \r\n → \n) and leave the renderer to a single smoke test.

7. Integration tip: escape at the boundary, not in the builder

If labels come from user data (table names, workflow step names, ticket titles), wrap them in one escapeLabel() helper that quotes the label and neutralizes ", (, ), ;, #, <, > and newlines. Call it wherever external strings enter, never scatter escaping through diagram classes.

Gotchas and Tips

Syntax and escaping

  • Unquoted labels break on parentheses, brackets, quotes, ;, and #. Always emit A["Charge card (Stripe)"] — quoted — and be aware " inside a quoted label needs entity-encoding (#quot;) in many mermaid versions.
  • %% is a comment; %%{init: {"theme":"dark"}}%% is a directive. Directives must be on the first line of the script or they are silently ignored in several mermaid versions. Same for flowchart vs graph — be consistent, they parse slightly differently.
  • Newlines in a label require <br/>, not \n. A stray real newline inside a node label is the #1 cause of "Parse error".

Security

  • Mermaid permits HTML in labels, and inline-rendered SVG is injected into the DOM. Any diagram built from user-supplied text is an XSS vector on a Blade page. Either escape strictly or set securityLevel: 'strict' in mermaid.initialize(). Do not skip this if labels come from a database.

Renderer / environment

  • Server-side rendering goes through @mermaid-js/mermaid-cli → Puppeteer → headless Chromium. In Docker/CI you'll need --no-sandbox (usually exposed as a puppeteer config file), plus the Chromium shared libs (libnss3, libatk, libgbm, fonts). Missing fonts → tofu boxes in PNG output; install fonts-dejavu or fonts-noto.
  • Version skew is the classic trap: the CLI's bundled mermaid version defines what syntax is valid. A diagram that renders in the Live Editor (latest) can fail on a pinned CI renderer. Pin mermaid-cli explicitly and pin the browser-side mermaid.js version to match; bump both together.
  • First render is slow (Node cold start, often 1–3s+). Batch multiple diagrams per subprocess if the package/CLI supports it, and always cache by hash.
  • Prefer SVG over PNG for docs — smaller, sharp, and no font-rendering dependency. PDF output inherits the Chromium print pipeline and is the fussiest format.

Diagram quality

  • Keep graphs under ~100 nodes. Mermaid's dagre layout degrades badly (and slowly) on dense graphs; if it looks like spaghetti, that's a signal to split into per-domain diagrams rather than tune the theme.
  • Set direction deliberately: LR for pipelines, TD for hierarchies. Default TD on a wide flow produces a very tall image that's unreadable in a README.
  • Add a generated-file header comment (%% generated by docs:diagrams — do not edit) so nobody hand-edits the .mmd and then loses it to the next regeneration.

Browser-side rendering quirks

  • Every diagram block on a page needs a unique id; duplicated IDs happen when rendering the same component twice and cause one diagram to vanish.
  • mermaid.initialize({startOnLoad: true}) only runs once. With Livewire, Turbo, htmx or Alpine-driven DOM swaps you must re-invoke mermaid.run({nodes: [...]}) after the swap; otherwise newly inserted diagrams stay as raw text.
  • Rendered SVG is not responsive by default — force max-width: 100%; height: auto in CSS or it will overflow on mobile.

Extension points

  • Most jbzoo builders implement __toString() for raw output; use that as the universal export and keep rendering pluggable behind a small interface (render(string $script): string) so you can swap mmdc for an HTTP call to a render service, or a fake in tests.
  • Theme/config is usually passable as an option array or a prepended init directive — centralize your house style (colors, font family, theme: 'base' + themeVariables) in one factory so all diagrams stay visually consistent, and so a re-theme is a one-file change.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource