API ReferenceTopologyBuilder

TopologyBuilder

TopologyBuilder is the entry point for defining an architecture topology. It manages groups, standalone nodes, and edges, then commits everything to the React Flow store with a single apply() call.

const topology = new TopologyBuilder(autoLayout: boolean);
ParameterTypeDescription
autoLayoutbooleanWhen true, node positions are computed automatically using a force-directed algorithm. When false, you must supply explicit x/y coordinates for every group.

createGroup

Creates a group container and returns a GroupBuilder for adding nodes and sub-groups.

topology.createGroup(
  id: string,
  config: GroupConfig,
  position?: { x: number; y: number }
): GroupBuilder

GroupConfig

PropertyTypeDefaultDescription
labelstringDisplay name shown in the group header
widthnumber400Initial width in pixels (recalculated by autoResize)
heightnumber200Initial height in pixels (recalculated by autoResize)
styleobject{}Inline CSS applied to the group container
colorstringBorder and header accent color (hex or CSS color)
layerstringLayer name; group is hidden when this layer is inactive

Usage

const backendGroup = topology.createGroup('backend', {
  label: 'Backend Services',
  width: 700,
  height: 300,
  color: '#3b82f6',
  layer: 'v2',
}, { x: 200, y: 300 });

When autoLayout is true, the position argument is ignored. Pass it anyway for documentation purposes — it has no effect.


createProcess

Creates a standalone node (not inside any group) and adds it directly to the canvas.

topology.createProcess(config: ProcessConfig): TopologyBuilder

ProcessConfig

PropertyTypeDefaultDescription
idstringRequired. Unique node identifier across the entire topology
labelstringRequired. Display name
state'running' | 'stopped' | 'error' | 'warning''running'Visual state indicator
shapestring'default'Node shape. See Node Types & Shapes
layerstringLayer name for visibility toggling
replicasnumberShorthand: creates N nodes with IDs id-1id-N
shardIdstringShard identifier shown as a badge
shardRole'primary' | 'replica' | 'arbiter'Shard role badge
externalbooleanfalseMarks the node as external (orange border styling)

Usage

topology.createProcess({
  id: 'cdn',
  label: 'CDN',
  shape: 'cloud',
  external: true,
  state: 'running',
});

connect

Creates a directed edge between two nodes.

topology.connect(
  source: string,
  target: string,
  options?: ConnectionOptions
): TopologyBuilder
⚠️

connect(A, B) means A opens the TCP connection to B. The arrow direction represents who dials whom, not who sends data. Responses always travel back along the same edge in reverse — never create a duplicate edge for responses.

ConnectionOptions

PropertyTypeDefaultDescription
labelstringText shown on the edge midpoint
protocolstringConnection protocol. Controls edge color. See Edges & Protocols
type'floating' | 'animated' | 'pulse''floating'Edge component to render
layerstringLayer name for visibility toggling
animatedbooleantrueWhether the edge animates (dashes move)
bidirectionalbooleanfalseRenders arrows on both ends

Usage

topology.connect('api', 'pg', {
  protocol: 'postgresql',
  label: 'SQL queries',
  type: 'floating',
});
 
topology.connect('flink', 'kafka', {
  protocol: 'kafka',
  label: 'consume',
  type: 'pulse',
});

apply

Commits all groups, nodes, and edges to the Zustand store. Triggers a React re-render and populates the canvas.

await topology.apply(): Promise<void>

apply() is asynchronous because it waits for React Flow to finish its layout pass before resolving. Always await it.

await topology.apply();
// Canvas is populated here. Safe to create FlowBuilder.
const flow = new FlowBuilder();

autoResizeGroups

Recalculates the dimensions of all groups to fit their contents. Equivalent to calling .autoResize() on every GroupBuilder after the fact.

topology.autoResizeGroups(): TopologyBuilder

Useful when you add nodes to groups dynamically and want a single resize pass at the end.

// Build all groups and nodes...
topology.autoResizeGroups();
await topology.apply();

newRow

Signals the auto-layout engine to place the next group on a new row, below the current row of groups.

topology.newRow(): TopologyBuilder
topology.createGroup('row1-left',  { label: 'Service A' });
topology.createGroup('row1-right', { label: 'Service B' });
topology.newRow();
topology.createGroup('row2',       { label: 'Database Layer' });

Full example

topology-full-example.ts
const topology = new TopologyBuilder(true);
 
// External client (no group)
topology.createProcess({
  id: 'internet',
  label: 'Internet',
  shape: 'cloud',
  external: true,
});
 
// Frontend group
const frontendGroup = topology.createGroup('frontend', {
  label: 'Frontend',
  color: '#10b981',
});
 
frontendGroup
  .addProcess({ id: 'nginx', label: 'Nginx', state: 'running' })
  .addProcess({ id: 'spa',   label: 'React SPA', state: 'running' })
  .autoResize();
 
topology.newRow();
 
// Backend group
const backendGroup = topology.createGroup('backend', {
  label: 'Backend',
  color: '#3b82f6',
});
 
backendGroup
  .addProcess({ id: 'api-1', label: 'API Pod 1', state: 'running' })
  .addProcess({ id: 'api-2', label: 'API Pod 2', state: 'running' })
  .addProcess({ id: 'pg',    label: 'PostgreSQL', shape: 'cylinder', state: 'running' })
  .autoResize();
 
// Connections
topology.connect('internet', 'nginx', { protocol: 'http',       label: 'HTTPS' });
topology.connect('nginx',    'spa',   { protocol: 'http',       label: 'static' });
topology.connect('nginx',    'api-1', { protocol: 'http',       label: 'proxy' });
topology.connect('nginx',    'api-2', { protocol: 'http',       label: 'proxy' });
topology.connect('api-1',    'pg',    { protocol: 'postgresql', label: 'SQL' });
topology.connect('api-2',    'pg',    { protocol: 'postgresql', label: 'SQL' });
 
await topology.apply();
return null;