v1.0.0
2026-06-30 · GitHub release · Diff
Major milestone release and first release under the seqeralabs GitHub organisation. 300+ commits since 0.7.2. The .mmd input format is backward compatible - existing files render without edits (many will look better thanks to the routing work below).
All four flow directions
Section titled “All four flow directions”nf-metro now supports all four Mermaid graph directions: LR, RL, TB, and BT. Previously only LR and TB were supported; RL and BT are their respective mirrors, with full routing vocabulary for fold sections, bypass-V, convergence sinks, and perpendicular entries.
Routing engine
Section titled “Routing engine”The majority of the code change in this release is engine work, and most of it is structural rather than a list of isolated fixes. Three large programs ran across the cycle, then a focused fold-routing sprint closed it out.
Centreline-builder unification. Edge routing was consolidated onto a single centreline builder that owns corner anchoring and tapering for every route family - entry-wrap, perpendicular-exit up-and-over, U-shaped bypass, TOP-entry staircase, fan L-shapes, and inter-section bundles. What used to be scattered per-case path construction now flows through one declarative inter-section dispatch table and one builder, so curves are correct by construction rather than patched after the fact (#791-#814, plus the #845 symbolic gap-slot model).
Direction-agnostic layout (AxisFrame). Layout heuristics that were written against hardcoded "TB" string checks were migrated to an AxisFrame abstraction with lane accessors and a single offset-regime applier, and the core handlers adopted a Direction enum. This is what made the new RL and BT directions tractable: every routing handler now operates on one canonical orientation, and the per-direction special cases were retired. The LR/TB rotation model was extended so RL and BT are derived by mirroring at the seam-classifier layer (#918-#922, #1029-#1049).
Robustness hardening. A gate-arm triage pass gave every un-exercised branch in the layout and routing modules a verdict - reachable (with a new fixture), defensive, or a filed bug - and the inter-phase state shared between layout stages was formalised into an explicit protocol. A guard registry with a cost audit and golden baseline now reds CI the moment a layout regresses (#687, #673, #921).
Fold-threshold routing. Folded sections (where a line wraps across a column boundary) got the most targeted-fix work, late in the cycle. The keystone: fold-back routes that cannot be drawn cleanly now raise a FoldThresholdError and are treated as an authoring constraint rather than emitting broken geometry (#1088). On top of that gate:
- Perpendicular-entry fans slot onto parallel approach channels by feeder order instead of overlapping (#1144).
- Folded LEFT-exit staircase bundle ordering and concentric nesting (#1143, #1161).
- Folded bbox bottom aligns to the target section’s settled content bottom, not its live bounding box, preventing balance drift on tall fold targets (#1162).
- Tight 1-row folds no longer leave a visible run-out stub on the bypass-V (#1177).
- Same-side cul-de-sac entry re-anchors the interior-consumer port instead of routing around it, removing a whole class of U-route generation (#1182).
- Opposing-line fold-backs under fold compression raise
FoldThresholdErrorrather than tangling (#1187). - Convergence-sink ports no longer face the wrong section after fold relocation (#1167).
- Disconnected components renormalise grid rows after stacking, preventing section overlap (#1164).
- Corridor-fed single-line sections re-centre instead of drifting off-trunk (#1173); same-column RIGHT-entry corridor descent no longer jogs before dropping (#1178).
- TB-section bypass-V seats on the line’s lane-side grid column, not a fixed offset (#1163); the post-bypass settling pass runs in both validate modes (#1171); convergence-split placement is deterministic across runs (#1168).
Spacing and symmetry.
- Symmetric 2-way diamonds compact to half pitch through the grid-snap, halving wasted horizontal space (#1076).
- Upright (TB/BT) label and icon spacing derives from the
AxisFramerather than hardcoded"TB"checks (#1043). - Light theme line width corrected to match
OFFSET_STEP(4 px -> 3 px) (#1073).
CSS offset-path animations
Section titled “CSS offset-path animations”Ball animations switch from SMIL <animateMotion> to CSS offset-path. SMIL is disabled in some host environments and causes SVG-in-HTML embedding issues; offset-path works reliably across all modern browsers.
Light and dark as independent axes
Section titled “Light and dark as independent axes”Brand (nfcore, seqera) and display mode (light, dark) are now independent. A single rendered SVG carries both palettes via CSS light-dark() and adapts to the viewer’s color-scheme automatically. Logo assets also adapt per color-scheme with no extra directives required.
Render API and render-many
Section titled “Render API and render-many”A stable Python API:
from nf_metro.api import render_string, RenderConfig
svg = render_string( graph_text, theme="nfcore", mode="dark", config=RenderConfig(embed_font=True, responsive=True),)render_string is the one-call entry point. RenderConfig is a typed dataclass bundling the render-side output options (font embedding, responsive viewBox, class prefixes, color-scheme handling) for callers who prefer a config object over keyword arguments. The render-many CLI command batch-renders a JSON manifest of jobs in a single process, amortising interpreter and import startup across the whole corpus.
Embedded data manifest
Section titled “Embedded data manifest”Every render now carries a machine-readable JSON manifest - station visual centres, pill dimensions, and line metadata - factored into a dependency-free nf_metro.manifest package and documented as a standard. This is what lets nf-metro serve accept a previously rendered SVG as input, and it gives host systems a stable way to map screen coordinates back to graph elements (#623).
Font portability
Section titled “Font portability”Renders can embed the Inter font or convert text to vector paths, so maps display identically whether or not the host has the font installed - important for SVGs that travel into PDFs, slides, and other documents (#839).
Live workflow visualisation (nf-metro serve)
Section titled “Live workflow visualisation (nf-metro serve)”nf-metro serve connects to a running Nextflow workflow and renders a live metro map in the browser, updating as processes progress. New in this release:
- SVG input - accepts a previously rendered SVG (with embedded manifest) instead of a
.mmdsource. auto_processmapping -%%metro auto_process: trueandprocess_scope:collapse a Nextflow DAG into a lean process-level map automatically.
Interactive browser playground
Section titled “Interactive browser playground”A browser-based editor powered by Pyodide runs the full Python engine client-side - edit .mmd source, see the map update live. Features: example dropdown, Nextflow DAG import, graphical topology editing, zoom controls, brand/mode toggles, gzip-compressed share URLs, and a service-worker cache so the Pyodide runtime loads instantly after the first visit.
New documentation site
Section titled “New documentation site”Rebuilt in Astro / Starlight with a Seqera-branded theme, replacing MkDocs-Material. Metro maps render live at build time; the <Metro> component presents source, CLI command, and rendered map as a three-panel toggle. Versioned docs with an in-page version switcher, Pagefind full-text search, ZoomableSVG lightbox, color-chip swatches in code blocks, and link validation in CI.
- 3-way parallel test split with
pytest-splitto cut CI wall-clock time. - Python 3.10 dropped (EOL); minimum is now Python 3.11.
- All GitHub Actions refs pinned to full commit SHAs (seqeralabs org policy).
- Incremental render-diff: PR previews only re-render changed fixtures.