Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.31.0 · main

Graph gallery

tier 3 — a surface

Whole graphs for real jobs. Each is one [data-graph] with the frame around it that the job needs — a toolbar, filters, a legend, a tooltip, a side panel — built from the markup on Graph, Graph layouts, Exploring a graph and Graph plugins. Nothing here is a component and nothing needs a script of your own: copy one, replace the list with your records, and it draws.

The list is the data, and the text alternative Every example's .graph-data is what the canvas draws and what a screen reader reads, so each record and each link is written as a sentence. Your app renders the same list from its own records. Past a few hundred, hand them over with data-graph-src or SetDataAsync instead of rendering markup.

An org chart

dagre from the top, data-graph-nodes="box" so every name is read, and data-graph-curve="taxi" for the right angles an org chart is expected to have. The role goes in data-meta, which a box writes under the name. Links carry no label, so data-graph-edge-labels="none" keeps the sentences off the canvas.

A dotted-line report is one more link with data-line="dotted". Draw it between adjacent levels: a hierarchy layout weighs every link the same, so a link that skips a level pulls the person it starts from down a rank. The search marks people rather than hiding the rest, and both downloads take the whole chart, not just the part in view.

  • Alex Fischer
  • Priya Nair
  • Elena Cavalli
  • Tobias Baumgartner
  • Judith Eichenberger
  • Jordan Weiss
  • Rin Nakamura
  • Marc Frei
  • Tomás Ferreira
  • Nadine Aebischer
  • Simon Dörig
  • Open role
  • Priya Nair reports to Alex Fischer.
  • Elena Cavalli reports to Alex Fischer.
  • Tobias Baumgartner reports to Alex Fischer.
  • Judith Eichenberger reports to Alex Fischer.
  • Jordan Weiss reports to Priya Nair.
  • Rin Nakamura reports to Priya Nair.
  • Marc Frei reports to Elena Cavalli.
  • Tomás Ferreira reports to Tobias Baumgartner.
  • Nadine Aebischer reports to Tobias Baumgartner.
  • Simon Dörig reports to Jordan Weiss.
  • The open data engineer role will report to Jordan Weiss.
  • Marc Frei also has a dotted-line report to Tobias Baumgartner.

Engineering Finance Operations People Reports to Dotted-line report Open role
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="toolbar-filters">
            <div class="input-group toolbar-input">
                <span class="input-affix"><i class="ri-search-line"></i></span>
                <input class="form-input" type="search" placeholder="Name or role" aria-label="Find a person" data-graph-search />
            </div>
        </div>
        <span class="toolbar-count" data-graph-stats="{nodes} people" data-graph-stats-match="{matches} of {nodes} people match"></span>
    </div>
    <div class="graph card" data-graph id="org-chart" data-graph-layout="dagre" data-graph-nodes="box"
         data-graph-curve="taxi" data-graph-edge-labels="none" aria-label="Organisation chart" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="md" data-tone="1" data-icon="ri-user-star-line" data-meta="Managing director" data-location="Zürich office" data-email="alex.fischer@example.com" data-root>Alex Fischer</li>
            <li data-node="engineering" data-tone="2" data-icon="ri-code-s-slash-line" data-meta="Engineering director" data-location="Zürich office" data-email="priya.nair@example.com">Priya Nair</li>
            <li data-node="finance" data-tone="3" data-icon="ri-funds-line" data-meta="Finance director" data-location="Milano office" data-email="elena.cavalli@example.com">Elena Cavalli</li>
            <li data-node="operations" data-tone="5" data-icon="ri-truck-line" data-meta="Operations director" data-location="Bern office" data-email="tobias.baumgartner@example.com">Tobias Baumgartner</li>
            <li data-node="people" data-tone="info" data-icon="ri-team-line" data-meta="Head of people" data-location="Zürich office" data-email="judith.eichenberger@example.com">Judith Eichenberger</li>
            <li data-node="platform" data-tone="2" data-meta="Platform lead" data-location="Remote" data-email="jordan.weiss@example.com">Jordan Weiss</li>
            <li data-node="design" data-tone="2" data-meta="Design lead" data-location="Zürich office" data-email="rin.nakamura@example.com">Rin Nakamura</li>
            <li data-node="controlling" data-tone="3" data-meta="Financial controller" data-location="Stuttgart office" data-email="marc.frei@example.com">Marc Frei</li>
            <li data-node="logistics" data-tone="5" data-meta="Logistics manager" data-location="Bern office" data-email="tomas.ferreira@example.com">Tomás Ferreira</li>
            <li data-node="service" data-tone="5" data-meta="Customer service lead" data-location="Zürich office" data-email="nadine.aebischer@example.com">Nadine Aebischer</li>
            <li data-node="reliability" data-tone="2" data-meta="Site reliability engineer" data-location="St. Gallen office" data-email="simon.doerig@example.com">Simon Dörig</li>
            <li data-node="data-role" data-tone="2" data-meta="Data engineer" data-location="Remote or Zürich" data-muted>Open role</li>

            <li data-edge data-source="md" data-target="engineering">Priya Nair reports to Alex Fischer.</li>
            <li data-edge data-source="md" data-target="finance">Elena Cavalli reports to Alex Fischer.</li>
            <li data-edge data-source="md" data-target="operations">Tobias Baumgartner reports to Alex Fischer.</li>
            <li data-edge data-source="md" data-target="people">Judith Eichenberger reports to Alex Fischer.</li>
            <li data-edge data-source="engineering" data-target="platform">Jordan Weiss reports to Priya Nair.</li>
            <li data-edge data-source="engineering" data-target="design">Rin Nakamura reports to Priya Nair.</li>
            <li data-edge data-source="finance" data-target="controlling">Marc Frei reports to Elena Cavalli.</li>
            <li data-edge data-source="operations" data-target="logistics">Tomás Ferreira reports to Tobias Baumgartner.</li>
            <li data-edge data-source="operations" data-target="service">Nadine Aebischer reports to Tobias Baumgartner.</li>
            <li data-edge data-source="platform" data-target="reliability">Simon Dörig reports to Jordan Weiss.</li>
            <li data-edge data-source="platform" data-target="data-role" data-line="dashed">The open data engineer role will report to Jordan Weiss.</li>
            <li data-edge data-source="operations" data-target="controlling" data-line="dotted" data-tone="5">Marc Frei also has a dotted-line report to Tobias Baumgartner.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
            <span class="graph-tools-sep"></span>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="export-svg" data-graph-filename="organisation-chart" aria-label="Download as SVG" data-tip="Download as SVG"><i class="ri-file-code-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="export-png" data-graph-filename="organisation-chart" aria-label="Download as PNG" data-tip="Download as PNG"><i class="ri-image-line"></i></button>
        </div>
        <div class="graph-tip" data-graph-tip hidden>
            <span class="graph-tip-head"><i data-graph-icon aria-hidden="true"></i><span class="graph-tip-title" data-graph-field="label"></span></span>
            <span class="graph-tip-meta" data-graph-field="meta"></span>
            <span class="graph-tip-meta" data-graph-field="location"></span>
            <span class="graph-tip-ref" data-graph-field="email"></span>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}, {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="graph-legend">
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-2"></span> <span>Engineering</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-3"></span> <span>Finance</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-5"></span> <span>Operations</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-info"></span> <span>People</span></span>
        <span class="graph-key"><span class="graph-line"></span> <span>Reports to</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dotted"></span> <span>Dotted-line report</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dashed"></span> <span>Open role</span></span>
    </div>
</div>

A service map with health

One data-group per team, laid out as islands and outlined with data-graph-hulls. The record whose id is the group's name is the team itself: it anchors its island and gives the outline its colour. Health is the tone — go, warn, danger — and the team's colour is a second one, data-tone-team, which the Health / Team switch chooses between. The words are in data-meta as well, so the tooltip, the search and the announcements say the status too.

The team chips are the legend for the islands and the filter at once. data-hub on the services that are failing writes their names in bold and puts them first when names compete for room, and data-graph-spacing="compact" keeps each island tight enough for every name to fit beside it.

  • Edge gateway
  • Storefront team
  • Web shop
  • Catalogue API
  • Search index
  • Recommendations
  • Checkout team
  • Checkout API
  • Basket service
  • Pricing engine
  • Payments team
  • Payments API
  • Fraud scoring
  • Ledger
  • Card gateway adapter
  • Fulfilment team
  • Orders API
  • Order worker
  • Warehouse sync
  • Shipping labels
  • Identity team
  • Identity API
  • Session store
  • The storefront team owns the web shop.
  • The storefront team owns the catalogue API.
  • The storefront team owns the search index.
  • The storefront team owns recommendations.
  • The checkout team owns the checkout API.
  • The checkout team owns the basket service.
  • The checkout team owns the pricing engine.
  • The payments team owns the payments API.
  • The payments team owns fraud scoring.
  • The payments team owns the ledger.
  • The payments team owns the card gateway adapter.
  • The fulfilment team owns the orders API.
  • The fulfilment team owns the order worker.
  • The fulfilment team owns warehouse sync.
  • The fulfilment team owns shipping labels.
  • The identity team owns the identity API.
  • The identity team owns the session store.
  • The edge gateway routes shoppers to the web shop.
  • The edge gateway routes to the checkout API.
  • The edge gateway signs shoppers in through the identity API.
  • The web shop reads products from the catalogue API.
  • The web shop asks recommendations for suggestions.
  • The web shop adds items to the basket service.
  • The catalogue API queries the search index.
  • Recommendations read products from the catalogue API.
  • The checkout API reads the basket.
  • The checkout API prices the basket with the pricing engine.
  • The pricing engine reads list prices from the catalogue API.
  • The checkout API verifies the shopper with the identity API.
  • The checkout API charges the card through the payments API.
  • The checkout API places the order with the orders API.
  • The payments API scores every charge with fraud scoring.
  • The payments API books every charge into the ledger.
  • The payments API authorises cards through the card gateway adapter.
  • The orders API queues each order for the order worker.
  • The order worker sends picking lists to warehouse sync.
  • The order worker prints shipping labels.
  • The identity API stores sessions in the session store.

Healthy Degraded Down Data store Calls Queues Owned by the team
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="toolbar-filters chip-set" role="group" aria-label="Teams">
            <button class="chip" type="button" data-graph-filter="group" value="storefront" aria-pressed="true"><span class="graph-swatch series-1"></span> <span>Storefront</span></button>
            <button class="chip" type="button" data-graph-filter="group" value="checkout" aria-pressed="true"><span class="graph-swatch series-3"></span> <span>Checkout</span></button>
            <button class="chip" type="button" data-graph-filter="group" value="payments" aria-pressed="true"><span class="graph-swatch series-5"></span> <span>Payments</span></button>
            <button class="chip" type="button" data-graph-filter="group" value="fulfilment" aria-pressed="true"><span class="graph-swatch series-4"></span> <span>Fulfilment</span></button>
            <button class="chip" type="button" data-graph-filter="group" value="identity" aria-pressed="true"><span class="graph-swatch series-2"></span> <span>Identity</span></button>
        </div>
        <div class="segmented segmented--sm" role="radiogroup" aria-label="Colour services by">
            <label class="segmented-option"><input type="radio" name="service-map-colour" value="tone" data-graph-option="colour" checked /> <span>Health</span></label>
            <label class="segmented-option"><input type="radio" name="service-map-colour" value="team" data-graph-option="colour" /> <span>Team</span></label>
        </div>
    </div>
    <div class="graph graph--lg card" data-graph id="service-map" data-graph-layout="islands" data-graph-hulls data-graph-spacing="compact"
         data-graph-arrows="target" aria-label="Service map by team, coloured by health" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="gateway" data-kind="edge" data-shape="hexagon" data-icon="ri-door-open-line" data-tone="go" data-tone-team="muted" data-meta="Healthy · p95 38 ms" data-host="edge-gateway-01" data-hub>Edge gateway</li>

            <li data-node="storefront" data-group="storefront" data-kind="team" data-shape="rounded" data-icon="ri-team-line" data-tone="1" data-meta="Owns 4 services">Storefront team</li>
            <li data-node="web-shop" data-group="storefront" data-kind="service" data-icon="ri-store-2-line" data-tone="go" data-tone-team="1" data-meta="Healthy · p95 120 ms" data-host="shop-web-01">Web shop</li>
            <li data-node="catalogue-api" data-group="storefront" data-kind="service" data-icon="ri-server-line" data-tone="go" data-tone-team="1" data-meta="Healthy · p95 64 ms" data-host="catalogue-api-02">Catalogue API</li>
            <li data-node="search-index" data-group="storefront" data-kind="store" data-shape="square" data-icon="ri-search-line" data-tone="go" data-tone-team="1" data-meta="Healthy · p95 22 ms" data-host="search-03">Search index</li>
            <li data-node="recommendations" data-group="storefront" data-kind="service" data-icon="ri-lightbulb-flash-line" data-tone="warn" data-tone-team="1" data-meta="Degraded · 3 % of requests fail" data-host="recs-worker-02" data-hub>Recommendations</li>

            <li data-node="checkout" data-group="checkout" data-kind="team" data-shape="rounded" data-icon="ri-team-line" data-tone="3" data-meta="Owns 3 services">Checkout team</li>
            <li data-node="checkout-api" data-group="checkout" data-kind="service" data-icon="ri-shopping-cart-2-line" data-tone="go" data-tone-team="3" data-meta="Healthy · p95 140 ms" data-host="checkout-api-01">Checkout API</li>
            <li data-node="basket" data-group="checkout" data-kind="service" data-icon="ri-server-line" data-tone="go" data-tone-team="3" data-meta="Healthy · p95 31 ms" data-host="basket-02">Basket service</li>
            <li data-node="pricing" data-group="checkout" data-kind="service" data-icon="ri-calculator-line" data-tone="go" data-tone-team="3" data-meta="Healthy · p95 47 ms" data-host="pricing-01">Pricing engine</li>

            <li data-node="payments" data-group="payments" data-kind="team" data-shape="rounded" data-icon="ri-team-line" data-tone="5" data-meta="Owns 4 services">Payments team</li>
            <li data-node="payments-api" data-group="payments" data-kind="service" data-icon="ri-bank-card-line" data-tone="go" data-tone-team="5" data-meta="Healthy · p95 210 ms" data-host="payments-api-01">Payments API</li>
            <li data-node="fraud" data-group="payments" data-kind="service" data-icon="ri-shield-check-line" data-tone="warn" data-tone-team="5" data-meta="Degraded · p95 1.9 s" data-host="fraud-score-01" data-hub>Fraud scoring</li>
            <li data-node="ledger" data-group="payments" data-kind="store" data-shape="square" data-icon="ri-database-2-line" data-tone="go" data-tone-team="5" data-meta="Healthy · replication lag 0 s" data-host="src-db-14">Ledger</li>
            <li data-node="card-gateway" data-group="payments" data-kind="service" data-icon="ri-exchange-line" data-tone="go" data-tone-team="5" data-meta="Healthy · p95 380 ms" data-host="card-adapter-01">Card gateway adapter</li>

            <li data-node="fulfilment" data-group="fulfilment" data-kind="team" data-shape="rounded" data-icon="ri-team-line" data-tone="4" data-meta="Owns 4 services">Fulfilment team</li>
            <li data-node="orders-api" data-group="fulfilment" data-kind="service" data-icon="ri-server-line" data-tone="go" data-tone-team="4" data-meta="Healthy · p95 95 ms" data-host="orders-console-01">Orders API</li>
            <li data-node="order-worker" data-group="fulfilment" data-kind="service" data-icon="ri-loop-right-line" data-tone="warn" data-tone-team="4" data-meta="Degraded · 1,240 messages waiting" data-host="orders-worker-03" data-hub>Order worker</li>
            <li data-node="warehouse-sync" data-group="fulfilment" data-kind="service" data-icon="ri-swap-line" data-tone="danger" data-tone-team="4" data-meta="Down since 09:12" data-host="wh-sync-01" data-hub>Warehouse sync</li>
            <li data-node="labels" data-group="fulfilment" data-kind="service" data-icon="ri-printer-line" data-tone="go" data-tone-team="4" data-meta="Healthy · p95 510 ms" data-host="labels-01">Shipping labels</li>

            <li data-node="identity" data-group="identity" data-kind="team" data-shape="rounded" data-icon="ri-team-line" data-tone="2" data-meta="Owns 2 services">Identity team</li>
            <li data-node="identity-api" data-group="identity" data-kind="service" data-icon="ri-key-2-line" data-tone="go" data-tone-team="2" data-meta="Healthy · p95 18 ms" data-host="identity-api-01">Identity API</li>
            <li data-node="session-store" data-group="identity" data-kind="store" data-shape="square" data-icon="ri-database-2-line" data-tone="go" data-tone-team="2" data-meta="Healthy · 42 % memory" data-host="session-cache-02">Session store</li>

            <li data-edge data-source="storefront" data-target="web-shop" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The storefront team owns the web shop.</li>
            <li data-edge data-source="storefront" data-target="catalogue-api" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The storefront team owns the catalogue API.</li>
            <li data-edge data-source="storefront" data-target="search-index" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The storefront team owns the search index.</li>
            <li data-edge data-source="storefront" data-target="recommendations" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The storefront team owns recommendations.</li>
            <li data-edge data-source="checkout" data-target="checkout-api" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The checkout team owns the checkout API.</li>
            <li data-edge data-source="checkout" data-target="basket" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The checkout team owns the basket service.</li>
            <li data-edge data-source="checkout" data-target="pricing" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The checkout team owns the pricing engine.</li>
            <li data-edge data-source="payments" data-target="payments-api" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The payments team owns the payments API.</li>
            <li data-edge data-source="payments" data-target="fraud" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The payments team owns fraud scoring.</li>
            <li data-edge data-source="payments" data-target="ledger" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The payments team owns the ledger.</li>
            <li data-edge data-source="payments" data-target="card-gateway" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The payments team owns the card gateway adapter.</li>
            <li data-edge data-source="fulfilment" data-target="orders-api" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The fulfilment team owns the orders API.</li>
            <li data-edge data-source="fulfilment" data-target="order-worker" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The fulfilment team owns the order worker.</li>
            <li data-edge data-source="fulfilment" data-target="warehouse-sync" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The fulfilment team owns warehouse sync.</li>
            <li data-edge data-source="fulfilment" data-target="labels" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The fulfilment team owns shipping labels.</li>
            <li data-edge data-source="identity" data-target="identity-api" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The identity team owns the identity API.</li>
            <li data-edge data-source="identity" data-target="session-store" data-kind="owns" data-label="owns" data-line="dotted" data-arrow="none" data-weight="light">The identity team owns the session store.</li>

            <li data-edge data-source="gateway" data-target="web-shop" data-kind="calls" data-label="routes">The edge gateway routes shoppers to the web shop.</li>
            <li data-edge data-source="gateway" data-target="checkout-api" data-kind="calls" data-label="routes">The edge gateway routes to the checkout API.</li>
            <li data-edge data-source="gateway" data-target="identity-api" data-kind="calls" data-label="signs in">The edge gateway signs shoppers in through the identity API.</li>
            <li data-edge data-source="web-shop" data-target="catalogue-api" data-kind="calls" data-label="reads">The web shop reads products from the catalogue API.</li>
            <li data-edge data-source="web-shop" data-target="recommendations" data-kind="calls" data-label="asks" data-tone="warn">The web shop asks recommendations for suggestions.</li>
            <li data-edge data-source="web-shop" data-target="basket" data-kind="calls" data-label="adds to">The web shop adds items to the basket service.</li>
            <li data-edge data-source="catalogue-api" data-target="search-index" data-kind="calls" data-label="queries">The catalogue API queries the search index.</li>
            <li data-edge data-source="recommendations" data-target="catalogue-api" data-kind="calls" data-label="reads">Recommendations read products from the catalogue API.</li>
            <li data-edge data-source="checkout-api" data-target="basket" data-kind="calls" data-label="reads">The checkout API reads the basket.</li>
            <li data-edge data-source="checkout-api" data-target="pricing" data-kind="calls" data-label="prices">The checkout API prices the basket with the pricing engine.</li>
            <li data-edge data-source="pricing" data-target="catalogue-api" data-kind="calls" data-label="reads">The pricing engine reads list prices from the catalogue API.</li>
            <li data-edge data-source="checkout-api" data-target="identity-api" data-kind="calls" data-label="verifies">The checkout API verifies the shopper with the identity API.</li>
            <li data-edge data-source="checkout-api" data-target="payments-api" data-kind="calls" data-label="charges" data-weight="heavy">The checkout API charges the card through the payments API.</li>
            <li data-edge data-source="checkout-api" data-target="orders-api" data-kind="calls" data-label="places" data-weight="heavy">The checkout API places the order with the orders API.</li>
            <li data-edge data-source="payments-api" data-target="fraud" data-kind="calls" data-label="scores" data-tone="warn">The payments API scores every charge with fraud scoring.</li>
            <li data-edge data-source="payments-api" data-target="ledger" data-kind="calls" data-label="books">The payments API books every charge into the ledger.</li>
            <li data-edge data-source="payments-api" data-target="card-gateway" data-kind="calls" data-label="authorises">The payments API authorises cards through the card gateway adapter.</li>
            <li data-edge data-source="orders-api" data-target="order-worker" data-kind="calls" data-label="queues" data-line="dashed">The orders API queues each order for the order worker.</li>
            <li data-edge data-source="order-worker" data-target="warehouse-sync" data-kind="calls" data-label="sends" data-tone="danger">The order worker sends picking lists to warehouse sync.</li>
            <li data-edge data-source="order-worker" data-target="labels" data-kind="calls" data-label="prints">The order worker prints shipping labels.</li>
            <li data-edge data-source="identity-api" data-target="session-store" data-kind="calls" data-label="stores">The identity API stores sessions in the session store.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
            <span class="graph-tools-sep"></span>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="hulls" aria-pressed="true" aria-label="Outline teams" data-tip="Outline teams"><i class="ri-shape-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fullscreen" aria-pressed="false" aria-label="Full screen" data-tip="Full screen">
                <i class="ri-fullscreen-line graph-when-off"></i><i class="ri-fullscreen-exit-line graph-when-on"></i>
            </button>
        </div>
        <div class="graph-tip" data-graph-tip hidden>
            <span class="graph-tip-head"><i data-graph-icon aria-hidden="true"></i><span class="graph-tip-title" data-graph-field="label"></span></span>
            <span class="graph-tip-meta" data-graph-field="meta"></span>
            <span class="graph-tip-ref" data-graph-field="host"></span>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}, {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="graph-legend">
        <span class="graph-key"><span class="graph-swatch series-go"></span> <span>Healthy</span></span>
        <span class="graph-key"><span class="graph-swatch series-warn"></span> <span>Degraded</span></span>
        <span class="graph-key"><span class="graph-swatch series-danger"></span> <span>Down</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--square series-muted"></span> <span>Data store</span></span>
        <span class="graph-key"><span class="graph-line graph-line--arrow"></span> <span>Calls</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dashed graph-line--arrow"></span> <span>Queues</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dotted"></span> <span>Owned by the team</span></span>
    </div>
</div>

A network by site and rack

Sites and racks are records too, and data-parent draws a host inside its rack and a rack inside its site. fcose is the layout that understands nested groups, and data-graph-collapse lets a reader fold a rack or a whole site away — with the cue on the group, or all at once from the toolbar.

Addresses are in data-meta, so typing 198.51 into the search marks the south site. The tooltip is the app's own .graph-tip, filled from data-role and data-meta; any data-* on a record is a field a slot can name.

  • North site
  • Rack A
  • Rack B
  • South site
  • Rack C
  • Rack D
  • edge-router-01
  • firewall-01
  • core-switch-01
  • rack-switch-11
  • src-db-14
  • src-db-15
  • rack-switch-12
  • build-runner-04
  • build-runner-05
  • core-switch-02
  • rack-switch-21
  • orders-console-01
  • orders-console-02
  • rack-switch-22
  • storage-node-07
  • storage-node-08
  • backup-vault-02
  • edge-router-01 hands all traffic to firewall-01.
  • firewall-01 connects to core-switch-01 at 10 Gb/s.
  • firewall-01 connects to core-switch-02 at 10 Gb/s.
  • core-switch-01 and core-switch-02 are joined by a 40 Gb/s link between the sites.
  • core-switch-01 connects to rack-switch-11 at 10 Gb/s.
  • core-switch-01 connects to rack-switch-12 at 10 Gb/s.
  • core-switch-02 connects to rack-switch-21 at 10 Gb/s.
  • core-switch-02 connects to rack-switch-22 at 10 Gb/s.
  • src-db-14 is on rack-switch-11.
  • src-db-15 is on rack-switch-11.
  • build-runner-04 is on rack-switch-12.
  • build-runner-05 is on rack-switch-12.
  • orders-console-01 is on rack-switch-21.
  • orders-console-02 is on rack-switch-21.
  • storage-node-07 is on rack-switch-22.
  • storage-node-08 is on rack-switch-22.
  • backup-vault-02 is on rack-switch-22.
  • src-db-14 replicates to src-db-15.
  • storage-node-07 mirrors storage-node-08.
  • storage-node-07 sends a nightly snapshot to backup-vault-02.

Network Compute Database Storage Failing Site or rack Trunk Between sites Replication and backup
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="toolbar-filters">
            <div class="input-group toolbar-input">
                <span class="input-affix"><i class="ri-search-line"></i></span>
                <input class="form-input" type="search" placeholder="Host or address" aria-label="Find a host by name or address" data-graph-search />
            </div>
            <span class="toolbar-count" data-graph-stats="{nodes} devices and groups" data-graph-stats-match="{matches} match"></span>
        </div>
        <div class="toolbar-actions">
            <button class="btn btn--sm" type="button" data-graph-action="expand-all"><i class="ri-expand-diagonal-line"></i> <span>Unfold all</span></button>
            <button class="btn btn--sm" type="button" data-graph-action="collapse-all"><i class="ri-collapse-diagonal-line"></i> <span>Fold all</span></button>
        </div>
    </div>
    <div class="graph graph--lg card" data-graph id="network" data-graph-layout="fcose" data-graph-spacing="compact"
         data-graph-collapse aria-label="Network by site and rack" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="north" data-tone="muted" data-meta="192.0.2.0/24">North site</li>
            <li data-node="rack-a" data-parent="north" data-tone="muted">Rack A</li>
            <li data-node="rack-b" data-parent="north" data-tone="muted">Rack B</li>
            <li data-node="south" data-tone="muted" data-meta="198.51.100.0/24">South site</li>
            <li data-node="rack-c" data-parent="south" data-tone="muted">Rack C</li>
            <li data-node="rack-d" data-parent="south" data-tone="muted">Rack D</li>

            <li data-node="edge-router-01" data-role="Router" data-icon="ri-global-line" data-shape="diamond" data-tone="6" data-meta="203.0.113.1">edge-router-01</li>
            <li data-node="firewall-01" data-role="Firewall" data-icon="ri-shield-line" data-shape="diamond" data-tone="6" data-meta="203.0.113.2">firewall-01</li>

            <li data-node="core-switch-01" data-parent="north" data-role="Core switch" data-icon="ri-router-line" data-shape="diamond" data-tone="6" data-meta="192.0.2.1">core-switch-01</li>
            <li data-node="rack-switch-11" data-parent="rack-a" data-role="Rack switch" data-icon="ri-router-line" data-shape="diamond" data-tone="6" data-meta="192.0.2.11">rack-switch-11</li>
            <li data-node="src-db-14" data-parent="rack-a" data-role="Database primary" data-icon="ri-database-2-line" data-shape="square" data-tone="3" data-meta="192.0.2.14">src-db-14</li>
            <li data-node="src-db-15" data-parent="rack-a" data-role="Database replica" data-icon="ri-database-2-line" data-shape="square" data-tone="3" data-meta="192.0.2.15">src-db-15</li>
            <li data-node="rack-switch-12" data-parent="rack-b" data-role="Rack switch" data-icon="ri-router-line" data-shape="diamond" data-tone="6" data-meta="192.0.2.12">rack-switch-12</li>
            <li data-node="build-runner-04" data-parent="rack-b" data-role="Build runner" data-icon="ri-cpu-line" data-tone="2" data-meta="192.0.2.31">build-runner-04</li>
            <li data-node="build-runner-05" data-parent="rack-b" data-role="Build runner" data-icon="ri-cpu-line" data-tone="2" data-meta="192.0.2.32">build-runner-05</li>

            <li data-node="core-switch-02" data-parent="south" data-role="Core switch" data-icon="ri-router-line" data-shape="diamond" data-tone="6" data-meta="198.51.100.1">core-switch-02</li>
            <li data-node="rack-switch-21" data-parent="rack-c" data-role="Rack switch" data-icon="ri-router-line" data-shape="diamond" data-tone="6" data-meta="198.51.100.11">rack-switch-21</li>
            <li data-node="orders-console-01" data-parent="rack-c" data-role="Application server" data-icon="ri-server-line" data-tone="2" data-meta="198.51.100.21">orders-console-01</li>
            <li data-node="orders-console-02" data-parent="rack-c" data-role="Application server" data-icon="ri-server-line" data-tone="2" data-meta="198.51.100.22">orders-console-02</li>
            <li data-node="rack-switch-22" data-parent="rack-d" data-role="Rack switch" data-icon="ri-router-line" data-shape="diamond" data-tone="6" data-meta="198.51.100.12">rack-switch-22</li>
            <li data-node="storage-node-07" data-parent="rack-d" data-role="Storage node" data-icon="ri-hard-drive-2-line" data-shape="hexagon" data-tone="5" data-meta="198.51.100.41">storage-node-07</li>
            <li data-node="storage-node-08" data-parent="rack-d" data-role="Storage node · a disk is failing" data-icon="ri-hard-drive-2-line" data-shape="hexagon" data-tone="danger" data-meta="198.51.100.42" data-hub>storage-node-08</li>
            <li data-node="backup-vault-02" data-parent="rack-d" data-role="Backup vault" data-icon="ri-archive-line" data-shape="hexagon" data-tone="5" data-meta="198.51.100.43">backup-vault-02</li>

            <li data-edge data-source="edge-router-01" data-target="firewall-01" data-label="uplink" data-weight="heavy">edge-router-01 hands all traffic to firewall-01.</li>
            <li data-edge data-source="firewall-01" data-target="core-switch-01" data-label="10 Gb/s" data-weight="heavy">firewall-01 connects to core-switch-01 at 10 Gb/s.</li>
            <li data-edge data-source="firewall-01" data-target="core-switch-02" data-label="10 Gb/s" data-weight="heavy">firewall-01 connects to core-switch-02 at 10 Gb/s.</li>
            <li data-edge data-source="core-switch-01" data-target="core-switch-02" data-label="40 Gb/s between sites" data-weight="heavy" data-line="dashed">core-switch-01 and core-switch-02 are joined by a 40 Gb/s link between the sites.</li>
            <li data-edge data-source="core-switch-01" data-target="rack-switch-11" data-label="10 Gb/s">core-switch-01 connects to rack-switch-11 at 10 Gb/s.</li>
            <li data-edge data-source="core-switch-01" data-target="rack-switch-12" data-label="10 Gb/s">core-switch-01 connects to rack-switch-12 at 10 Gb/s.</li>
            <li data-edge data-source="core-switch-02" data-target="rack-switch-21" data-label="10 Gb/s">core-switch-02 connects to rack-switch-21 at 10 Gb/s.</li>
            <li data-edge data-source="core-switch-02" data-target="rack-switch-22" data-label="10 Gb/s">core-switch-02 connects to rack-switch-22 at 10 Gb/s.</li>
            <li data-edge data-source="rack-switch-11" data-target="src-db-14" data-label="1 Gb/s">src-db-14 is on rack-switch-11.</li>
            <li data-edge data-source="rack-switch-11" data-target="src-db-15" data-label="1 Gb/s">src-db-15 is on rack-switch-11.</li>
            <li data-edge data-source="rack-switch-12" data-target="build-runner-04" data-label="1 Gb/s">build-runner-04 is on rack-switch-12.</li>
            <li data-edge data-source="rack-switch-12" data-target="build-runner-05" data-label="1 Gb/s">build-runner-05 is on rack-switch-12.</li>
            <li data-edge data-source="rack-switch-21" data-target="orders-console-01" data-label="1 Gb/s">orders-console-01 is on rack-switch-21.</li>
            <li data-edge data-source="rack-switch-21" data-target="orders-console-02" data-label="1 Gb/s">orders-console-02 is on rack-switch-21.</li>
            <li data-edge data-source="rack-switch-22" data-target="storage-node-07" data-label="10 Gb/s">storage-node-07 is on rack-switch-22.</li>
            <li data-edge data-source="rack-switch-22" data-target="storage-node-08" data-label="10 Gb/s">storage-node-08 is on rack-switch-22.</li>
            <li data-edge data-source="rack-switch-22" data-target="backup-vault-02" data-label="10 Gb/s">backup-vault-02 is on rack-switch-22.</li>
            <li data-edge data-source="src-db-14" data-target="src-db-15" data-label="replicates" data-line="dotted">src-db-14 replicates to src-db-15.</li>
            <li data-edge data-source="storage-node-07" data-target="storage-node-08" data-label="mirrors" data-line="dotted">storage-node-07 mirrors storage-node-08.</li>
            <li data-edge data-source="storage-node-07" data-target="backup-vault-02" data-label="nightly snapshot" data-line="dotted">storage-node-07 sends a nightly snapshot to backup-vault-02.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="arrange" aria-label="Arrange again" data-tip="Arrange again"><i class="ri-magic-line"></i></button>
        </div>
        <div class="graph-tip" data-graph-tip hidden>
            <span class="graph-tip-head"><i data-graph-icon aria-hidden="true"></i><span class="graph-tip-title" data-graph-field="label"></span></span>
            <span class="graph-tip-meta" data-graph-field="role"></span>
            <span class="graph-tip-ref" data-graph-field="meta"></span>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}, {role}, {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="graph-legend">
        <span class="graph-key"><span class="graph-swatch graph-swatch--diamond series-6"></span> <span>Network</span></span>
        <span class="graph-key"><span class="graph-swatch series-2"></span> <span>Compute</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--square series-3"></span> <span>Database</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--hexagon series-5"></span> <span>Storage</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--hexagon series-danger"></span> <span>Failing</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--group series-muted"></span> <span>Site or rack</span></span>
        <span class="graph-key"><span class="graph-line graph-line--heavy"></span> <span>Trunk</span></span>
        <span class="graph-key"><span class="graph-line graph-line--heavy graph-line--dashed"></span> <span>Between sites</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dotted"></span> <span>Replication and backup</span></span>
    </div>
</div>

A knowledge graph

Notes, tasks, people and tags, each kind with its own shape as well as its own colour, filed into one island per project. People and tags belong to no project, so they sit between the islands they join. The kind chips are the legend and the switch, and Done tasks shows or hides the records marked data-muted.

Select a record and the side panel lists what it touches, one row per neighbour cloned from the app's <template data-graph-neighbour>; a row selects that neighbour, so the reader can walk the graph from the keyboard alone. Right-click a record, or press Shift + F10 on it, for the menu. Names give way to each other at this size — zoom in, point at a record or search to read the rest.

  • Spring catalogue
  • Kick-off notes
  • Photo shoot brief
  • Print schedule
  • Book the photographer
  • Approve the layout
  • Send files to the printer
  • Warehouse move
  • Floor plan, second draft
  • Forklift rental quotes
  • Moving weekend checklist
  • Order new racking
  • Label the bays
  • Move slow sellers first
  • Supplier onboarding
  • Supplier checklist
  • Contract template
  • Sign the framework contract
  • Set up supplier accounts
  • Collect safety certificates
  • Alex Fischer
  • Priya Nair
  • Jordan Weiss
  • Rin Nakamura
  • Tomás Ferreira
  • print
  • budget
  • logistics
  • legal
  • The kick-off notes are filed under the spring catalogue.
  • The photo shoot brief is filed under the spring catalogue.
  • The print schedule is filed under the spring catalogue.
  • Booking the photographer is filed under the spring catalogue.
  • Approving the layout is filed under the spring catalogue.
  • Sending files to the printer is filed under the spring catalogue.
  • The floor plan is filed under the warehouse move.
  • The forklift quotes are filed under the warehouse move.
  • The moving weekend checklist is filed under the warehouse move.
  • Ordering new racking is filed under the warehouse move.
  • Labelling the bays is filed under the warehouse move.
  • Moving slow sellers is filed under the warehouse move.
  • The supplier checklist is filed under supplier onboarding.
  • The contract template is filed under supplier onboarding.
  • Signing the framework contract is filed under supplier onboarding.
  • Setting up supplier accounts is filed under supplier onboarding.
  • Collecting safety certificates is filed under supplier onboarding.
  • Approving the layout is described in the print schedule.
  • Sending files to the printer is described in the print schedule.
  • Booking the photographer is described in the photo shoot brief.
  • Ordering new racking is described in the floor plan.
  • Labelling the bays is described in the moving weekend checklist.
  • Signing the framework contract is described in the contract template.
  • Setting up supplier accounts is described in the supplier checklist.
  • The kick-off notes link to the floor plan, because the catalogue shoot uses the new warehouse.
  • Alex Fischer wrote the kick-off notes.
  • Rin Nakamura wrote the photo shoot brief.
  • Tomás Ferreira wrote the floor plan.
  • Jordan Weiss wrote the supplier checklist.
  • Approving the layout is assigned to Alex Fischer.
  • Sending files to the printer is assigned to Rin Nakamura.
  • Booking the photographer was assigned to Rin Nakamura.
  • Ordering new racking is assigned to Tomás Ferreira.
  • Labelling the bays is assigned to Jordan Weiss.
  • Moving slow sellers was assigned to Tomás Ferreira.
  • Signing the framework contract is assigned to Alex Fischer.
  • Setting up supplier accounts is assigned to Priya Nair.
  • Collecting safety certificates was assigned to Jordan Weiss.
  • The kick-off notes are tagged print.
  • The kick-off notes are tagged budget.
  • The print schedule is tagged print.
  • Sending files to the printer is tagged print.
  • The forklift quotes are tagged budget.
  • Ordering new racking is tagged budget.
  • The moving weekend checklist is tagged logistics.
  • Labelling the bays is tagged logistics.
  • The contract template is tagged legal.
  • Signing the framework contract is tagged legal.

Project Done task Filed under, written by, assigned to Tagged
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="toolbar-filters">
            <div class="input-group toolbar-input">
                <span class="input-affix"><i class="ri-search-line"></i></span>
                <input class="form-input" type="search" placeholder="Search" aria-label="Search the knowledge graph" data-graph-search />
            </div>
            <label class="form-check"><input type="checkbox" data-graph-show="muted" checked /> <span>Done tasks</span></label>
        </div>
        <span class="toolbar-count" data-graph-stats="{nodes} records · {edges} links" data-graph-stats-match="{matches} of {nodes} records match"></span>
    </div>
    <div class="chip-set" role="group" aria-label="Show kinds">
        <button class="chip" type="button" data-graph-filter="kind" value="note" aria-pressed="true"><span class="graph-swatch graph-swatch--rounded series-2"></span> <span>Notes</span></button>
        <button class="chip" type="button" data-graph-filter="kind" value="task" aria-pressed="true"><span class="graph-swatch graph-swatch--diamond series-3"></span> <span>Tasks</span></button>
        <button class="chip" type="button" data-graph-filter="kind" value="person" aria-pressed="true"><span class="graph-swatch series-5"></span> <span>People</span></button>
        <button class="chip" type="button" data-graph-filter="kind" value="tag" aria-pressed="true"><span class="graph-swatch graph-swatch--tag series-6"></span> <span>Tags</span></button>
    </div>
    <div class="sedna-split">
        <div class="graph card" data-graph id="knowledge" data-graph-layout="islands"
             aria-label="Knowledge graph of three projects" aria-roledescription="graph">
            <ul class="graph-data" data-graph-data>
                <li data-node="catalogue" data-group="catalogue" data-kind="project" data-shape="hexagon" data-icon="ri-folder-3-line" data-tone="1" data-meta="Project · due 1 April">Spring catalogue</li>
                <li data-node="kickoff" data-group="catalogue" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 12 January" data-tags="print budget">Kick-off notes</li>
                <li data-node="shoot-brief" data-group="catalogue" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 3 February">Photo shoot brief</li>
                <li data-node="print-schedule" data-group="catalogue" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 9 February" data-tags="print">Print schedule</li>
                <li data-node="book-photographer" data-group="catalogue" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · done 5 February" data-muted>Book the photographer</li>
                <li data-node="approve-layout" data-group="catalogue" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · due 6 March">Approve the layout</li>
                <li data-node="send-to-printer" data-group="catalogue" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · due 14 March" data-tags="print">Send files to the printer</li>

                <li data-node="warehouse" data-group="warehouse" data-kind="project" data-shape="hexagon" data-icon="ri-folder-3-line" data-tone="1" data-meta="Project · due 30 May">Warehouse move</li>
                <li data-node="floor-plan" data-group="warehouse" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 20 February">Floor plan, second draft</li>
                <li data-node="forklift-quotes" data-group="warehouse" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 24 February" data-tags="budget">Forklift rental quotes</li>
                <li data-node="moving-checklist" data-group="warehouse" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 2 March" data-tags="logistics">Moving weekend checklist</li>
                <li data-node="order-racking" data-group="warehouse" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · due 20 March" data-tags="budget">Order new racking</li>
                <li data-node="label-bays" data-group="warehouse" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · due 10 May" data-tags="logistics">Label the bays</li>
                <li data-node="move-slow-sellers" data-group="warehouse" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · done 1 March" data-muted>Move slow sellers first</li>

                <li data-node="suppliers" data-group="suppliers" data-kind="project" data-shape="hexagon" data-icon="ri-folder-3-line" data-tone="1" data-meta="Project · ongoing">Supplier onboarding</li>
                <li data-node="supplier-checklist" data-group="suppliers" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 15 January">Supplier checklist</li>
                <li data-node="contract-template" data-group="suppliers" data-kind="note" data-shape="rounded" data-tone="2" data-meta="Note · 18 January" data-tags="legal">Contract template</li>
                <li data-node="sign-contract" data-group="suppliers" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · due 28 February" data-tags="legal">Sign the framework contract</li>
                <li data-node="supplier-accounts" data-group="suppliers" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · due 7 March">Set up supplier accounts</li>
                <li data-node="collect-certificates" data-group="suppliers" data-kind="task" data-shape="diamond" data-tone="3" data-meta="Task · done 2 February" data-muted>Collect safety certificates</li>

                <li data-node="alex" data-kind="person" data-tone="5" data-icon="ri-user-line" data-meta="Person · Managing director">Alex Fischer</li>
                <li data-node="priya" data-kind="person" data-tone="5" data-icon="ri-user-line" data-meta="Person · Engineering">Priya Nair</li>
                <li data-node="jordan" data-kind="person" data-tone="5" data-icon="ri-user-line" data-meta="Person · Operations">Jordan Weiss</li>
                <li data-node="rin" data-kind="person" data-tone="5" data-icon="ri-user-line" data-meta="Person · Design">Rin Nakamura</li>
                <li data-node="tomas" data-kind="person" data-tone="5" data-icon="ri-user-line" data-meta="Person · Logistics">Tomás Ferreira</li>

                <li data-node="tag-print" data-kind="tag" data-shape="tag" data-tone="6" data-meta="Tag">print</li>
                <li data-node="tag-budget" data-kind="tag" data-shape="tag" data-tone="6" data-meta="Tag">budget</li>
                <li data-node="tag-logistics" data-kind="tag" data-shape="tag" data-tone="6" data-meta="Tag">logistics</li>
                <li data-node="tag-legal" data-kind="tag" data-shape="tag" data-tone="6" data-meta="Tag">legal</li>

                <li data-edge data-source="kickoff" data-target="catalogue" data-kind="filed" data-label="filed under">The kick-off notes are filed under the spring catalogue.</li>
                <li data-edge data-source="shoot-brief" data-target="catalogue" data-kind="filed" data-label="filed under">The photo shoot brief is filed under the spring catalogue.</li>
                <li data-edge data-source="print-schedule" data-target="catalogue" data-kind="filed" data-label="filed under">The print schedule is filed under the spring catalogue.</li>
                <li data-edge data-source="book-photographer" data-target="catalogue" data-kind="filed" data-label="filed under">Booking the photographer is filed under the spring catalogue.</li>
                <li data-edge data-source="approve-layout" data-target="catalogue" data-kind="filed" data-label="filed under">Approving the layout is filed under the spring catalogue.</li>
                <li data-edge data-source="send-to-printer" data-target="catalogue" data-kind="filed" data-label="filed under">Sending files to the printer is filed under the spring catalogue.</li>
                <li data-edge data-source="floor-plan" data-target="warehouse" data-kind="filed" data-label="filed under">The floor plan is filed under the warehouse move.</li>
                <li data-edge data-source="forklift-quotes" data-target="warehouse" data-kind="filed" data-label="filed under">The forklift quotes are filed under the warehouse move.</li>
                <li data-edge data-source="moving-checklist" data-target="warehouse" data-kind="filed" data-label="filed under">The moving weekend checklist is filed under the warehouse move.</li>
                <li data-edge data-source="order-racking" data-target="warehouse" data-kind="filed" data-label="filed under">Ordering new racking is filed under the warehouse move.</li>
                <li data-edge data-source="label-bays" data-target="warehouse" data-kind="filed" data-label="filed under">Labelling the bays is filed under the warehouse move.</li>
                <li data-edge data-source="move-slow-sellers" data-target="warehouse" data-kind="filed" data-label="filed under">Moving slow sellers is filed under the warehouse move.</li>
                <li data-edge data-source="supplier-checklist" data-target="suppliers" data-kind="filed" data-label="filed under">The supplier checklist is filed under supplier onboarding.</li>
                <li data-edge data-source="contract-template" data-target="suppliers" data-kind="filed" data-label="filed under">The contract template is filed under supplier onboarding.</li>
                <li data-edge data-source="sign-contract" data-target="suppliers" data-kind="filed" data-label="filed under">Signing the framework contract is filed under supplier onboarding.</li>
                <li data-edge data-source="supplier-accounts" data-target="suppliers" data-kind="filed" data-label="filed under">Setting up supplier accounts is filed under supplier onboarding.</li>
                <li data-edge data-source="collect-certificates" data-target="suppliers" data-kind="filed" data-label="filed under">Collecting safety certificates is filed under supplier onboarding.</li>

                <li data-edge data-source="approve-layout" data-target="print-schedule" data-kind="mentions" data-label="described in">Approving the layout is described in the print schedule.</li>
                <li data-edge data-source="send-to-printer" data-target="print-schedule" data-kind="mentions" data-label="described in">Sending files to the printer is described in the print schedule.</li>
                <li data-edge data-source="book-photographer" data-target="shoot-brief" data-kind="mentions" data-label="described in">Booking the photographer is described in the photo shoot brief.</li>
                <li data-edge data-source="order-racking" data-target="floor-plan" data-kind="mentions" data-label="described in">Ordering new racking is described in the floor plan.</li>
                <li data-edge data-source="label-bays" data-target="moving-checklist" data-kind="mentions" data-label="described in">Labelling the bays is described in the moving weekend checklist.</li>
                <li data-edge data-source="sign-contract" data-target="contract-template" data-kind="mentions" data-label="described in">Signing the framework contract is described in the contract template.</li>
                <li data-edge data-source="supplier-accounts" data-target="supplier-checklist" data-kind="mentions" data-label="described in">Setting up supplier accounts is described in the supplier checklist.</li>
                <li data-edge data-source="kickoff" data-target="floor-plan" data-kind="mentions" data-label="links to">The kick-off notes link to the floor plan, because the catalogue shoot uses the new warehouse.</li>

                <li data-edge data-source="kickoff" data-target="alex" data-kind="author" data-label="written by">Alex Fischer wrote the kick-off notes.</li>
                <li data-edge data-source="shoot-brief" data-target="rin" data-kind="author" data-label="written by">Rin Nakamura wrote the photo shoot brief.</li>
                <li data-edge data-source="floor-plan" data-target="tomas" data-kind="author" data-label="written by">Tomás Ferreira wrote the floor plan.</li>
                <li data-edge data-source="supplier-checklist" data-target="jordan" data-kind="author" data-label="written by">Jordan Weiss wrote the supplier checklist.</li>
                <li data-edge data-source="approve-layout" data-target="alex" data-kind="assigned" data-label="assigned to">Approving the layout is assigned to Alex Fischer.</li>
                <li data-edge data-source="send-to-printer" data-target="rin" data-kind="assigned" data-label="assigned to">Sending files to the printer is assigned to Rin Nakamura.</li>
                <li data-edge data-source="book-photographer" data-target="rin" data-kind="assigned" data-label="assigned to">Booking the photographer was assigned to Rin Nakamura.</li>
                <li data-edge data-source="order-racking" data-target="tomas" data-kind="assigned" data-label="assigned to">Ordering new racking is assigned to Tomás Ferreira.</li>
                <li data-edge data-source="label-bays" data-target="jordan" data-kind="assigned" data-label="assigned to">Labelling the bays is assigned to Jordan Weiss.</li>
                <li data-edge data-source="move-slow-sellers" data-target="tomas" data-kind="assigned" data-label="assigned to">Moving slow sellers was assigned to Tomás Ferreira.</li>
                <li data-edge data-source="sign-contract" data-target="alex" data-kind="assigned" data-label="assigned to">Signing the framework contract is assigned to Alex Fischer.</li>
                <li data-edge data-source="supplier-accounts" data-target="priya" data-kind="assigned" data-label="assigned to">Setting up supplier accounts is assigned to Priya Nair.</li>
                <li data-edge data-source="collect-certificates" data-target="jordan" data-kind="assigned" data-label="assigned to">Collecting safety certificates was assigned to Jordan Weiss.</li>

                <li data-edge data-source="kickoff" data-target="tag-print" data-kind="tagged" data-label="tagged" data-line="dotted">The kick-off notes are tagged print.</li>
                <li data-edge data-source="kickoff" data-target="tag-budget" data-kind="tagged" data-label="tagged" data-line="dotted">The kick-off notes are tagged budget.</li>
                <li data-edge data-source="print-schedule" data-target="tag-print" data-kind="tagged" data-label="tagged" data-line="dotted">The print schedule is tagged print.</li>
                <li data-edge data-source="send-to-printer" data-target="tag-print" data-kind="tagged" data-label="tagged" data-line="dotted">Sending files to the printer is tagged print.</li>
                <li data-edge data-source="forklift-quotes" data-target="tag-budget" data-kind="tagged" data-label="tagged" data-line="dotted">The forklift quotes are tagged budget.</li>
                <li data-edge data-source="order-racking" data-target="tag-budget" data-kind="tagged" data-label="tagged" data-line="dotted">Ordering new racking is tagged budget.</li>
                <li data-edge data-source="moving-checklist" data-target="tag-logistics" data-kind="tagged" data-label="tagged" data-line="dotted">The moving weekend checklist is tagged logistics.</li>
                <li data-edge data-source="label-bays" data-target="tag-logistics" data-kind="tagged" data-label="tagged" data-line="dotted">Labelling the bays is tagged logistics.</li>
                <li data-edge data-source="contract-template" data-target="tag-legal" data-kind="tagged" data-label="tagged" data-line="dotted">The contract template is tagged legal.</li>
                <li data-edge data-source="sign-contract" data-target="tag-legal" data-kind="tagged" data-label="tagged" data-line="dotted">Signing the framework contract is tagged legal.</li>
            </ul>
            <div class="graph-canvas"></div>
            <div class="graph-tools" role="toolbar" aria-label="View">
                <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
                <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
                <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
                <span class="graph-tools-sep"></span>
                <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="reset" aria-label="Reset the view and the filters" data-tip="Reset"><i class="ri-restart-line"></i></button>
            </div>
            <div class="menu graph-menu" data-graph-menu role="menu" hidden>
                <span class="menu-label" data-graph-field="label"></span>
                <button class="menu-item" role="menuitem" type="button" data-graph-action="focus"><i class="ri-focus-3-line"></i> <span>Only its neighbourhood</span></button>
                <button class="menu-item" role="menuitem" type="button" data-graph-action="unfocus"><i class="ri-apps-2-line"></i> <span>Everything again</span></button>
                <button class="menu-item" role="menuitem" type="button" data-graph-action="hide"><i class="ri-eye-off-line"></i> <span>Hide it</span></button>
                <button class="menu-item" role="menuitem" type="button" data-graph-action="show-all"><i class="ri-eye-line"></i> <span>Show what I hid</span></button>
            </div>
            <div class="graph-wait skeleton skeleton-block"></div>
            <p class="visually-hidden" data-graph-live aria-live="polite"
               data-graph-announce="{label}, {meta}. {links} links." data-graph-announce-select="{label} selected. Its links are listed beside the graph."></p>
        </div>
        <aside class="card card--fill sedna-split-aside graph-detail" data-graph-detail hidden aria-label="Selected record">
            <div class="card-head">
                <strong data-graph-field="label"></strong>
                <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="clear" aria-label="Close the panel"><i class="ri-close-line"></i></button>
            </div>
            <div class="card-body">
                <p class="form-hint" data-graph-field="meta"></p>
                <ul class="list" data-graph-neighbours>
                    <template data-graph-neighbour>
                        <li>
                            <button class="list-row" type="button" data-graph-action="select">
                                <span class="list-main">
                                    <span class="list-title" data-graph-field="label"></span>
                                    <span class="list-sub">
                                        <span class="graph-direction" aria-hidden="true"><i class="ri-arrow-right-line graph-direction-out"></i><i class="ri-arrow-left-line graph-direction-in"></i><i class="ri-arrow-left-right-line graph-direction-both"></i></span>
                                        <span data-graph-link></span>
                                    </span>
                                </span>
                            </button>
                        </li>
                    </template>
                </ul>
            </div>
            <div class="card-foot card-foot--start">
                <button class="btn btn--sm" type="button" data-graph-action="focus"><i class="ri-focus-3-line"></i> <span>Neighbourhood</span></button>
                <button class="btn btn--ghost btn--sm" type="button" data-graph-action="unfocus">Everything</button>
            </div>
        </aside>
    </div>
    <div class="graph-legend">
        <span class="graph-key"><span class="graph-swatch graph-swatch--hexagon series-1"></span> <span>Project</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--diamond series-3 graph-swatch--muted"></span> <span>Done task</span></span>
        <span class="graph-key"><span class="graph-line"></span> <span>Filed under, written by, assigned to</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dotted"></span> <span>Tagged</span></span>
    </div>
</div>

A state machine

dagre left to right, boxes, arrows, and the event on every transition with data-graph-edge-labels="always". The start and the two ends are data-display="dot" in a graph of boxes; the failure is danger, the exceptions are dashed, and data-root rings the state this order is in. data-graph-drag="false" keeps a diagram people learn by its shape from being pulled apart.

Keep event names short. A transition's label sits between two states on a link no longer than the gap between them, and a long one covers its own arrow.

Order lifecycle This order is packed
  • Start
  • Placed
  • Payment failed
  • Paid
  • Packed
  • Shipped
  • Delivered
  • Refused
  • Cancelled
  • Closed
  • An order starts when it is placed.
  • A placed order is paid.
  • A placed order fails when the card is declined.
  • A failed payment can be retried, which places the order again.
  • A failed payment that is not retried within a day cancels the order, which ends it.
  • A paid order is packed.
  • A packed order is shipped.
  • A shipped order is delivered.
  • A shipped order is refused when nobody accepts it at the door.
  • A delivered order is closed after 30 days, which ends it.
  • A refused order is closed once it is refunded.

Payment Fulfilment Failure Start or end Normal path Exception
<div class="card">
    <div class="card-head">
        <strong>Order lifecycle</strong>
        <span class="badge badge--info">This order is packed</span>
    </div>
    <div class="graph graph--sm" data-graph id="order-states" data-graph-layout="dagre" data-graph-direction="LR" data-graph-nodes="box"
         data-graph-arrows="target" data-graph-edge-labels="always" data-graph-drag="false"
         aria-label="Order lifecycle: the states an order moves through" aria-roledescription="state diagram">
        <ul class="graph-data" data-graph-data>
            <li data-node="start" data-display="dot" data-tone="muted" data-weight="0">Start</li>
            <li data-node="placed" data-tone="6" data-meta="Awaiting payment">Placed</li>
            <li data-node="payment-failed" data-tone="danger" data-icon="ri-error-warning-line" data-meta="Card declined">Payment failed</li>
            <li data-node="paid" data-tone="6">Paid</li>
            <li data-node="packed" data-tone="4" data-meta="In the warehouse" data-root>Packed</li>
            <li data-node="shipped" data-tone="4">Shipped</li>
            <li data-node="delivered" data-tone="go">Delivered</li>
            <li data-node="refused" data-tone="warn" data-meta="Back to the warehouse">Refused</li>
            <li data-node="cancelled" data-display="dot" data-tone="muted" data-weight="0">Cancelled</li>
            <li data-node="closed" data-display="dot" data-tone="go" data-weight="0">Closed</li>

            <li data-edge data-source="start" data-target="placed" data-label="place">An order starts when it is placed.</li>
            <li data-edge data-source="placed" data-target="paid" data-label="pay">A placed order is paid.</li>
            <li data-edge data-source="placed" data-target="payment-failed" data-label="decline" data-tone="danger">A placed order fails when the card is declined.</li>
            <li data-edge data-source="payment-failed" data-target="placed" data-label="retry" data-line="dashed">A failed payment can be retried, which places the order again.</li>
            <li data-edge data-source="payment-failed" data-target="cancelled" data-label="time out" data-line="dashed">A failed payment that is not retried within a day cancels the order, which ends it.</li>
            <li data-edge data-source="paid" data-target="packed" data-label="pack">A paid order is packed.</li>
            <li data-edge data-source="packed" data-target="shipped" data-label="ship">A packed order is shipped.</li>
            <li data-edge data-source="shipped" data-target="delivered" data-label="deliver">A shipped order is delivered.</li>
            <li data-edge data-source="shipped" data-target="refused" data-label="refuse" data-line="dashed">A shipped order is refused when nobody accepts it at the door.</li>
            <li data-edge data-source="delivered" data-target="closed" data-label="close">A delivered order is closed after 30 days, which ends it.</li>
            <li data-edge data-source="refused" data-target="closed" data-label="refund">A refused order is closed once it is refunded.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}. {meta}. {links} transitions." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="card-foot card-foot--start">
        <div class="graph-legend">
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-6"></span> <span>Payment</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-4"></span> <span>Fulfilment</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-danger"></span> <span>Failure</span></span>
            <span class="graph-key"><span class="graph-swatch series-muted"></span> <span>Start or end</span></span>
            <span class="graph-key"><span class="graph-line graph-line--arrow"></span> <span>Normal path</span></span>
            <span class="graph-key"><span class="graph-line graph-line--dashed graph-line--arrow"></span> <span>Exception</span></span>
        </div>
    </div>
</div>

An automation flow, mid-run

A flow as an automation tool exports it, drawn with dagre across, and a run on top of it: data-state on each record says how far the run has got. Set it on records only — a link takes its target's state, so data flowing into the step that is running marches along its link. The chat and phone branches were not taken, and a link out of a skipped step is skipped too, so they stay quiet all the way into Classify while the link from the email runs.

The state is drawn around a record and its tone is left alone, so the step kinds stay readable as the run moves through them. Say the state in words as well — here in data-meta, which the box, the tooltip and the announcement repeat. Re-render the list with new states, or send them with SetDataAsync, and only what changed is redrawn, where it stands.

Support intake Running Started 09:14:02 by a webhook
  • Webhook
  • Parse payload
  • Find the caller
  • Which channel?
  • Clean the email
  • Chat transcript
  • Transcribe call
  • Ask for the order
  • Classify (AI)
  • Summarise (AI)
  • Merge
  • Create ticket
  • Urgent?
  • Page on-call
  • Queue it
  • Reply to caller
  • The webhook's payload is parsed.
  • The parsed payload names the caller, who is looked up.
  • The run branches on the channel the request came in by.
  • An email is cleaned of signatures and quoted replies.
  • A chat has its transcript joined.
  • A call is transcribed.
  • A caller with no order number is asked for one.
  • The cleaned email is classified by urgency and topic.
  • The cleaned email is summarised.
  • A chat transcript would be classified.
  • A call transcript would be classified.
  • The classification is merged with the rest.
  • The summary is merged with the rest.
  • The caller's reply is merged with the rest.
  • A ticket is created from what was merged.
  • The run branches on urgency.
  • An urgent ticket pages the on-call engineer.
  • Any other ticket joins the support queue.
  • The caller is told the ticket's number.

Trigger Data AI Logic Action
Done Running Waiting Next Skipped Failed
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <strong>Support intake</strong>
        <span class="badge badge--info"><i class="ri-loader-4-line"></i> <span>Running</span></span>
        <span class="toolbar-count">Started 09:14:02 by a webhook</span>
    </div>
    <div class="graph card" data-graph id="support-run" data-graph-layout="dagre" data-graph-direction="LR" data-graph-nodes="box"
         data-graph-arrows="target" data-graph-edge-labels="none" data-graph-spacing="compact" data-graph-drag="false"
         aria-label="Support intake automation, run in progress" aria-roledescription="automation flow">
        <ul class="graph-data" data-graph-data>
            <li data-node="webhook" data-kind="trigger" data-tone="1" data-icon="ri-webhook-line" data-state="done" data-meta="Done · POST /hooks/support">Webhook</li>
            <li data-node="parse" data-kind="data" data-tone="2" data-icon="ri-code-s-slash-line" data-state="done" data-meta="Done in 12 ms">Parse payload</li>
            <li data-node="lookup" data-kind="data" data-tone="2" data-icon="ri-user-search-line" data-state="done" data-meta="Done · Northwind Retail">Find the caller</li>
            <li data-node="channel" data-kind="logic" data-tone="6" data-icon="ri-git-branch-line" data-state="done" data-meta="Done · email">Which channel?</li>
            <li data-node="email" data-kind="data" data-tone="2" data-icon="ri-mail-line" data-state="done" data-meta="Done in 40 ms">Clean the email</li>
            <li data-node="chat" data-kind="data" data-tone="2" data-icon="ri-chat-3-line" data-state="skipped" data-meta="Skipped">Chat transcript</li>
            <li data-node="phone" data-kind="data" data-tone="2" data-icon="ri-phone-line" data-state="skipped" data-meta="Skipped">Transcribe call</li>
            <li data-node="order" data-kind="action" data-tone="3" data-icon="ri-question-answer-line" data-state="waiting" data-meta="Waiting for a reply">Ask for the order</li>
            <li data-node="classify" data-kind="ai" data-tone="5" data-icon="ri-sparkling-2-line" data-state="running" data-meta="Running · 4 s">Classify (AI)</li>
            <li data-node="summarise" data-kind="ai" data-tone="5" data-icon="ri-quill-pen-line" data-state="done" data-meta="Done in 2.1 s">Summarise (AI)</li>
            <li data-node="merge" data-kind="logic" data-tone="6" data-icon="ri-git-merge-line" data-state="next" data-meta="Up next">Merge</li>
            <li data-node="ticket" data-kind="action" data-tone="3" data-icon="ri-ticket-2-line" data-meta="Not reached">Create ticket</li>
            <li data-node="urgent" data-kind="logic" data-tone="6" data-icon="ri-git-branch-line" data-meta="Not reached">Urgent?</li>
            <li data-node="page" data-kind="action" data-tone="3" data-icon="ri-alarm-warning-line" data-meta="Not reached">Page on-call</li>
            <li data-node="queue" data-kind="action" data-tone="3" data-icon="ri-inbox-line" data-meta="Not reached">Queue it</li>
            <li data-node="reply" data-kind="action" data-tone="3" data-icon="ri-reply-line" data-meta="Not reached">Reply to caller</li>

            <li data-edge data-source="webhook" data-target="parse">The webhook's payload is parsed.</li>
            <li data-edge data-source="parse" data-target="lookup">The parsed payload names the caller, who is looked up.</li>
            <li data-edge data-source="lookup" data-target="channel">The run branches on the channel the request came in by.</li>
            <li data-edge data-source="channel" data-target="email">An email is cleaned of signatures and quoted replies.</li>
            <li data-edge data-source="channel" data-target="chat">A chat has its transcript joined.</li>
            <li data-edge data-source="channel" data-target="phone">A call is transcribed.</li>
            <li data-edge data-source="lookup" data-target="order">A caller with no order number is asked for one.</li>
            <li data-edge data-source="email" data-target="classify">The cleaned email is classified by urgency and topic.</li>
            <li data-edge data-source="email" data-target="summarise">The cleaned email is summarised.</li>
            <li data-edge data-source="chat" data-target="classify">A chat transcript would be classified.</li>
            <li data-edge data-source="phone" data-target="classify">A call transcript would be classified.</li>
            <li data-edge data-source="classify" data-target="merge">The classification is merged with the rest.</li>
            <li data-edge data-source="summarise" data-target="merge">The summary is merged with the rest.</li>
            <li data-edge data-source="order" data-target="merge">The caller's reply is merged with the rest.</li>
            <li data-edge data-source="merge" data-target="ticket">A ticket is created from what was merged.</li>
            <li data-edge data-source="ticket" data-target="urgent">The run branches on urgency.</li>
            <li data-edge data-source="urgent" data-target="page">An urgent ticket pages the on-call engineer.</li>
            <li data-edge data-source="urgent" data-target="queue">Any other ticket joins the support queue.</li>
            <li data-edge data-source="ticket" data-target="reply">The caller is told the ticket's number.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
            <span class="graph-tools-sep"></span>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fullscreen" aria-pressed="false" aria-label="Full screen" data-tip="Full screen">
                <i class="ri-fullscreen-line graph-when-off"></i><i class="ri-fullscreen-exit-line graph-when-on"></i>
            </button>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}, {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="sedna-row-wrap">
        <div class="graph-legend" role="group" aria-label="Steps">
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-1"></span> <span>Trigger</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-2"></span> <span>Data</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-5"></span> <span>AI</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-6"></span> <span>Logic</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-3"></span> <span>Action</span></span>
        </div>
        <div class="graph-legend sedna-push" role="group" aria-label="This run">
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-go"></span> <span>Done</span></span>
            <span class="graph-key"><span class="graph-line graph-line--flow graph-line--arrow"></span> <span>Running</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--group series-warn"></span> <span>Waiting</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--group series-1"></span> <span>Next</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--group series-muted"></span> <span>Skipped</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-danger"></span> <span>Failed</span></span>
        </div>
    </div>
</div>

A dependency tree

Versions in data-meta, deprecated packages data-muted behind a data-graph-show="muted" checkbox, and build-only packages behind a chip on their own field, data-scope. The two radios are data-graph-option="direction", so the same tree reads down or across without a script.

A package two others depend on is one record with two links in, which is what makes it a graph and not a tree — log-core here. The advisory is a danger tone and an icon and words in the box, never the colour alone.

  • storefront-web
  • http-client
  • auth-client
  • json-codec
  • image-resize
  • date-format
  • test-runner
  • retry-policy
  • log-core
  • crypto-kit
  • text-encoding
  • native-imaging
  • locale-data
  • assert-kit
  • mock-kit
  • storefront-web depends on auth-client 3.4.1.
  • storefront-web depends on json-codec 13.0.3.
  • storefront-web depends on image-resize 2.2.0; 2.3.0 is available.
  • storefront-web depends on date-format 1.9.8, which is deprecated.
  • storefront-web builds with test-runner 17.0.0.
  • http-client depends on retry-policy 7.3.0.
  • http-client depends on log-core 6.1.0.
  • retry-policy depends on log-core 6.1.0.
  • auth-client depends on http-client 8.1.0.
  • auth-client depends on crypto-kit 2.4.1, which has a published security advisory.
  • json-codec depends on text-encoding 5.0.0.
  • image-resize depends on native-imaging 1.12.0.
  • date-format depends on locale-data 0.8.2, which is deprecated.
  • test-runner depends on assert-kit 4.0.0.
  • test-runner depends on mock-kit 2.1.0.

Up to date Update available Security advisory Deprecated Depends on Build only
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="toolbar-filters">
            <div class="segmented segmented--sm" role="group" aria-label="Direction">
                <label class="segmented-option"><input type="radio" name="packages-direction" value="TB" data-graph-option="direction" checked /><i class="ri-arrow-down-line"></i> <span>Top down</span></label>
                <label class="segmented-option"><input type="radio" name="packages-direction" value="LR" data-graph-option="direction" /><i class="ri-arrow-right-line"></i> <span>Left to right</span></label>
            </div>
            <label class="form-check"><input type="checkbox" data-graph-show="muted" checked /> <span>Deprecated</span></label>
            <button class="chip" type="button" data-graph-filter="scope" value="build" aria-pressed="true">Build-only</button>
        </div>
        <span class="toolbar-count" data-graph-stats="{nodes} of {totalNodes} packages"></span>
    </div>
    <div class="graph graph--lg card" data-graph id="packages" data-graph-layout="dagre" data-graph-nodes="box"
         data-graph-arrows="target" data-graph-edge-labels="none" aria-label="Dependency tree of the storefront package" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="storefront-web" data-tone="1" data-icon="ri-store-2-line" data-meta="4.2.0" data-scope="runtime" data-root>storefront-web</li>
            <li data-node="http-client" data-tone="2" data-meta="8.1.0" data-scope="runtime">http-client</li>
            <li data-node="auth-client" data-tone="2" data-icon="ri-box-3-line" data-meta="3.4.1" data-scope="runtime">auth-client</li>
            <li data-node="json-codec" data-tone="2" data-icon="ri-box-3-line" data-meta="13.0.3" data-scope="runtime">json-codec</li>
            <li data-node="image-resize" data-tone="warn" data-icon="ri-box-3-line" data-meta="2.2.0 → 2.3.0" data-scope="runtime">image-resize</li>
            <li data-node="date-format" data-tone="muted" data-icon="ri-box-3-line" data-meta="1.9.8 · deprecated" data-scope="runtime" data-muted>date-format</li>
            <li data-node="test-runner" data-tone="2" data-icon="ri-box-3-line" data-meta="17.0.0" data-scope="build">test-runner</li>
            <li data-node="retry-policy" data-tone="2" data-meta="7.3.0" data-scope="runtime">retry-policy</li>
            <li data-node="log-core" data-tone="2" data-meta="6.1.0" data-scope="runtime">log-core</li>
            <li data-node="crypto-kit" data-tone="danger" data-icon="ri-alert-line" data-meta="2.4.1 · advisory" data-scope="runtime">crypto-kit</li>
            <li data-node="text-encoding" data-tone="2" data-meta="5.0.0" data-scope="runtime">text-encoding</li>
            <li data-node="native-imaging" data-tone="2" data-meta="1.12.0" data-scope="runtime">native-imaging</li>
            <li data-node="locale-data" data-tone="muted" data-meta="0.8.2 · deprecated" data-scope="runtime" data-muted>locale-data</li>
            <li data-node="assert-kit" data-tone="2" data-meta="4.0.0" data-scope="build">assert-kit</li>
            <li data-node="mock-kit" data-tone="2" data-meta="2.1.0" data-scope="build">mock-kit</li>

            <li data-edge data-source="storefront-web" data-target="auth-client">storefront-web depends on auth-client 3.4.1.</li>
            <li data-edge data-source="storefront-web" data-target="json-codec">storefront-web depends on json-codec 13.0.3.</li>
            <li data-edge data-source="storefront-web" data-target="image-resize">storefront-web depends on image-resize 2.2.0; 2.3.0 is available.</li>
            <li data-edge data-source="storefront-web" data-target="date-format" data-muted>storefront-web depends on date-format 1.9.8, which is deprecated.</li>
            <li data-edge data-source="storefront-web" data-target="test-runner" data-line="dashed">storefront-web builds with test-runner 17.0.0.</li>
            <li data-edge data-source="http-client" data-target="retry-policy">http-client depends on retry-policy 7.3.0.</li>
            <li data-edge data-source="http-client" data-target="log-core">http-client depends on log-core 6.1.0.</li>
            <li data-edge data-source="retry-policy" data-target="log-core">retry-policy depends on log-core 6.1.0.</li>
            <li data-edge data-source="auth-client" data-target="http-client">auth-client depends on http-client 8.1.0.</li>
            <li data-edge data-source="auth-client" data-target="crypto-kit" data-tone="danger">auth-client depends on crypto-kit 2.4.1, which has a published security advisory.</li>
            <li data-edge data-source="json-codec" data-target="text-encoding">json-codec depends on text-encoding 5.0.0.</li>
            <li data-edge data-source="image-resize" data-target="native-imaging">image-resize depends on native-imaging 1.12.0.</li>
            <li data-edge data-source="date-format" data-target="locale-data" data-muted>date-format depends on locale-data 0.8.2, which is deprecated.</li>
            <li data-edge data-source="test-runner" data-target="assert-kit" data-line="dashed">test-runner depends on assert-kit 4.0.0.</li>
            <li data-edge data-source="test-runner" data-target="mock-kit" data-line="dashed">test-runner depends on mock-kit 2.1.0.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label} {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="graph-legend">
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-2"></span> <span>Up to date</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-warn"></span> <span>Update available</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-danger"></span> <span>Security advisory</span></span>
        <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-muted"></span> <span>Deprecated</span></span>
        <span class="graph-key"><span class="graph-line graph-line--arrow"></span> <span>Depends on</span></span>
        <span class="graph-key"><span class="graph-line graph-line--dashed graph-line--arrow"></span> <span>Build only</span></span>
    </div>
</div>

Data lineage

Sources, staging, models, marts and reports, left to right with data-graph-curve="round-taxi". Each record carries two colourings: its layer as data-tone and its freshness as data-tone-freshness. Switch to Freshness and the failed load shows how far it reached — the two legends are both on screen, because a legend is markup and the switch does not rewrite it.

Last run today at 06:00
  • Orders database
  • Payments export
  • Web analytics
  • Returns feed
  • orders_clean
  • payments_clean
  • sessions_clean
  • returns_clean
  • Order facts
  • Customer dimension
  • Sessions by campaign
  • Sales mart
  • Marketing mart
  • Daily revenue
  • Returns report
  • Campaign performance
  • The orders database is loaded into orders_clean.
  • The payments export is loaded into payments_clean.
  • Web analytics events are loaded into sessions_clean.
  • The returns feed is loaded into returns_clean, and today's load failed.
  • orders_clean feeds order facts.
  • payments_clean feeds order facts.
  • returns_clean feeds order facts.
  • orders_clean feeds the customer dimension.
  • sessions_clean feeds sessions by campaign.
  • Order facts feed the sales mart.
  • The customer dimension feeds the sales mart.
  • The customer dimension feeds the marketing mart.
  • Sessions by campaign feed the marketing mart.
  • The sales mart feeds the daily revenue dashboard.
  • The sales mart feeds the returns report.
  • returns_clean feeds the returns report directly.
  • The marketing mart feeds the campaign performance report.

Source Staging Model Mart Report
Fresh Partial Failed or stale
<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="segmented segmented--sm" role="group" aria-label="Colour by">
            <label class="segmented-option"><input type="radio" name="lineage-colour" value="tone" data-graph-option="colour" checked /> <span>Layer</span></label>
            <label class="segmented-option"><input type="radio" name="lineage-colour" value="freshness" data-graph-option="colour" /> <span>Freshness</span></label>
        </div>
        <span class="toolbar-count">Last run today at 06:00</span>
    </div>
    <div class="graph card" data-graph id="lineage" data-graph-layout="dagre" data-graph-direction="LR" data-graph-nodes="box"
         data-graph-curve="round-taxi" data-graph-arrows="target" data-graph-edge-labels="none"
         aria-label="Data lineage from sources to reports" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="orders-db" data-kind="source" data-tone="muted" data-tone-freshness="go" data-icon="ri-database-2-line" data-meta="src-db-14 · live">Orders database</li>
            <li data-node="payments-export" data-kind="source" data-tone="muted" data-tone-freshness="go" data-icon="ri-file-list-3-line" data-meta="Daily file · 05:10">Payments export</li>
            <li data-node="web-events" data-kind="source" data-tone="muted" data-tone-freshness="go" data-icon="ri-radar-line" data-meta="Event stream · live">Web analytics</li>
            <li data-node="returns-feed" data-kind="source" data-tone="muted" data-tone-freshness="danger" data-icon="ri-file-damage-line" data-meta="Daily file · failed 05:40">Returns feed</li>

            <li data-node="orders-clean" data-kind="staging" data-tone="6" data-tone-freshness="go" data-icon="ri-table-line" data-meta="Refreshed 06:02">orders_clean</li>
            <li data-node="payments-clean" data-kind="staging" data-tone="6" data-tone-freshness="go" data-icon="ri-table-line" data-meta="Refreshed 06:03">payments_clean</li>
            <li data-node="sessions-clean" data-kind="staging" data-tone="6" data-tone-freshness="go" data-icon="ri-table-line" data-meta="Refreshed 06:05">sessions_clean</li>
            <li data-node="returns-clean" data-kind="staging" data-tone="6" data-tone-freshness="danger" data-icon="ri-table-line" data-meta="Not refreshed">returns_clean</li>

            <li data-node="order-facts" data-kind="model" data-tone="2" data-tone-freshness="warn" data-icon="ri-function-line" data-meta="Partial · no returns">Order facts</li>
            <li data-node="customers" data-kind="model" data-tone="2" data-tone-freshness="go" data-icon="ri-function-line" data-meta="Refreshed 06:09">Customer dimension</li>
            <li data-node="sessions" data-kind="model" data-tone="2" data-tone-freshness="go" data-icon="ri-function-line" data-meta="Refreshed 06:11">Sessions by campaign</li>

            <li data-node="sales-mart" data-kind="mart" data-tone="3" data-tone-freshness="warn" data-icon="ri-stack-line" data-meta="Partial">Sales mart</li>
            <li data-node="marketing-mart" data-kind="mart" data-tone="3" data-tone-freshness="go" data-icon="ri-stack-line" data-meta="Refreshed 06:14">Marketing mart</li>

            <li data-node="revenue-dashboard" data-kind="report" data-tone="5" data-tone-freshness="warn" data-icon="ri-dashboard-line" data-meta="Shows yesterday's returns">Daily revenue</li>
            <li data-node="returns-report" data-kind="report" data-tone="5" data-tone-freshness="danger" data-icon="ri-bar-chart-box-line" data-meta="Out of date">Returns report</li>
            <li data-node="campaign-report" data-kind="report" data-tone="5" data-tone-freshness="go" data-icon="ri-pie-chart-2-line" data-meta="Up to date">Campaign performance</li>

            <li data-edge data-source="orders-db" data-target="orders-clean">The orders database is loaded into orders_clean.</li>
            <li data-edge data-source="payments-export" data-target="payments-clean">The payments export is loaded into payments_clean.</li>
            <li data-edge data-source="web-events" data-target="sessions-clean">Web analytics events are loaded into sessions_clean.</li>
            <li data-edge data-source="returns-feed" data-target="returns-clean" data-tone="danger">The returns feed is loaded into returns_clean, and today's load failed.</li>
            <li data-edge data-source="orders-clean" data-target="order-facts">orders_clean feeds order facts.</li>
            <li data-edge data-source="payments-clean" data-target="order-facts">payments_clean feeds order facts.</li>
            <li data-edge data-source="returns-clean" data-target="order-facts" data-tone="danger">returns_clean feeds order facts.</li>
            <li data-edge data-source="orders-clean" data-target="customers">orders_clean feeds the customer dimension.</li>
            <li data-edge data-source="sessions-clean" data-target="sessions">sessions_clean feeds sessions by campaign.</li>
            <li data-edge data-source="order-facts" data-target="sales-mart">Order facts feed the sales mart.</li>
            <li data-edge data-source="customers" data-target="sales-mart">The customer dimension feeds the sales mart.</li>
            <li data-edge data-source="customers" data-target="marketing-mart">The customer dimension feeds the marketing mart.</li>
            <li data-edge data-source="sessions" data-target="marketing-mart">Sessions by campaign feed the marketing mart.</li>
            <li data-edge data-source="sales-mart" data-target="revenue-dashboard">The sales mart feeds the daily revenue dashboard.</li>
            <li data-edge data-source="sales-mart" data-target="returns-report">The sales mart feeds the returns report.</li>
            <li data-edge data-source="returns-clean" data-target="returns-report" data-tone="danger">returns_clean feeds the returns report directly.</li>
            <li data-edge data-source="marketing-mart" data-target="campaign-report">The marketing mart feeds the campaign performance report.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}, {kind}, {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="sedna-row-wrap">
        <div class="graph-legend" role="group" aria-label="Layers">
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-muted"></span> <span>Source</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-6"></span> <span>Staging</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-2"></span> <span>Model</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-3"></span> <span>Mart</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-5"></span> <span>Report</span></span>
        </div>
        <div class="graph-legend sedna-push" role="group" aria-label="Freshness">
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-go"></span> <span>Fresh</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-warn"></span> <span>Partial</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--rounded series-danger"></span> <span>Failed or stale</span></span>
        </div>
    </div>
</div>

A mind map

rings around the data-root topic, the branches weighted larger with data-weight and named in bold with data-hub, each branch in a tone its links repeat. data-graph-spacing="compact" keeps each branch's ideas close to it and leaves room between the branches for every name. Keep ideas short: a name that would run into another is left out until the reader zooms in.

Spring catalogue launch
  • Spring catalogue launch
  • Audience
  • Returning customers
  • Garden owners
  • Trade buyers
  • Channels
  • Printed catalogue
  • Newsletter
  • Web shop banner
  • In-store posters
  • Content
  • Product photos
  • Care guides
  • Price list
  • Timeline
  • Shoot in February
  • Print in March
  • Live on 1 April
  • Budget
  • Print run
  • Photography
  • Paid social
  • Risks
  • Paper prices
  • Late stock
  • Rain on the shoot day
  • The launch is aimed at an audience.
  • The launch goes out through channels.
  • The launch needs content.
  • The launch follows a timeline.
  • The launch has a budget.
  • The launch has risks.
  • One audience is returning customers.
  • One audience is garden owners.
  • One audience is trade buyers.
  • One channel is the printed catalogue.
  • One channel is the newsletter.
  • One channel is a web shop banner.
  • One channel is in-store posters.
  • The content includes product photos.
  • The content includes care guides.
  • The content includes a price list.
  • The photo shoot is in February.
  • The files go to the printer in March.
  • The catalogue is live on 1 April.
  • The budget covers the print run.
  • The budget covers photography.
  • The budget covers paid social.
  • One risk is paper prices.
  • One risk is late stock.
  • One risk is rain on the shoot day.
<div class="card">
    <div class="card-head">
        <strong>Spring catalogue launch</strong>
        <span class="form-hint" data-graph-for="mind-map" data-graph-stats="{nodes} ideas"></span>
    </div>
    <div class="graph graph--lg" data-graph id="mind-map" data-graph-layout="rings" data-graph-edge-labels="none"
         data-graph-spacing="compact" aria-label="Mind map of the spring catalogue launch" aria-roledescription="mind map">
        <ul class="graph-data" data-graph-data>
            <li data-node="launch" data-tone="1" data-icon="ri-lightbulb-flash-line" data-weight="14" data-root>Spring catalogue launch</li>

            <li data-node="audience" data-tone="2" data-icon="ri-group-line" data-weight="6" data-hub>Audience</li>
            <li data-node="returning" data-tone="2">Returning customers</li>
            <li data-node="gardeners" data-tone="2">Garden owners</li>
            <li data-node="trade" data-tone="2">Trade buyers</li>

            <li data-node="channels" data-tone="3" data-icon="ri-megaphone-line" data-weight="6" data-hub>Channels</li>
            <li data-node="print" data-tone="3">Printed catalogue</li>
            <li data-node="newsletter" data-tone="3">Newsletter</li>
            <li data-node="banner" data-tone="3">Web shop banner</li>
            <li data-node="posters" data-tone="3">In-store posters</li>

            <li data-node="content" data-tone="4" data-icon="ri-image-line" data-weight="6" data-hub>Content</li>
            <li data-node="photos" data-tone="4">Product photos</li>
            <li data-node="care-guides" data-tone="4">Care guides</li>
            <li data-node="price-list" data-tone="4">Price list</li>

            <li data-node="timeline" data-tone="5" data-icon="ri-calendar-event-line" data-weight="6" data-hub>Timeline</li>
            <li data-node="shoot" data-tone="5">Shoot in February</li>
            <li data-node="to-print" data-tone="5">Print in March</li>
            <li data-node="go-live" data-tone="5">Live on 1 April</li>

            <li data-node="budget" data-tone="6" data-icon="ri-coins-line" data-weight="6" data-hub>Budget</li>
            <li data-node="print-run" data-tone="6">Print run</li>
            <li data-node="photography" data-tone="6">Photography</li>
            <li data-node="paid-social" data-tone="6">Paid social</li>

            <li data-node="risks" data-tone="warn" data-icon="ri-alert-line" data-weight="6" data-hub>Risks</li>
            <li data-node="paper" data-tone="warn">Paper prices</li>
            <li data-node="late-stock" data-tone="warn">Late stock</li>
            <li data-node="weather" data-tone="warn">Rain on the shoot day</li>

            <li data-edge data-source="launch" data-target="audience" data-weight="heavy" data-tone="2">The launch is aimed at an audience.</li>
            <li data-edge data-source="launch" data-target="channels" data-weight="heavy" data-tone="3">The launch goes out through channels.</li>
            <li data-edge data-source="launch" data-target="content" data-weight="heavy" data-tone="4">The launch needs content.</li>
            <li data-edge data-source="launch" data-target="timeline" data-weight="heavy" data-tone="5">The launch follows a timeline.</li>
            <li data-edge data-source="launch" data-target="budget" data-weight="heavy" data-tone="6">The launch has a budget.</li>
            <li data-edge data-source="launch" data-target="risks" data-weight="heavy" data-tone="warn">The launch has risks.</li>
            <li data-edge data-source="audience" data-target="returning" data-tone="2">One audience is returning customers.</li>
            <li data-edge data-source="audience" data-target="gardeners" data-tone="2">One audience is garden owners.</li>
            <li data-edge data-source="audience" data-target="trade" data-tone="2">One audience is trade buyers.</li>
            <li data-edge data-source="channels" data-target="print" data-tone="3">One channel is the printed catalogue.</li>
            <li data-edge data-source="channels" data-target="newsletter" data-tone="3">One channel is the newsletter.</li>
            <li data-edge data-source="channels" data-target="banner" data-tone="3">One channel is a web shop banner.</li>
            <li data-edge data-source="channels" data-target="posters" data-tone="3">One channel is in-store posters.</li>
            <li data-edge data-source="content" data-target="photos" data-tone="4">The content includes product photos.</li>
            <li data-edge data-source="content" data-target="care-guides" data-tone="4">The content includes care guides.</li>
            <li data-edge data-source="content" data-target="price-list" data-tone="4">The content includes a price list.</li>
            <li data-edge data-source="timeline" data-target="shoot" data-tone="5">The photo shoot is in February.</li>
            <li data-edge data-source="timeline" data-target="to-print" data-tone="5">The files go to the printer in March.</li>
            <li data-edge data-source="timeline" data-target="go-live" data-tone="5">The catalogue is live on 1 April.</li>
            <li data-edge data-source="budget" data-target="print-run" data-tone="6">The budget covers the print run.</li>
            <li data-edge data-source="budget" data-target="photography" data-tone="6">The budget covers photography.</li>
            <li data-edge data-source="budget" data-target="paid-social" data-tone="6">The budget covers paid social.</li>
            <li data-edge data-source="risks" data-target="paper" data-tone="warn">One risk is paper prices.</li>
            <li data-edge data-source="risks" data-target="late-stock" data-tone="warn">One risk is late stock.</li>
            <li data-edge data-source="risks" data-target="weather" data-tone="warn">One risk is rain on the shoot day.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="export-png" data-graph-filename="spring-catalogue-launch" aria-label="Download as PNG" data-tip="Download as PNG"><i class="ri-image-line"></i></button>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
    </div>
</div>

The blast radius of an incident

The failing store is the root, and data-graph-focus with data-graph-focus-depth="2" starts on everything within two hops of it. The hop radios are data-graph-option="depth"; Whole map is data-graph-action="unfocus", and Back to the failure is a focus action with the record's id as its value. dagre puts the callers above what they call, so the failure is at the bottom and the damage climbs.

The stats line counts what is in view against the whole, in the app's words. It sits in the card's body rather than in the graph, and data-graph-frame on the card is what ties it and the controls to this graph.

Session store is down Since 09:12
  • Session store
  • Identity API
  • Basket service
  • Web shop
  • Mobile app API
  • Checkout API
  • Partner API
  • Admin console
  • Support desk
  • Accounts
  • Catalogue API
  • Recommendations
  • Pricing engine
  • Payments API
  • Orders API
  • Search index
  • Product database
  • Order database
  • Ledger
  • Order worker
  • Warehouse sync
  • Reporting
  • Newsletter
  • The identity API stores sessions in the session store.
  • The basket service keeps guest baskets in the session store.
  • The identity API reads users from the accounts store.
  • The web shop signs shoppers in through the identity API.
  • The web shop adds items to the basket service.
  • The web shop reads products from the catalogue API.
  • The web shop asks recommendations for suggestions.
  • The mobile app API signs shoppers in through the identity API.
  • The mobile app API adds items to the basket service.
  • The mobile app API reads products from the catalogue API.
  • The checkout API verifies the shopper with the identity API.
  • The checkout API reads the basket.
  • The checkout API prices the basket with the pricing engine.
  • The checkout API charges through the payments API.
  • The checkout API places orders with the orders API.
  • The partner API refreshes tokens with the identity API.
  • The partner API reads orders from the orders API.
  • The admin console signs staff in through the identity API.
  • The admin console edits products through the catalogue API.
  • The support desk signs staff in through the identity API.
  • The support desk looks orders up in the orders API.
  • Recommendations read products from the catalogue API.
  • The catalogue API queries the search index.
  • The catalogue API reads the product database.
  • The pricing engine reads the product database.
  • The payments API books into the ledger.
  • The orders API writes the order database.
  • The orders API queues orders for the order worker.
  • The order worker sends picking lists to warehouse sync.
  • Reporting reads the order database.
  • Reporting reads the ledger.
  • The newsletter reads addresses from the accounts store.

Down Failing because of it Healthy Data store Calls
<div class="card" data-graph-frame>
    <div class="card-head">
        <strong>Session store is down</strong>
        <span class="badge badge--danger">Since 09:12</span>
    </div>
    <div class="card-body">
        <div class="toolbar">
            <div class="toolbar-filters">
                <div class="segmented segmented--sm" role="group" aria-label="How far to follow the calls">
                    <label class="segmented-option"><input type="radio" name="blast-depth" value="1" data-graph-option="depth" /> <span>1 hop</span></label>
                    <label class="segmented-option"><input type="radio" name="blast-depth" value="2" data-graph-option="depth" checked /> <span>2 hops</span></label>
                    <label class="segmented-option"><input type="radio" name="blast-depth" value="3" data-graph-option="depth" /> <span>3 hops</span></label>
                </div>
                <span class="toolbar-count" data-graph-stats="{nodes} of {totalNodes} services in view"></span>
            </div>
            <div class="toolbar-actions">
                <button class="btn btn--sm" type="button" data-graph-action="unfocus"><i class="ri-apps-2-line"></i> <span>Whole map</span></button>
                <button class="btn btn--sm" type="button" data-graph-action="focus" value="session-store"><i class="ri-focus-3-line"></i> <span>Back to the failure</span></button>
            </div>
        </div>
    </div>
    <div class="graph graph--lg" data-graph id="blast-radius" data-graph-layout="dagre" data-graph-arrows="target"
         data-graph-focus="session-store" data-graph-focus-depth="2" data-graph-spacing="loose"
         aria-label="Services that depend on the session store" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="session-store" data-tone="danger" data-shape="square" data-icon="ri-database-2-line" data-meta="Down · connection refused" data-root>Session store</li>
            <li data-node="identity-api" data-tone="warn" data-icon="ri-key-2-line" data-meta="38 % of sign-ins fail">Identity API</li>
            <li data-node="basket" data-tone="warn" data-icon="ri-shopping-cart-2-line" data-meta="Guest baskets cannot be read">Basket service</li>
            <li data-node="web-shop" data-tone="warn" data-icon="ri-store-2-line" data-meta="Sign-in and basket errors">Web shop</li>
            <li data-node="mobile-api" data-tone="warn" data-icon="ri-smartphone-line" data-meta="Sign-in errors">Mobile app API</li>
            <li data-node="checkout-api" data-tone="warn" data-icon="ri-bank-card-line" data-meta="Checkout falls back to guest">Checkout API</li>
            <li data-node="partner-api" data-tone="warn" data-icon="ri-links-line" data-meta="Token refresh fails">Partner API</li>
            <li data-node="admin-console" data-tone="warn" data-icon="ri-settings-3-line" data-meta="Staff cannot sign in">Admin console</li>
            <li data-node="support-desk" data-tone="warn" data-icon="ri-customer-service-2-line" data-meta="Staff cannot sign in">Support desk</li>
            <li data-node="accounts" data-tone="go" data-shape="square" data-icon="ri-database-2-line" data-meta="Healthy">Accounts</li>
            <li data-node="catalogue-api" data-tone="go" data-icon="ri-server-line" data-meta="Healthy">Catalogue API</li>
            <li data-node="recommendations" data-tone="go" data-icon="ri-lightbulb-flash-line" data-meta="Healthy">Recommendations</li>
            <li data-node="pricing" data-tone="go" data-icon="ri-calculator-line" data-meta="Healthy">Pricing engine</li>
            <li data-node="payments-api" data-tone="go" data-icon="ri-bank-card-line" data-meta="Healthy">Payments API</li>
            <li data-node="orders-api" data-tone="go" data-icon="ri-server-line" data-meta="Healthy">Orders API</li>
            <li data-node="search-index" data-tone="go" data-shape="square" data-icon="ri-search-line" data-meta="Healthy">Search index</li>
            <li data-node="product-db" data-tone="go" data-shape="square" data-icon="ri-database-2-line" data-meta="Healthy">Product database</li>
            <li data-node="order-db" data-tone="go" data-shape="square" data-icon="ri-database-2-line" data-meta="Healthy">Order database</li>
            <li data-node="ledger" data-tone="go" data-shape="square" data-icon="ri-database-2-line" data-meta="Healthy">Ledger</li>
            <li data-node="order-worker" data-tone="go" data-icon="ri-loop-right-line" data-meta="Healthy">Order worker</li>
            <li data-node="warehouse-sync" data-tone="go" data-icon="ri-swap-line" data-meta="Healthy">Warehouse sync</li>
            <li data-node="reporting" data-tone="go" data-icon="ri-bar-chart-box-line" data-meta="Healthy">Reporting</li>
            <li data-node="newsletter" data-tone="go" data-icon="ri-mail-line" data-meta="Healthy">Newsletter</li>

            <li data-edge data-source="identity-api" data-target="session-store" data-tone="danger" data-label="stores sessions">The identity API stores sessions in the session store.</li>
            <li data-edge data-source="basket" data-target="session-store" data-tone="danger" data-label="stores guest baskets">The basket service keeps guest baskets in the session store.</li>
            <li data-edge data-source="identity-api" data-target="accounts" data-label="reads users">The identity API reads users from the accounts store.</li>
            <li data-edge data-source="web-shop" data-target="identity-api" data-tone="warn" data-label="signs in">The web shop signs shoppers in through the identity API.</li>
            <li data-edge data-source="web-shop" data-target="basket" data-tone="warn" data-label="adds to">The web shop adds items to the basket service.</li>
            <li data-edge data-source="web-shop" data-target="catalogue-api" data-label="reads">The web shop reads products from the catalogue API.</li>
            <li data-edge data-source="web-shop" data-target="recommendations" data-label="asks">The web shop asks recommendations for suggestions.</li>
            <li data-edge data-source="mobile-api" data-target="identity-api" data-tone="warn" data-label="signs in">The mobile app API signs shoppers in through the identity API.</li>
            <li data-edge data-source="mobile-api" data-target="basket" data-tone="warn" data-label="adds to">The mobile app API adds items to the basket service.</li>
            <li data-edge data-source="mobile-api" data-target="catalogue-api" data-label="reads">The mobile app API reads products from the catalogue API.</li>
            <li data-edge data-source="checkout-api" data-target="identity-api" data-tone="warn" data-label="verifies">The checkout API verifies the shopper with the identity API.</li>
            <li data-edge data-source="checkout-api" data-target="basket" data-tone="warn" data-label="reads">The checkout API reads the basket.</li>
            <li data-edge data-source="checkout-api" data-target="pricing" data-label="prices">The checkout API prices the basket with the pricing engine.</li>
            <li data-edge data-source="checkout-api" data-target="payments-api" data-label="charges">The checkout API charges through the payments API.</li>
            <li data-edge data-source="checkout-api" data-target="orders-api" data-label="places">The checkout API places orders with the orders API.</li>
            <li data-edge data-source="partner-api" data-target="identity-api" data-tone="warn" data-label="refreshes tokens">The partner API refreshes tokens with the identity API.</li>
            <li data-edge data-source="partner-api" data-target="orders-api" data-label="reads orders">The partner API reads orders from the orders API.</li>
            <li data-edge data-source="admin-console" data-target="identity-api" data-tone="warn" data-label="signs in">The admin console signs staff in through the identity API.</li>
            <li data-edge data-source="admin-console" data-target="catalogue-api" data-label="edits">The admin console edits products through the catalogue API.</li>
            <li data-edge data-source="support-desk" data-target="identity-api" data-tone="warn" data-label="signs in">The support desk signs staff in through the identity API.</li>
            <li data-edge data-source="support-desk" data-target="orders-api" data-label="looks up">The support desk looks orders up in the orders API.</li>
            <li data-edge data-source="recommendations" data-target="catalogue-api" data-label="reads">Recommendations read products from the catalogue API.</li>
            <li data-edge data-source="catalogue-api" data-target="search-index" data-label="queries">The catalogue API queries the search index.</li>
            <li data-edge data-source="catalogue-api" data-target="product-db" data-label="reads">The catalogue API reads the product database.</li>
            <li data-edge data-source="pricing" data-target="product-db" data-label="reads">The pricing engine reads the product database.</li>
            <li data-edge data-source="payments-api" data-target="ledger" data-label="books">The payments API books into the ledger.</li>
            <li data-edge data-source="orders-api" data-target="order-db" data-label="writes">The orders API writes the order database.</li>
            <li data-edge data-source="orders-api" data-target="order-worker" data-label="queues">The orders API queues orders for the order worker.</li>
            <li data-edge data-source="order-worker" data-target="warehouse-sync" data-label="sends">The order worker sends picking lists to warehouse sync.</li>
            <li data-edge data-source="reporting" data-target="order-db" data-label="reads">Reporting reads the order database.</li>
            <li data-edge data-source="reporting" data-target="ledger" data-label="reads">Reporting reads the ledger.</li>
            <li data-edge data-source="newsletter" data-target="accounts" data-label="reads">The newsletter reads addresses from the accounts store.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
        </div>
        <div class="graph-wait skeleton skeleton-block"></div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}: {meta}. {links} links in view." data-graph-announce-select="{label} selected."></p>
    </div>
    <div class="card-foot card-foot--start">
        <div class="graph-legend">
            <span class="graph-key"><span class="graph-swatch series-danger"></span> <span>Down</span></span>
            <span class="graph-key"><span class="graph-swatch series-warn"></span> <span>Failing because of it</span></span>
            <span class="graph-key"><span class="graph-swatch series-go"></span> <span>Healthy</span></span>
            <span class="graph-key"><span class="graph-swatch graph-swatch--square series-muted"></span> <span>Data store</span></span>
            <span class="graph-key"><span class="graph-line graph-line--arrow"></span> <span>Calls</span></span>
        </div>
    </div>
</div>

A large map

Every service at once, as islands: one per domain, each shaped by its own springs with the domain's record at the centre, and the domains of one data-cluster packed side by side. At this size the shape is the point, so names are placed the way a map places them — the domains first, the rest as zooming makes room. The minimap keeps the reader's place, and switching every platform off shows the app's own .graph-empty--filtered.

The records here are markup so the example stays one file. A real map of this size comes from data-graph-src, which the browser fetches itself, or from SetDataAsync; a list rendered by Blazor is held in the circuit and diffed on every change.

  • Domain 1
  • Service 1
  • Service 2
  • Service 3
  • Service 4
  • Service 5
  • Service 6
  • Service 7
  • Service 8
  • Service 9
  • Service 10
  • Service 11
  • Domain 2
  • Service 12
  • Service 13
  • Service 14
  • Service 15
  • Service 16
  • Service 17
  • Service 18
  • Service 19
  • Service 20
  • Service 21
  • Service 22
  • Domain 3
  • Service 23
  • Service 24
  • Service 25
  • Service 26
  • Service 27
  • Service 28
  • Service 29
  • Service 30
  • Service 31
  • Service 32
  • Domain 4
  • Service 33
  • Service 34
  • Service 35
  • Service 36
  • Service 37
  • Service 38
  • Service 39
  • Service 40
  • Service 41
  • Service 42
  • Service 43
  • Domain 5
  • Service 44
  • Service 45
  • Service 46
  • Service 47
  • Service 48
  • Service 49
  • Service 50
  • Service 51
  • Service 52
  • Service 53
  • Domain 6
  • Service 54
  • Service 55
  • Service 56
  • Service 57
  • Service 58
  • Service 59
  • Service 60
  • Service 61
  • Service 62
  • Domain 7
  • Service 63
  • Service 64
  • Service 65
  • Service 66
  • Service 67
  • Service 68
  • Service 69
  • Service 70
  • Service 71
  • Service 72
  • Domain 8
  • Service 73
  • Service 74
  • Service 75
  • Service 76
  • Service 77
  • Service 78
  • Service 79
  • Service 80
  • Service 81
  • Domain 9
  • Service 82
  • Service 83
  • Service 84
  • Service 85
  • Service 86
  • Service 87
  • Service 88
  • Service 89
  • Service 90
  • Service 91
  • Domain 10
  • Service 92
  • Service 93
  • Service 94
  • Service 95
  • Service 96
  • Service 97
  • Service 98
  • Service 99
  • Service 100
  • Domain 11
  • Service 101
  • Service 102
  • Service 103
  • Service 104
  • Service 105
  • Service 106
  • Service 107
  • Service 108
  • Service 109
  • Service 110
  • Domain 12
  • Service 111
  • Service 112
  • Service 113
  • Service 114
  • Service 115
  • Service 116
  • Service 117
  • Service 118
  • Service 119
  • Service 120
  • Domain 13
  • Service 121
  • Service 122
  • Service 123
  • Service 124
  • Service 125
  • Service 126
  • Service 127
  • Service 128
  • Service 129
  • Service 130
  • Service 131
  • Domain 1 exposes Service 1.
  • Domain 1 exposes Service 2.
  • Service 1 calls Service 3.
  • Service 2 calls Service 4.
  • Service 2 calls Service 5.
  • Service 5 calls Service 6.
  • Service 1 calls Service 7.
  • Service 3 calls Service 7.
  • Service 4 calls Service 8.
  • Service 5 calls Service 9.
  • Service 2 calls Service 9.
  • Service 8 calls Service 10.
  • Service 2 calls Service 10.
  • Service 7 calls Service 11.
  • Domain 2 exposes Service 12.
  • Domain 2 exposes Service 13.
  • Service 12 calls Service 14.
  • Service 13 calls Service 14.
  • Service 14 calls Service 15.
  • Service 12 calls Service 15.
  • Service 13 calls Service 16.
  • Service 15 calls Service 17.
  • Service 14 calls Service 18.
  • Service 18 calls Service 19.
  • Service 19 calls Service 20.
  • Service 12 calls Service 21.
  • Service 14 calls Service 22.
  • Domain 3 exposes Service 23.
  • Domain 3 exposes Service 24.
  • Service 23 calls Service 25.
  • Service 24 calls Service 26.
  • Service 25 calls Service 27.
  • Service 26 calls Service 28.
  • Service 25 calls Service 28.
  • Service 27 calls Service 29.
  • Service 28 calls Service 30.
  • Service 24 calls Service 30.
  • Service 25 calls Service 31.
  • Service 23 calls Service 32.
  • Domain 4 exposes Service 33.
  • Domain 4 exposes Service 34.
  • Service 33 calls Service 35.
  • Service 35 calls Service 36.
  • Service 34 calls Service 37.
  • Service 33 calls Service 38.
  • Service 37 calls Service 39.
  • Service 36 calls Service 40.
  • Service 38 calls Service 41.
  • Service 37 calls Service 42.
  • Service 37 calls Service 43.
  • Domain 5 exposes Service 44.
  • Domain 5 exposes Service 45.
  • Service 45 calls Service 46.
  • Service 44 calls Service 47.
  • Service 47 calls Service 48.
  • Service 44 calls Service 49.
  • Service 47 calls Service 49.
  • Service 46 calls Service 50.
  • Service 45 calls Service 51.
  • Service 49 calls Service 52.
  • Service 44 calls Service 53.
  • Domain 6 exposes Service 54.
  • Domain 6 exposes Service 55.
  • Service 55 calls Service 56.
  • Service 54 calls Service 57.
  • Service 56 calls Service 57.
  • Service 57 calls Service 58.
  • Service 57 calls Service 59.
  • Service 55 calls Service 59.
  • Service 55 calls Service 60.
  • Service 58 calls Service 60.
  • Service 54 calls Service 61.
  • Service 54 calls Service 62.
  • Service 56 calls Service 62.
  • Domain 7 exposes Service 63.
  • Domain 7 exposes Service 64.
  • Service 64 calls Service 65.
  • Service 63 calls Service 65.
  • Service 65 calls Service 66.
  • Service 63 calls Service 66.
  • Service 66 calls Service 67.
  • Service 63 calls Service 68.
  • Service 65 calls Service 69.
  • Service 65 calls Service 70.
  • Service 66 calls Service 70.
  • Service 70 calls Service 71.
  • Service 71 calls Service 72.
  • Domain 8 exposes Service 73.
  • Domain 8 exposes Service 74.
  • Service 73 calls Service 75.
  • Service 75 calls Service 76.
  • Service 75 calls Service 77.
  • Service 74 calls Service 78.
  • Service 78 calls Service 79.
  • Service 73 calls Service 79.
  • Service 75 calls Service 80.
  • Service 79 calls Service 81.
  • Domain 9 exposes Service 82.
  • Domain 9 exposes Service 83.
  • Service 82 calls Service 84.
  • Service 83 calls Service 85.
  • Service 83 calls Service 86.
  • Service 84 calls Service 86.
  • Service 85 calls Service 87.
  • Service 82 calls Service 88.
  • Service 87 calls Service 88.
  • Service 85 calls Service 89.
  • Service 85 calls Service 90.
  • Service 83 calls Service 91.
  • Service 84 calls Service 91.
  • Domain 10 exposes Service 92.
  • Domain 10 exposes Service 93.
  • Service 92 calls Service 94.
  • Service 93 calls Service 95.
  • Service 95 calls Service 96.
  • Service 95 calls Service 97.
  • Service 96 calls Service 98.
  • Service 94 calls Service 99.
  • Service 96 calls Service 100.
  • Domain 11 exposes Service 101.
  • Domain 11 exposes Service 102.
  • Service 101 calls Service 103.
  • Service 102 calls Service 104.
  • Service 102 calls Service 105.
  • Service 103 calls Service 105.
  • Service 105 calls Service 106.
  • Service 105 calls Service 107.
  • Service 107 calls Service 108.
  • Service 102 calls Service 108.
  • Service 107 calls Service 109.
  • Service 105 calls Service 110.
  • Domain 12 exposes Service 111.
  • Domain 12 exposes Service 112.
  • Service 112 calls Service 113.
  • Service 113 calls Service 114.
  • Service 112 calls Service 114.
  • Service 111 calls Service 115.
  • Service 115 calls Service 116.
  • Service 115 calls Service 117.
  • Service 114 calls Service 118.
  • Service 111 calls Service 118.
  • Service 115 calls Service 119.
  • Service 113 calls Service 120.
  • Domain 13 exposes Service 121.
  • Domain 13 exposes Service 122.
  • Service 122 calls Service 123.
  • Service 121 calls Service 123.
  • Service 123 calls Service 124.
  • Service 123 calls Service 125.
  • Service 122 calls Service 126.
  • Service 124 calls Service 127.
  • Service 127 calls Service 128.
  • Service 125 calls Service 129.
  • Service 125 calls Service 130.
  • Service 126 calls Service 131.
  • Service 82 calls Service 54.
  • Service 43 calls Service 121.
  • Service 66 calls Service 75.
  • Service 14 calls Service 46.
  • Service 114 calls Service 93.
  • Service 130 calls Service 94.
  • Service 95 calls Service 101.
  • Service 125 calls Service 111.
  • Service 35 calls Service 3.
  • Service 3 calls Service 24.
  • Service 54 calls Service 73.
  • Service 78 calls Service 63.
  • Service 45 calls Service 24.
  • Service 101 calls Service 73.
  • Service 17 calls Service 25.
  • Service 96 calls Service 112.
  • Service 57 calls Service 44.
  • Service 37 calls Service 23.
  • Service 36 calls Service 55.
  • Service 40 calls Service 2.
  • Service 102 calls Service 64.
  • Service 53 calls Service 33.
  • Service 20 calls Service 23.
  • Service 70 calls Service 94.
  • Service 69 calls Service 56.
  • Service 101 calls Service 93.
  • Service 5 calls Service 25.
  • Service 3 calls Service 25.
  • Service 110 calls Service 112.
  • Service 123 calls Service 24.
  • Service 33 calls Service 46.
  • Service 102 calls Service 82.
  • Service 124 calls Service 92.
  • Service 54 calls Service 64.
Every platform is switched off

<div class="graph-frame" data-graph-frame>
    <div class="toolbar">
        <div class="toolbar-filters">
            <div class="input-group toolbar-input">
                <span class="input-affix"><i class="ri-search-line"></i></span>
                <input class="form-input" type="search" placeholder="Find a service" aria-label="Find a service or a domain" data-graph-search />
            </div>
            <div class="chip-set" role="group" aria-label="Platforms">
            <button class="chip" type="button" data-graph-filter="cluster" value="platform-a" aria-pressed="true">Platform A</button>
            <button class="chip" type="button" data-graph-filter="cluster" value="platform-b" aria-pressed="true">Platform B</button>
            <button class="chip" type="button" data-graph-filter="cluster" value="platform-c" aria-pressed="true">Platform C</button>
            </div>
            <label class="form-check"><input type="checkbox" data-graph-show="muted" checked /> <span>Retired</span></label>
        </div>
        <span class="toolbar-count" data-graph-stats="{nodes} records · {edges} links" data-graph-stats-match="{matches} of {nodes} records match"></span>
    </div>
    <div class="graph graph--lg card" data-graph id="large-map" data-graph-layout="islands" data-graph-arrows="target"
         aria-label="Map of every service, in islands by domain" aria-roledescription="graph">
        <ul class="graph-data" data-graph-data>
            <li data-node="domain-1" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="11 services · Platform A">Domain 1</li>
            <li data-node="service-1" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 1</li>
            <li data-node="service-2" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 2</li>
            <li data-node="service-3" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 3</li>
            <li data-node="service-4" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 4</li>
            <li data-node="service-5" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 5</li>
            <li data-node="service-6" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 6</li>
            <li data-node="service-7" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 7</li>
            <li data-node="service-8" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 8</li>
            <li data-node="service-9" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1 · retired" data-muted>Service 9</li>
            <li data-node="service-10" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 10</li>
            <li data-node="service-11" data-group="domain-1" data-cluster="platform-a" data-tone="1" data-meta="Domain 1">Service 11</li>
            <li data-node="domain-2" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="11 services · Platform A">Domain 2</li>
            <li data-node="service-12" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 12</li>
            <li data-node="service-13" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 13</li>
            <li data-node="service-14" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 14</li>
            <li data-node="service-15" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 15</li>
            <li data-node="service-16" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 16</li>
            <li data-node="service-17" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 17</li>
            <li data-node="service-18" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 18</li>
            <li data-node="service-19" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 19</li>
            <li data-node="service-20" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 20</li>
            <li data-node="service-21" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 21</li>
            <li data-node="service-22" data-group="domain-2" data-cluster="platform-a" data-tone="2" data-meta="Domain 2">Service 22</li>
            <li data-node="domain-3" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="10 services · Platform A">Domain 3</li>
            <li data-node="service-23" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 23</li>
            <li data-node="service-24" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 24</li>
            <li data-node="service-25" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 25</li>
            <li data-node="service-26" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 26</li>
            <li data-node="service-27" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 27</li>
            <li data-node="service-28" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 28</li>
            <li data-node="service-29" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 29</li>
            <li data-node="service-30" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 30</li>
            <li data-node="service-31" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 31</li>
            <li data-node="service-32" data-group="domain-3" data-cluster="platform-a" data-tone="3" data-meta="Domain 3">Service 32</li>
            <li data-node="domain-4" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="11 services · Platform A">Domain 4</li>
            <li data-node="service-33" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 33</li>
            <li data-node="service-34" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 34</li>
            <li data-node="service-35" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 35</li>
            <li data-node="service-36" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 36</li>
            <li data-node="service-37" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 37</li>
            <li data-node="service-38" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 38</li>
            <li data-node="service-39" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 39</li>
            <li data-node="service-40" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4 · retired" data-muted>Service 40</li>
            <li data-node="service-41" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 41</li>
            <li data-node="service-42" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4 · retired" data-muted>Service 42</li>
            <li data-node="service-43" data-group="domain-4" data-cluster="platform-a" data-tone="4" data-meta="Domain 4">Service 43</li>
            <li data-node="domain-5" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="10 services · Platform A">Domain 5</li>
            <li data-node="service-44" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 44</li>
            <li data-node="service-45" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 45</li>
            <li data-node="service-46" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 46</li>
            <li data-node="service-47" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 47</li>
            <li data-node="service-48" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 48</li>
            <li data-node="service-49" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 49</li>
            <li data-node="service-50" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 50</li>
            <li data-node="service-51" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 51</li>
            <li data-node="service-52" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 52</li>
            <li data-node="service-53" data-group="domain-5" data-cluster="platform-a" data-tone="5" data-meta="Domain 5">Service 53</li>
            <li data-node="domain-6" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="9 services · Platform B">Domain 6</li>
            <li data-node="service-54" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 54</li>
            <li data-node="service-55" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 55</li>
            <li data-node="service-56" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 56</li>
            <li data-node="service-57" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 57</li>
            <li data-node="service-58" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 58</li>
            <li data-node="service-59" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 59</li>
            <li data-node="service-60" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 60</li>
            <li data-node="service-61" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 61</li>
            <li data-node="service-62" data-group="domain-6" data-cluster="platform-b" data-tone="6" data-meta="Domain 6">Service 62</li>
            <li data-node="domain-7" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="10 services · Platform B">Domain 7</li>
            <li data-node="service-63" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 63</li>
            <li data-node="service-64" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 64</li>
            <li data-node="service-65" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 65</li>
            <li data-node="service-66" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 66</li>
            <li data-node="service-67" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 67</li>
            <li data-node="service-68" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 68</li>
            <li data-node="service-69" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 69</li>
            <li data-node="service-70" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 70</li>
            <li data-node="service-71" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 71</li>
            <li data-node="service-72" data-group="domain-7" data-cluster="platform-b" data-tone="1" data-meta="Domain 7">Service 72</li>
            <li data-node="domain-8" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="9 services · Platform B">Domain 8</li>
            <li data-node="service-73" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 73</li>
            <li data-node="service-74" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 74</li>
            <li data-node="service-75" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 75</li>
            <li data-node="service-76" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 76</li>
            <li data-node="service-77" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 77</li>
            <li data-node="service-78" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 78</li>
            <li data-node="service-79" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8 · retired" data-muted>Service 79</li>
            <li data-node="service-80" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8">Service 80</li>
            <li data-node="service-81" data-group="domain-8" data-cluster="platform-b" data-tone="2" data-meta="Domain 8 · retired" data-muted>Service 81</li>
            <li data-node="domain-9" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="10 services · Platform B">Domain 9</li>
            <li data-node="service-82" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 82</li>
            <li data-node="service-83" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 83</li>
            <li data-node="service-84" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 84</li>
            <li data-node="service-85" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 85</li>
            <li data-node="service-86" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 86</li>
            <li data-node="service-87" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 87</li>
            <li data-node="service-88" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9 · retired" data-muted>Service 88</li>
            <li data-node="service-89" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 89</li>
            <li data-node="service-90" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 90</li>
            <li data-node="service-91" data-group="domain-9" data-cluster="platform-b" data-tone="3" data-meta="Domain 9">Service 91</li>
            <li data-node="domain-10" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="9 services · Platform C">Domain 10</li>
            <li data-node="service-92" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 92</li>
            <li data-node="service-93" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 93</li>
            <li data-node="service-94" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 94</li>
            <li data-node="service-95" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 95</li>
            <li data-node="service-96" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 96</li>
            <li data-node="service-97" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 97</li>
            <li data-node="service-98" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 98</li>
            <li data-node="service-99" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 99</li>
            <li data-node="service-100" data-group="domain-10" data-cluster="platform-c" data-tone="4" data-meta="Domain 10">Service 100</li>
            <li data-node="domain-11" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="10 services · Platform C">Domain 11</li>
            <li data-node="service-101" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 101</li>
            <li data-node="service-102" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 102</li>
            <li data-node="service-103" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 103</li>
            <li data-node="service-104" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 104</li>
            <li data-node="service-105" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11 · retired" data-muted>Service 105</li>
            <li data-node="service-106" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 106</li>
            <li data-node="service-107" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11 · retired" data-muted>Service 107</li>
            <li data-node="service-108" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 108</li>
            <li data-node="service-109" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 109</li>
            <li data-node="service-110" data-group="domain-11" data-cluster="platform-c" data-tone="5" data-meta="Domain 11">Service 110</li>
            <li data-node="domain-12" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="10 services · Platform C">Domain 12</li>
            <li data-node="service-111" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 111</li>
            <li data-node="service-112" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 112</li>
            <li data-node="service-113" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 113</li>
            <li data-node="service-114" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 114</li>
            <li data-node="service-115" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 115</li>
            <li data-node="service-116" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 116</li>
            <li data-node="service-117" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 117</li>
            <li data-node="service-118" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 118</li>
            <li data-node="service-119" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 119</li>
            <li data-node="service-120" data-group="domain-12" data-cluster="platform-c" data-tone="6" data-meta="Domain 12">Service 120</li>
            <li data-node="domain-13" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="11 services · Platform C">Domain 13</li>
            <li data-node="service-121" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 121</li>
            <li data-node="service-122" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 122</li>
            <li data-node="service-123" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 123</li>
            <li data-node="service-124" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 124</li>
            <li data-node="service-125" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 125</li>
            <li data-node="service-126" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 126</li>
            <li data-node="service-127" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 127</li>
            <li data-node="service-128" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13 · retired" data-muted>Service 128</li>
            <li data-node="service-129" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 129</li>
            <li data-node="service-130" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 130</li>
            <li data-node="service-131" data-group="domain-13" data-cluster="platform-c" data-tone="1" data-meta="Domain 13">Service 131</li>

            <li data-edge data-source="domain-1" data-target="service-1" data-label="exposes" data-weight="heavy">Domain 1 exposes Service 1.</li>
            <li data-edge data-source="domain-1" data-target="service-2" data-label="exposes" data-weight="heavy">Domain 1 exposes Service 2.</li>
            <li data-edge data-source="service-1" data-target="service-3" data-label="calls">Service 1 calls Service 3.</li>
            <li data-edge data-source="service-2" data-target="service-4" data-label="calls">Service 2 calls Service 4.</li>
            <li data-edge data-source="service-2" data-target="service-5" data-label="calls">Service 2 calls Service 5.</li>
            <li data-edge data-source="service-5" data-target="service-6" data-label="calls">Service 5 calls Service 6.</li>
            <li data-edge data-source="service-1" data-target="service-7" data-label="calls">Service 1 calls Service 7.</li>
            <li data-edge data-source="service-3" data-target="service-7" data-label="calls">Service 3 calls Service 7.</li>
            <li data-edge data-source="service-4" data-target="service-8" data-label="calls">Service 4 calls Service 8.</li>
            <li data-edge data-source="service-5" data-target="service-9" data-label="calls">Service 5 calls Service 9.</li>
            <li data-edge data-source="service-2" data-target="service-9" data-label="calls">Service 2 calls Service 9.</li>
            <li data-edge data-source="service-8" data-target="service-10" data-label="calls">Service 8 calls Service 10.</li>
            <li data-edge data-source="service-2" data-target="service-10" data-label="calls">Service 2 calls Service 10.</li>
            <li data-edge data-source="service-7" data-target="service-11" data-label="calls">Service 7 calls Service 11.</li>
            <li data-edge data-source="domain-2" data-target="service-12" data-label="exposes" data-weight="heavy">Domain 2 exposes Service 12.</li>
            <li data-edge data-source="domain-2" data-target="service-13" data-label="exposes" data-weight="heavy">Domain 2 exposes Service 13.</li>
            <li data-edge data-source="service-12" data-target="service-14" data-label="calls">Service 12 calls Service 14.</li>
            <li data-edge data-source="service-13" data-target="service-14" data-label="calls">Service 13 calls Service 14.</li>
            <li data-edge data-source="service-14" data-target="service-15" data-label="calls">Service 14 calls Service 15.</li>
            <li data-edge data-source="service-12" data-target="service-15" data-label="calls">Service 12 calls Service 15.</li>
            <li data-edge data-source="service-13" data-target="service-16" data-label="calls">Service 13 calls Service 16.</li>
            <li data-edge data-source="service-15" data-target="service-17" data-label="calls">Service 15 calls Service 17.</li>
            <li data-edge data-source="service-14" data-target="service-18" data-label="calls">Service 14 calls Service 18.</li>
            <li data-edge data-source="service-18" data-target="service-19" data-label="calls">Service 18 calls Service 19.</li>
            <li data-edge data-source="service-19" data-target="service-20" data-label="calls">Service 19 calls Service 20.</li>
            <li data-edge data-source="service-12" data-target="service-21" data-label="calls">Service 12 calls Service 21.</li>
            <li data-edge data-source="service-14" data-target="service-22" data-label="calls">Service 14 calls Service 22.</li>
            <li data-edge data-source="domain-3" data-target="service-23" data-label="exposes" data-weight="heavy">Domain 3 exposes Service 23.</li>
            <li data-edge data-source="domain-3" data-target="service-24" data-label="exposes" data-weight="heavy">Domain 3 exposes Service 24.</li>
            <li data-edge data-source="service-23" data-target="service-25" data-label="calls">Service 23 calls Service 25.</li>
            <li data-edge data-source="service-24" data-target="service-26" data-label="calls">Service 24 calls Service 26.</li>
            <li data-edge data-source="service-25" data-target="service-27" data-label="calls">Service 25 calls Service 27.</li>
            <li data-edge data-source="service-26" data-target="service-28" data-label="calls">Service 26 calls Service 28.</li>
            <li data-edge data-source="service-25" data-target="service-28" data-label="calls">Service 25 calls Service 28.</li>
            <li data-edge data-source="service-27" data-target="service-29" data-label="calls">Service 27 calls Service 29.</li>
            <li data-edge data-source="service-28" data-target="service-30" data-label="calls">Service 28 calls Service 30.</li>
            <li data-edge data-source="service-24" data-target="service-30" data-label="calls">Service 24 calls Service 30.</li>
            <li data-edge data-source="service-25" data-target="service-31" data-label="calls">Service 25 calls Service 31.</li>
            <li data-edge data-source="service-23" data-target="service-32" data-label="calls">Service 23 calls Service 32.</li>
            <li data-edge data-source="domain-4" data-target="service-33" data-label="exposes" data-weight="heavy">Domain 4 exposes Service 33.</li>
            <li data-edge data-source="domain-4" data-target="service-34" data-label="exposes" data-weight="heavy">Domain 4 exposes Service 34.</li>
            <li data-edge data-source="service-33" data-target="service-35" data-label="calls">Service 33 calls Service 35.</li>
            <li data-edge data-source="service-35" data-target="service-36" data-label="calls">Service 35 calls Service 36.</li>
            <li data-edge data-source="service-34" data-target="service-37" data-label="calls">Service 34 calls Service 37.</li>
            <li data-edge data-source="service-33" data-target="service-38" data-label="calls">Service 33 calls Service 38.</li>
            <li data-edge data-source="service-37" data-target="service-39" data-label="calls">Service 37 calls Service 39.</li>
            <li data-edge data-source="service-36" data-target="service-40" data-label="calls">Service 36 calls Service 40.</li>
            <li data-edge data-source="service-38" data-target="service-41" data-label="calls">Service 38 calls Service 41.</li>
            <li data-edge data-source="service-37" data-target="service-42" data-label="calls">Service 37 calls Service 42.</li>
            <li data-edge data-source="service-37" data-target="service-43" data-label="calls">Service 37 calls Service 43.</li>
            <li data-edge data-source="domain-5" data-target="service-44" data-label="exposes" data-weight="heavy">Domain 5 exposes Service 44.</li>
            <li data-edge data-source="domain-5" data-target="service-45" data-label="exposes" data-weight="heavy">Domain 5 exposes Service 45.</li>
            <li data-edge data-source="service-45" data-target="service-46" data-label="calls">Service 45 calls Service 46.</li>
            <li data-edge data-source="service-44" data-target="service-47" data-label="calls">Service 44 calls Service 47.</li>
            <li data-edge data-source="service-47" data-target="service-48" data-label="calls">Service 47 calls Service 48.</li>
            <li data-edge data-source="service-44" data-target="service-49" data-label="calls">Service 44 calls Service 49.</li>
            <li data-edge data-source="service-47" data-target="service-49" data-label="calls">Service 47 calls Service 49.</li>
            <li data-edge data-source="service-46" data-target="service-50" data-label="calls">Service 46 calls Service 50.</li>
            <li data-edge data-source="service-45" data-target="service-51" data-label="calls">Service 45 calls Service 51.</li>
            <li data-edge data-source="service-49" data-target="service-52" data-label="calls">Service 49 calls Service 52.</li>
            <li data-edge data-source="service-44" data-target="service-53" data-label="calls">Service 44 calls Service 53.</li>
            <li data-edge data-source="domain-6" data-target="service-54" data-label="exposes" data-weight="heavy">Domain 6 exposes Service 54.</li>
            <li data-edge data-source="domain-6" data-target="service-55" data-label="exposes" data-weight="heavy">Domain 6 exposes Service 55.</li>
            <li data-edge data-source="service-55" data-target="service-56" data-label="calls">Service 55 calls Service 56.</li>
            <li data-edge data-source="service-54" data-target="service-57" data-label="calls">Service 54 calls Service 57.</li>
            <li data-edge data-source="service-56" data-target="service-57" data-label="calls">Service 56 calls Service 57.</li>
            <li data-edge data-source="service-57" data-target="service-58" data-label="calls">Service 57 calls Service 58.</li>
            <li data-edge data-source="service-57" data-target="service-59" data-label="calls">Service 57 calls Service 59.</li>
            <li data-edge data-source="service-55" data-target="service-59" data-label="calls">Service 55 calls Service 59.</li>
            <li data-edge data-source="service-55" data-target="service-60" data-label="calls">Service 55 calls Service 60.</li>
            <li data-edge data-source="service-58" data-target="service-60" data-label="calls">Service 58 calls Service 60.</li>
            <li data-edge data-source="service-54" data-target="service-61" data-label="calls">Service 54 calls Service 61.</li>
            <li data-edge data-source="service-54" data-target="service-62" data-label="calls">Service 54 calls Service 62.</li>
            <li data-edge data-source="service-56" data-target="service-62" data-label="calls">Service 56 calls Service 62.</li>
            <li data-edge data-source="domain-7" data-target="service-63" data-label="exposes" data-weight="heavy">Domain 7 exposes Service 63.</li>
            <li data-edge data-source="domain-7" data-target="service-64" data-label="exposes" data-weight="heavy">Domain 7 exposes Service 64.</li>
            <li data-edge data-source="service-64" data-target="service-65" data-label="calls">Service 64 calls Service 65.</li>
            <li data-edge data-source="service-63" data-target="service-65" data-label="calls">Service 63 calls Service 65.</li>
            <li data-edge data-source="service-65" data-target="service-66" data-label="calls">Service 65 calls Service 66.</li>
            <li data-edge data-source="service-63" data-target="service-66" data-label="calls">Service 63 calls Service 66.</li>
            <li data-edge data-source="service-66" data-target="service-67" data-label="calls">Service 66 calls Service 67.</li>
            <li data-edge data-source="service-63" data-target="service-68" data-label="calls">Service 63 calls Service 68.</li>
            <li data-edge data-source="service-65" data-target="service-69" data-label="calls">Service 65 calls Service 69.</li>
            <li data-edge data-source="service-65" data-target="service-70" data-label="calls">Service 65 calls Service 70.</li>
            <li data-edge data-source="service-66" data-target="service-70" data-label="calls">Service 66 calls Service 70.</li>
            <li data-edge data-source="service-70" data-target="service-71" data-label="calls">Service 70 calls Service 71.</li>
            <li data-edge data-source="service-71" data-target="service-72" data-label="calls">Service 71 calls Service 72.</li>
            <li data-edge data-source="domain-8" data-target="service-73" data-label="exposes" data-weight="heavy">Domain 8 exposes Service 73.</li>
            <li data-edge data-source="domain-8" data-target="service-74" data-label="exposes" data-weight="heavy">Domain 8 exposes Service 74.</li>
            <li data-edge data-source="service-73" data-target="service-75" data-label="calls">Service 73 calls Service 75.</li>
            <li data-edge data-source="service-75" data-target="service-76" data-label="calls">Service 75 calls Service 76.</li>
            <li data-edge data-source="service-75" data-target="service-77" data-label="calls">Service 75 calls Service 77.</li>
            <li data-edge data-source="service-74" data-target="service-78" data-label="calls">Service 74 calls Service 78.</li>
            <li data-edge data-source="service-78" data-target="service-79" data-label="calls">Service 78 calls Service 79.</li>
            <li data-edge data-source="service-73" data-target="service-79" data-label="calls">Service 73 calls Service 79.</li>
            <li data-edge data-source="service-75" data-target="service-80" data-label="calls">Service 75 calls Service 80.</li>
            <li data-edge data-source="service-79" data-target="service-81" data-label="calls">Service 79 calls Service 81.</li>
            <li data-edge data-source="domain-9" data-target="service-82" data-label="exposes" data-weight="heavy">Domain 9 exposes Service 82.</li>
            <li data-edge data-source="domain-9" data-target="service-83" data-label="exposes" data-weight="heavy">Domain 9 exposes Service 83.</li>
            <li data-edge data-source="service-82" data-target="service-84" data-label="calls">Service 82 calls Service 84.</li>
            <li data-edge data-source="service-83" data-target="service-85" data-label="calls">Service 83 calls Service 85.</li>
            <li data-edge data-source="service-83" data-target="service-86" data-label="calls">Service 83 calls Service 86.</li>
            <li data-edge data-source="service-84" data-target="service-86" data-label="calls">Service 84 calls Service 86.</li>
            <li data-edge data-source="service-85" data-target="service-87" data-label="calls">Service 85 calls Service 87.</li>
            <li data-edge data-source="service-82" data-target="service-88" data-label="calls">Service 82 calls Service 88.</li>
            <li data-edge data-source="service-87" data-target="service-88" data-label="calls">Service 87 calls Service 88.</li>
            <li data-edge data-source="service-85" data-target="service-89" data-label="calls">Service 85 calls Service 89.</li>
            <li data-edge data-source="service-85" data-target="service-90" data-label="calls">Service 85 calls Service 90.</li>
            <li data-edge data-source="service-83" data-target="service-91" data-label="calls">Service 83 calls Service 91.</li>
            <li data-edge data-source="service-84" data-target="service-91" data-label="calls">Service 84 calls Service 91.</li>
            <li data-edge data-source="domain-10" data-target="service-92" data-label="exposes" data-weight="heavy">Domain 10 exposes Service 92.</li>
            <li data-edge data-source="domain-10" data-target="service-93" data-label="exposes" data-weight="heavy">Domain 10 exposes Service 93.</li>
            <li data-edge data-source="service-92" data-target="service-94" data-label="calls">Service 92 calls Service 94.</li>
            <li data-edge data-source="service-93" data-target="service-95" data-label="calls">Service 93 calls Service 95.</li>
            <li data-edge data-source="service-95" data-target="service-96" data-label="calls">Service 95 calls Service 96.</li>
            <li data-edge data-source="service-95" data-target="service-97" data-label="calls">Service 95 calls Service 97.</li>
            <li data-edge data-source="service-96" data-target="service-98" data-label="calls">Service 96 calls Service 98.</li>
            <li data-edge data-source="service-94" data-target="service-99" data-label="calls">Service 94 calls Service 99.</li>
            <li data-edge data-source="service-96" data-target="service-100" data-label="calls">Service 96 calls Service 100.</li>
            <li data-edge data-source="domain-11" data-target="service-101" data-label="exposes" data-weight="heavy">Domain 11 exposes Service 101.</li>
            <li data-edge data-source="domain-11" data-target="service-102" data-label="exposes" data-weight="heavy">Domain 11 exposes Service 102.</li>
            <li data-edge data-source="service-101" data-target="service-103" data-label="calls">Service 101 calls Service 103.</li>
            <li data-edge data-source="service-102" data-target="service-104" data-label="calls">Service 102 calls Service 104.</li>
            <li data-edge data-source="service-102" data-target="service-105" data-label="calls">Service 102 calls Service 105.</li>
            <li data-edge data-source="service-103" data-target="service-105" data-label="calls">Service 103 calls Service 105.</li>
            <li data-edge data-source="service-105" data-target="service-106" data-label="calls">Service 105 calls Service 106.</li>
            <li data-edge data-source="service-105" data-target="service-107" data-label="calls">Service 105 calls Service 107.</li>
            <li data-edge data-source="service-107" data-target="service-108" data-label="calls">Service 107 calls Service 108.</li>
            <li data-edge data-source="service-102" data-target="service-108" data-label="calls">Service 102 calls Service 108.</li>
            <li data-edge data-source="service-107" data-target="service-109" data-label="calls">Service 107 calls Service 109.</li>
            <li data-edge data-source="service-105" data-target="service-110" data-label="calls">Service 105 calls Service 110.</li>
            <li data-edge data-source="domain-12" data-target="service-111" data-label="exposes" data-weight="heavy">Domain 12 exposes Service 111.</li>
            <li data-edge data-source="domain-12" data-target="service-112" data-label="exposes" data-weight="heavy">Domain 12 exposes Service 112.</li>
            <li data-edge data-source="service-112" data-target="service-113" data-label="calls">Service 112 calls Service 113.</li>
            <li data-edge data-source="service-113" data-target="service-114" data-label="calls">Service 113 calls Service 114.</li>
            <li data-edge data-source="service-112" data-target="service-114" data-label="calls">Service 112 calls Service 114.</li>
            <li data-edge data-source="service-111" data-target="service-115" data-label="calls">Service 111 calls Service 115.</li>
            <li data-edge data-source="service-115" data-target="service-116" data-label="calls">Service 115 calls Service 116.</li>
            <li data-edge data-source="service-115" data-target="service-117" data-label="calls">Service 115 calls Service 117.</li>
            <li data-edge data-source="service-114" data-target="service-118" data-label="calls">Service 114 calls Service 118.</li>
            <li data-edge data-source="service-111" data-target="service-118" data-label="calls">Service 111 calls Service 118.</li>
            <li data-edge data-source="service-115" data-target="service-119" data-label="calls">Service 115 calls Service 119.</li>
            <li data-edge data-source="service-113" data-target="service-120" data-label="calls">Service 113 calls Service 120.</li>
            <li data-edge data-source="domain-13" data-target="service-121" data-label="exposes" data-weight="heavy">Domain 13 exposes Service 121.</li>
            <li data-edge data-source="domain-13" data-target="service-122" data-label="exposes" data-weight="heavy">Domain 13 exposes Service 122.</li>
            <li data-edge data-source="service-122" data-target="service-123" data-label="calls">Service 122 calls Service 123.</li>
            <li data-edge data-source="service-121" data-target="service-123" data-label="calls">Service 121 calls Service 123.</li>
            <li data-edge data-source="service-123" data-target="service-124" data-label="calls">Service 123 calls Service 124.</li>
            <li data-edge data-source="service-123" data-target="service-125" data-label="calls">Service 123 calls Service 125.</li>
            <li data-edge data-source="service-122" data-target="service-126" data-label="calls">Service 122 calls Service 126.</li>
            <li data-edge data-source="service-124" data-target="service-127" data-label="calls">Service 124 calls Service 127.</li>
            <li data-edge data-source="service-127" data-target="service-128" data-label="calls">Service 127 calls Service 128.</li>
            <li data-edge data-source="service-125" data-target="service-129" data-label="calls">Service 125 calls Service 129.</li>
            <li data-edge data-source="service-125" data-target="service-130" data-label="calls">Service 125 calls Service 130.</li>
            <li data-edge data-source="service-126" data-target="service-131" data-label="calls">Service 126 calls Service 131.</li>
            <li data-edge data-source="service-82" data-target="service-54" data-label="calls">Service 82 calls Service 54.</li>
            <li data-edge data-source="service-43" data-target="service-121" data-label="calls">Service 43 calls Service 121.</li>
            <li data-edge data-source="service-66" data-target="service-75" data-label="calls">Service 66 calls Service 75.</li>
            <li data-edge data-source="service-14" data-target="service-46" data-label="calls">Service 14 calls Service 46.</li>
            <li data-edge data-source="service-114" data-target="service-93" data-label="calls">Service 114 calls Service 93.</li>
            <li data-edge data-source="service-130" data-target="service-94" data-label="calls">Service 130 calls Service 94.</li>
            <li data-edge data-source="service-95" data-target="service-101" data-label="calls">Service 95 calls Service 101.</li>
            <li data-edge data-source="service-125" data-target="service-111" data-label="calls">Service 125 calls Service 111.</li>
            <li data-edge data-source="service-35" data-target="service-3" data-label="calls">Service 35 calls Service 3.</li>
            <li data-edge data-source="service-3" data-target="service-24" data-label="calls">Service 3 calls Service 24.</li>
            <li data-edge data-source="service-54" data-target="service-73" data-label="calls">Service 54 calls Service 73.</li>
            <li data-edge data-source="service-78" data-target="service-63" data-label="calls">Service 78 calls Service 63.</li>
            <li data-edge data-source="service-45" data-target="service-24" data-label="calls">Service 45 calls Service 24.</li>
            <li data-edge data-source="service-101" data-target="service-73" data-label="calls">Service 101 calls Service 73.</li>
            <li data-edge data-source="service-17" data-target="service-25" data-label="calls">Service 17 calls Service 25.</li>
            <li data-edge data-source="service-96" data-target="service-112" data-label="calls">Service 96 calls Service 112.</li>
            <li data-edge data-source="service-57" data-target="service-44" data-label="calls">Service 57 calls Service 44.</li>
            <li data-edge data-source="service-37" data-target="service-23" data-label="calls">Service 37 calls Service 23.</li>
            <li data-edge data-source="service-36" data-target="service-55" data-label="calls">Service 36 calls Service 55.</li>
            <li data-edge data-source="service-40" data-target="service-2" data-label="calls">Service 40 calls Service 2.</li>
            <li data-edge data-source="service-102" data-target="service-64" data-label="calls">Service 102 calls Service 64.</li>
            <li data-edge data-source="service-53" data-target="service-33" data-label="calls">Service 53 calls Service 33.</li>
            <li data-edge data-source="service-20" data-target="service-23" data-label="calls">Service 20 calls Service 23.</li>
            <li data-edge data-source="service-70" data-target="service-94" data-label="calls">Service 70 calls Service 94.</li>
            <li data-edge data-source="service-69" data-target="service-56" data-label="calls">Service 69 calls Service 56.</li>
            <li data-edge data-source="service-101" data-target="service-93" data-label="calls">Service 101 calls Service 93.</li>
            <li data-edge data-source="service-5" data-target="service-25" data-label="calls">Service 5 calls Service 25.</li>
            <li data-edge data-source="service-3" data-target="service-25" data-label="calls">Service 3 calls Service 25.</li>
            <li data-edge data-source="service-110" data-target="service-112" data-label="calls">Service 110 calls Service 112.</li>
            <li data-edge data-source="service-123" data-target="service-24" data-label="calls">Service 123 calls Service 24.</li>
            <li data-edge data-source="service-33" data-target="service-46" data-label="calls">Service 33 calls Service 46.</li>
            <li data-edge data-source="service-102" data-target="service-82" data-label="calls">Service 102 calls Service 82.</li>
            <li data-edge data-source="service-124" data-target="service-92" data-label="calls">Service 124 calls Service 92.</li>
            <li data-edge data-source="service-54" data-target="service-64" data-label="calls">Service 54 calls Service 64.</li>
        </ul>
        <div class="graph-canvas"></div>
        <div class="graph-tools" role="toolbar" aria-label="View">
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-in" aria-label="Zoom in" data-tip="Zoom in"><i class="ri-zoom-in-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="zoom-out" aria-label="Zoom out" data-tip="Zoom out"><i class="ri-zoom-out-line"></i></button>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fit" aria-label="Fit to the frame" data-tip="Fit to the frame"><i class="ri-focus-3-line"></i></button>
            <span class="graph-tools-sep"></span>
            <button class="btn btn--ghost btn--sm btn--icon" type="button" data-graph-action="fullscreen" aria-pressed="false" aria-label="Full screen" data-tip="Full screen">
                <i class="ri-fullscreen-line graph-when-off"></i><i class="ri-fullscreen-exit-line graph-when-on"></i>
            </button>
        </div>
        <canvas class="graph-minimap" data-graph-minimap aria-hidden="true"></canvas>
        <div class="graph-wait skeleton skeleton-block"></div>
        <div class="graph-empty graph-empty--filtered empty-state">
            <svg class="state-art" aria-hidden="true"><use href="#filtered-out" /></svg>
            <span class="empty-state-title">Every platform is switched off</span>
            <button class="btn btn--sm" type="button" data-graph-action="reset"><i class="ri-restart-line"></i> <span>Show every platform</span></button>
        </div>
        <p class="visually-hidden" data-graph-live aria-live="polite"
           data-graph-announce="{label}, {meta}. {links} links." data-graph-announce-select="{label} selected."></p>
    </div>
</div>

Which one to start from

The jobLayoutRecordsAround it
Who reports to whomdagre, taxiBoxesSearch, legend, export
What calls what, and what is brokenislands, hullsDotsTeam chips, colour switch, tooltip
What is inside whatfcose, data-parentDotsFold buttons, search by address
How things relate, to exploreislandsDotsKind chips, search, side panel, menu
How something moves between statesdagre acrossBoxes, labelled linksLegend
How far a run has gotdagre acrossBoxes, data-stateTwo legends, full screen
What depends on whatdagreBoxesDirection, deprecated, chips
Where data comes fromdagre across, round-taxiBoxesColour switch, two legends
One topic and its ideasringsDotsNothing
What one failure reachesdagre, a focusDotsDepth, whole map, stats
Everything at onceislands, clustersDotsMinimap, search, chips, full screen