Embed contract: data-* attributes and driver API
This page is the reference for the stable surface a host depends on. If you are starting out, read the task-oriented Embedding guide first. It explains which output to produce and how to size, theme and drive a map. Come back here for the exact attribute vocabulary and driver method signatures.
An nf-metro SVG is a self-describing, driveable artifact. A host page can:
- Inline the SVG (or load it via
<img>/<object>). - Load one driver script.
- Call a documented API to highlight lines, select nodes by process pattern, or read the embedded manifest without touching internals.
The contract has two halves: the data-* attributes carried by the SVG and
the driver API a host uses to manipulate it. Both are documented below. The
Data manifest page covers the manifest format (nodes,
groups, regions and overlays) in more depth.
data-* attribute contract
Section titled “data-* attribute contract”Every rendered SVG carries two sets of attributes.
Interactive set
Section titled “Interactive set”The driver consumes these attributes, and they are the stable addresses for CSS-level interaction:
| Attribute | Element | Value |
|---|---|---|
data-station-id | Station marker <rect>/<circle> and associated label/icon <g> | The station’s stable id (matches node.id in the manifest). |
data-station-lines | Station marker element only | Comma-separated list of line ids passing through the station. |
data-station-label | Station marker element only | Human-readable label (HTML-escaped). |
data-section-id | Section box and associated label <g> | The section’s stable id (matches region.id in the manifest). |
data-section-name | Station marker elements within a section | Human-readable section name (HTML-escaped). |
data-section-lines | Section box element only | Comma-separated list of line ids present in the section. |
data-line-id | Edge path elements | The id of the line this edge belongs to. |
Querying examples:
// All station markers for a specific station id:svg.querySelectorAll('[data-station-id="align"]');
// All edges belonging to a line:svg.querySelectorAll('[data-line-id="star_salmon"]');
// All section boxes that include a given line:svg.querySelectorAll("[data-section-lines]").forEach((el) => { const lines = el.getAttribute("data-section-lines").split(","); if (lines.includes("star_salmon")) { /* ... */ }});Manifest set
Section titled “Manifest set”A second set carries the coordinate and pattern data that overlays need:
data-node-id, data-node-cx/-cy/-r, data-node-groups and
data-node-region. The manifest system writes them, and they are specified in
full under Per-node attributes on the
Data manifest page.
Both sets join on the station id (data-station-id = data-node-id =
node.id in the manifest JSON).
Driver API
Section titled “Driver API”Obtaining the driver
Section titled “Obtaining the driver”Option A: embed the HTML output. This is the simplest route. nf-metro render --format html produces a self-contained interactive page with the
driver already inlined. Copy the inline snippet from the Embed modal and paste
it into any host page.
Option B: load the driver separately. Export the driver script and load it alongside the SVG:
nf-metro embed-script -o nf-metro-embed.jsThen on the host page:
<!-- 1. Inline the SVG (must contain data-* attributes and manifest) --><div id="my-map"> <div class="nf-metro-canvas"> <!-- paste SVG here --> </div> <div class="nf-metro-legend"></div> <div class="nf-metro-tip"></div></div>
<!-- 2. Load the driver --><script src="nf-metro-embed.js"></script>
<!-- 3. Attach and capture the API --><script> const api = attachMetroMap({ root: document.getElementById("my-map"), lines: [ { id: "star_salmon", label: "STAR + Salmon", color: "#e05c5c", style: "solid", }, /* ... */ ], embed: null, });</script>The lines array must match the lines embedded in the SVG. The easiest source
for it is the groups array in the manifest (see
getManifest below).
API methods
Section titled “API methods”attachMetroMap(opts) returns an API object with the methods below. Every
method is a no-op when the SVG has no manifest or no matching elements.
highlightLine(id)
Section titled “highlightLine(id)”Activate a line by its id string. Stations and edges that do not belong to that
line are hidden, and the map zooms to the visible subset. Calling it with the
currently active id clears the filter, the same as clearHighlight().
api.highlightLine("star_salmon");clearHighlight()
Section titled “clearHighlight()”Remove any active line filter and station selection, returning the map to its initial unfiltered state.
api.clearHighlight();getManifest()
Section titled “getManifest()”Return the embedded manifest JSON object, parsed from the <metadata id="diagram-manifest"> element, or null if the SVG has no manifest. Use it to
build lines arrays, read node coordinates for overlays, or look up process
patterns.
const manifest = api.getManifest();if (manifest) { console.log(manifest.nodes.map((n) => n.id));}selectNode(processName)
Section titled “selectNode(processName)”Match processName against each node’s patterns array using a
case-insensitive regex, then highlight the matching stations and dim the rest.
A string that matches no node is a no-op.
// Highlight the station(s) whose patterns match this Nextflow process name:api.selectNode("NFCORE_RNASEQ:RNASEQ:ALIGN_STAR_SALMON:STAR_ALIGN");CSS classes written by selectNode:
| Class | Applied to |
|---|---|
nf-metro-station-selected | Matching station marker elements ([data-station-lines]). |
nf-metro-station-dim | All [data-station-id] elements that are not a match. |
nf-metro-selecting | The root element while a selection is active. |
The default templates ship CSS for these classes. If you load the driver separately, add your own styles:
.nf-metro-station-selected rect,.nf-metro-station-selected circle { stroke: #fff; stroke-width: 2;}.nf-metro-station-dim { opacity: 0.2; transition: opacity 0.2s;}reset()
Section titled “reset()”Alias for clearHighlight().
Overlay path
Section titled “Overlay path”For a coordinate-accurate progress overlay, such as lighting up stations as a
pipeline runs, draw a transparent layer that shares the base SVG’s viewBox
and place markers at each node’s manifest coordinates. The
overlay_svg() helper builds that layer, and
the manifest tutorial,
Light up a diagram as a job runs,
walks through the full read-match-draw recipe.
The highlightLine and selectNode API and the overlay approach solve
different problems:
- Driver API. Manipulates the base SVG’s existing DOM elements by adding CSS classes. It adds no elements and works without the manifest.
- Overlay. Adds new elements in a separate layer at exact coordinates from the manifest. Use it for progress indicators, status badges and annotation.
Integration example
Section titled “Integration example”This snippet builds a self-contained host page that loads a separately generated SVG and driver, then wires keyboard shortcuts to the public API.
<!doctype html><html> <head> <style> #map-root { position: relative; } .nf-metro-canvas svg { width: 100%; height: auto; } .nf-metro-legend { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px; } .nf-metro-tip { position: fixed; pointer-events: none; } /* Station selection styles */ .nf-metro-station-selected rect, .nf-metro-station-selected circle { stroke: #4cf; stroke-width: 2; } .nf-metro-station-dim { opacity: 0.15; transition: opacity 0.2s; } </style> </head> <body> <div id="map-root"> <div class="nf-metro-canvas"> <!-- Inline the SVG exported by: nf-metro render map.mmd -o map.svg --> </div> <div class="nf-metro-legend"></div> <div class="nf-metro-tip"></div> </div>
<script src="nf-metro-embed.js"></script> <script> const manifest = (() => { const el = document.querySelector("#diagram-manifest"); return el ? JSON.parse(el.textContent) : null; })();
const lines = (manifest?.groups || []).map((g) => ({ id: g.id, label: g.label, color: g.color, style: "solid", }));
const api = attachMetroMap({ root: document.getElementById("map-root"), lines, embed: null, });
// Example: drive from your application state function onProcessStarted(fqProcessName) { api.selectNode(fqProcessName); }
function onPipelineDone() { api.clearHighlight(); } </script> </body></html>Versioning
Section titled “Versioning”Both the manifest schema and the driver contract are versioned. The Python constants are:
from nf_metro.manifest import MANIFEST_SCHEMA_VERSION # e.g. "1.0"from nf_metro.render.driver import DRIVER_CONTRACT_VERSION # e.g. "1.0"The schema version follows major.minor semantics. The minor part increments
for additive, backward-compatible changes, and the major part increments for
breaking changes. Consumers must ignore unknown fields.
This surface is stable as of nf-metro 1.0, so within a major version the contract only grows in backward-compatible ways. Pin to a specific nf-metro release only if you depend on the exact bytes of the output.