@pipelex/mthds-ui
v0.7.0
Published
Shared graph rendering logic for MTHDS method visualization
Downloads
630
Readme
@pipelex/mthds-ui
Interactive graph visualization for MTHDS method pipelines. Renders execution graphs from GraphSpec data — the canonical format produced by Pipelex when tracing pipeline execution.
Core graph logic (builders, layout, analysis) is pure TypeScript with no React dependency. The React layer provides a drop-in GraphViewer component powered by ReactFlow.
Install
npm install @pipelex/mthds-uiReleased versions are listed on the npm page and the GitHub releases page.
Peer dependencies
| Dependency | Required | Used by |
| -------------------- | -------- | ----------------------------- |
| react, react-dom | no | React layer (graph/react) |
| shiki | no | Syntax highlighting (shiki) |
Bundled dependencies
| Dependency | License | Used by |
| --------------- | ------- | ------------------------------- |
| elkjs | EPL-2.0 | Graph layout engine |
| @xyflow/react | MIT | Graph rendering (graph/react) |
elkjs (Eclipse Layout Kernel) is licensed under the Eclipse Public License 2.0. See NOTICE for details.
Quick start (React)
import { GraphViewer } from "@pipelex/mthds-ui/graph/react";
function MethodGraph({ graphspec }) {
return <GraphViewer graphspec={graphspec} />;
}That's it. GraphViewer handles layout, styling, CSS variables, and all ReactFlow internals. All props except graphspec are optional with sensible defaults.
Next.js (App Router)
ReactFlow accesses browser globals at module-evaluation time, so it cannot be server-side rendered. Use next/dynamic with ssr: false:
"use client";
import dynamic from "next/dynamic";
import type { GraphViewerProps } from "@pipelex/mthds-ui/graph/react";
import React from "react";
const GraphViewer = dynamic(
() =>
import("@pipelex/mthds-ui/graph/react").then((mod) => ({
default: mod.GraphViewer,
})),
{ ssr: false },
) as React.ComponentType<GraphViewerProps>;
export function MyGraph({ graphspec }) {
return <GraphViewer graphspec={graphspec} />;
}GraphViewer props
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------------------- | ---------------------- | ---------------------------------------- |
| graphspec | GraphSpec \| null | — | Graph data (nodes + edges) |
| config | GraphConfig | DEFAULT_GRAPH_CONFIG | Layout and visual configuration |
| direction | GraphDirection | "LR" | Layout direction: TB, LR, RL, BT |
| showControllers | boolean | false | Show controller group outlines |
| onNavigateToPipe | (pipeCode: string, status?: PipeStatus) => void | — | Callback when a pipe node is clicked |
| onReactFlowInit | (instance: AppRFInstance) => void | — | Access the underlying ReactFlow instance |
Container sizing
The graph container uses position: absolute; inset: 0 to fill its parent. Make sure the parent element has position: relative and a defined height (e.g. h-full, flex-1, or an explicit height).
GraphSpec
GraphSpec is the data format that describes a pipeline execution graph. It's generated by Pipelex when running or validating MTHDS method bundles.
Generating a GraphSpec
# From a .mthds bundle file
pipelex-agent validate bundle my-method.mthds --view
# The output JSON contains a graphspec fieldOr programmatically via the Pipelex Python SDK:
from pipelex import Pipelex
px = Pipelex()
result = px.validate_bundle("my-method.mthds", view=True)
graphspec = result.graphspec # dict ready for JSON serializationStructure
interface GraphSpec {
nodes: GraphSpecNode[];
edges: GraphSpecEdge[];
}
interface GraphSpecNode {
id: string;
pipe_code?: string; // e.g. "analyze_match"
pipe_type?: string; // e.g. "PipeLLM", "PipeSequence", "PipeExtract"
status?: string; // "succeeded", "failed", "running", "scheduled", "skipped"
io?: {
inputs?: IOItem[];
outputs?: IOItem[];
};
}
interface GraphSpecEdge {
id?: string;
source: string; // Source node ID
target: string; // Target node ID
kind: GraphSpecEdgeKind; // "data", "contains", "batch_item", etc.
label?: string;
}Node types
Nodes represent pipes (operations) and stuffs (data artifacts) in the pipeline:
- Pipe nodes — operations like
PipeLLM,PipeSequence,PipeExtract,PipeSearch - Stuff nodes — data flowing between pipes, typed by concepts (e.g.
CandidateProfile,Document)
Edge kinds
| Kind | Description |
| ------------------ | ----------------------------------------------------------- |
| data | Data flow — stuff produced by one pipe, consumed by another |
| contains | Containment — a controller pipe wraps child pipes |
| batch_item | Batch processing — items fanned out from a collection |
| batch_aggregate | Batch aggregation — items collected back |
| parallel_combine | Parallel results combined |
Example GraphSpec (minimal)
{
"nodes": [
{
"id": "extract_text",
"pipe_code": "extract_text",
"pipe_type": "PipeExtract",
"io": {
"inputs": [{ "digest": "input_doc", "name": "document", "concept": "Document" }],
"outputs": [{ "digest": "pages", "name": "pages", "concept": "TextPages" }]
}
},
{
"id": "summarize",
"pipe_code": "summarize",
"pipe_type": "PipeLLM",
"io": {
"inputs": [{ "digest": "pages", "name": "pages", "concept": "TextPages" }],
"outputs": [{ "digest": "summary", "name": "summary", "concept": "Summary" }]
}
}
],
"edges": []
}Full specification: docs.pipelex.com — Execution Graph Tracing
Configuration
GraphConfig
Controls layout and visual behavior. All fields are optional — DEFAULT_GRAPH_CONFIG provides sensible defaults.
import { DEFAULT_GRAPH_CONFIG } from "@pipelex/mthds-ui";
// Override specific settings
const myConfig = {
...DEFAULT_GRAPH_CONFIG,
direction: "LR",
nodesep: 80,
ranksep: 50,
};| Field | Type | Default | Description |
| ----------------- | ------------------------ | ------------- | -------------------------------------- |
| direction | GraphDirection | "LR" | Layout direction |
| showControllers | boolean | false | Show controller group boxes |
| nodesep | number | 50 | Horizontal spacing between nodes |
| ranksep | number | 100 | Vertical spacing between ranks |
| edgeType | EdgeType | "bezier" | Edge curve style |
| initialZoom | number \| null | null | Override fit-view zoom (null = auto) |
| panToTop | boolean | true | Pan viewport to top after layout |
| paletteColors | Record<string, string> | (see below) | CSS variable overrides for theming |
Theming with palette colors
GraphViewer applies CSS custom properties from paletteColors on mount. Override colors by passing a custom config:
<GraphViewer
graphspec={graphspec}
config={{
...DEFAULT_GRAPH_CONFIG,
paletteColors: {
...DEFAULT_GRAPH_CONFIG.paletteColors,
"--color-pipe": "#e06c75",
"--color-stuff": "#61afef",
"--color-bg": "#282c34",
},
}}
/>Default palette colors include:
| Variable | Purpose |
| ------------------------- | -------------------------- |
| --color-pipe | Pipe node border/accent |
| --color-pipe-bg | Pipe node background |
| --color-stuff | Stuff node border/accent |
| --color-stuff-bg | Stuff node background |
| --color-edge | Edge line color |
| --color-batch-item | Batch item edge color |
| --color-batch-aggregate | Batch aggregate edge color |
| --color-bg | Graph background |
| --color-bg-dots | Background dot pattern |
| --font-sans | Node font family |
| --font-mono | Code/controller font |
See graphConfig.ts for the full default palette.
Entry points
| Import path | Content |
| ------------------------------- | ------------------------------------------------------------------ |
| @pipelex/mthds-ui | Pure-TS graph logic — types, builders, layout, controllers, config |
| @pipelex/mthds-ui/graph/react | React components — GraphViewer, label helpers, type converters |
| @pipelex/mthds-ui/shiki | MTHDS syntax highlighting with shiki |
Pure TypeScript usage
Use the graph logic without React — build nodes/edges, run layout, and feed the result to your own renderer:
import {
buildGraph,
getLayoutedElements,
applyControllers,
DEFAULT_GRAPH_CONFIG,
} from "@pipelex/mthds-ui";
// Build graph data from a GraphSpec
const { graphData, analysis } = buildGraph(graphspec, "bezier");
// Apply ELK layout
const { nodes, edges } = getLayoutedElements(graphData.nodes, graphData.edges, "TB");
// Optionally wrap nodes in controller groups
const final = applyControllers(nodes, edges, graphspec, analysis, true);Shiki integration
Syntax-highlight MTHDS code with the bundled grammar and themes:
import { highlightMthds, getAvailableThemes } from "@pipelex/mthds-ui/shiki";
const html = await highlightMthds(mthdsSource, "pipelex-dark");Development
npm install
make check # lint + format-check + typecheck
make test # unit tests (vitest)
make build # build to dist/License
MIT — see LICENSE.
This project depends on elkjs which is licensed under EPL-2.0. See NOTICE for third-party license details.
