feat: directed arrows, infrastructure nodes, Container Diagram tab#1
Merged
abdullahbodur merged 10 commits intomainfrom Mar 21, 2026
Merged
Conversation
- Add directed arrowheads (markerEnd: "arrow") to all edges in service-flow and data-flow views so dependency direction is unambiguous at a glance - Add InfraNode / InfraType types across scanner, graph-builder, and web; RawInfraDecl in scanner for partial YAML declarations that rely on ref files for name/type - Scanner parses infrastructure[] from archmap.yml; resolves same-repo refs (./path.yml) in both local and GitHub scan modes, and cross-repo refs (repo/path.yml?ref=tag) in GitHub scan mode; inline fields take priority over ref file fields - New container-diagram view builder: domain boundary group nodes, service child nodes, infra nodes (databaseNode / queueNode / cacheNode / externalNode) placed below groups; edges labeled "persists to", "publishes to", "subscribes to", "caches via", "calls"; shared infra id deduped to one node - Four new React Flow node components: DatabaseNode (cyan cylinder), QueueNode (purple parallel-lines), CacheNode (amber), ExternalNode (gray dashed); all show ref path in node footer - Add Container tab as 4th tab in the web UI - Add infrastructure declarations to order-service and inventory-service archmap.yml with ref files under infra/; shared kafka id deduplicates to one Kafka node in the container diagram - Remove all emojis from source files - Update docs/configuration.md with infrastructure field reference, InfraNode fields table, ref file format, and Container Diagram view description; update docs/use-cases.md with example commerce org Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Link to the docktail/archmap repo in both configuration.md and use-cases.md so readers can clone the repo and run the commerce domain example (Order Service + Inventory Service) immediately. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
graph-builder: - service-flow: assert markerEnd: "arrow" on dependsOn and kafka edges - data-flow: new test file — empty graph, deduplication, edge creation, markerEnd: "arrow", self-loop prevention, multi-type edge label - container-diagram: new test file — service nodes, group nodes with parentId/extent, infra type mapping (database/queue/cache/external), deduplication by id, edge creation, edge labels per infra type (persists to / publishes to / subscribes to / uses / caches via / calls), markerEnd and smoothstep on all edges scanner: - extract parseRepoConfig and resolveInfraRefsLocal into src/config.ts so they can be imported without pulling in the full scanner entrypoint - config.test.ts: parseRepoConfig covers all fields, skip flag, domain alias, type validation, infrastructure inline/ref/missing cases; resolveInfraRefsLocal covers ref resolution, inline-wins merge, missing ref fallback, cross-repo ref skip, multi-node resolution - exclude src/__tests__ from tsc compilation to prevent dist/ clash 97 tests total passing (was 49) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React Flow only auto-generates SVG arrow marker definitions when
markerEnd is passed as { type: "arrow" }. Passing the plain string
"arrow" is treated as a raw SVG marker ID reference that does not exist,
so no arrowhead was rendered.
Convert in GraphView.tsx before handing edges to useEdgesState, keeping
the graph-builder output framework-agnostic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ut spacing All node components (ServiceNode, DataTypeNode, FunctionNode, DatabaseNode, QueueNode, CacheNode, ExternalNode) now expose 8 named handles (source and target at top/bottom/left/right) so edges can connect to any side. GraphView computes sourceHandle/targetHandle based on relative node center positions — horizontal-dominant pairs use left/right; vertical-dominant pairs use top/bottom — ensuring lines attach to the correct dock point rather than defaulting to the bottom handle. Dagre autolayout now reads node.measured dimensions (falls back to 260×160) and uses nodesep=80, ranksep=200 to prevent nodes from overlapping or crowding. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…verlap resolution Layout (layout.ts): - Default spacing is now 64px (nodesep=64, ranksep=128), configurable via the new `spacing` param on applyDagreLayout - resolveOverlaps() runs after dagre to iteratively push apart any top-level nodes whose bounding boxes still overlap (up to 100 iterations, 16px padding) - Child nodes (parentId set) are excluded from overlap resolution Edge routing (GraphView.tsx): - Extracted getAbsoluteCenter and routeEdges as pure module-level functions - routeEdges tracks per-node per-handle occupancy; when multiple edges share the same node side, subsequent ones are distributed to the next least-used dock rather than stacking on a single point Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Apply a three-layer z-index stack so connection lines are never hidden under domain boundary boxes in the container diagram: group nodes → zIndex 0 (background layer) edges → zIndex 1 (always visible above group boxes) service/infra nodes → zIndex 2 (rendered on top of edge lines) This is a no-op for views without group nodes (serviceFlow, dataFlow, functionFlow) since the relative order of nodes and edges is unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes fixed: 1. Layout was only applied on button click — edges were rendered with the graph-builder grid positions where straight bezier lines could cut through intermediate nodes. Dagre layout is now applied automatically whenever the view data changes (useMemo keyed on view/viewType/selectedServiceId), so nodes are always in proper channel-separated positions before the graph is first shown. 2. Edges defaulted to bezier curves which draw direct diagonals across the canvas. Changed default to smoothstep (orthogonal right-angle routing) so edges travel horizontally and vertically through the clear channels between ranked nodes rather than crossing node boxes. Edge routing is now done AFTER dagre layout so sourceHandle/targetHandle assignments reflect final node positions. handleAutoLayout re-routes edges from the original view data so markerEnd is never double-converted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React Flow renders all nodes in an HTML layer that sits above the edge SVG layer by default — no explicit zIndex needed to achieve boxes > lines > frame. Removed the edge zIndex:1 elevation (which caused lines to float on top of group container borders) and the per-node zIndex grouping. All boxes now render above all edges via React Flow's natural stacking order. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the generic applyDagreLayout with getLayoutedElements, a Dagre
wrapper that understands the microservice diagram's node categories:
Service / group nodes → placed as LR anchors (natural leftmost rank)
Database / Cache nodes → forced two ranks right via weight=3 minlen=2
on service→db edges, so databases always appear
clearly to the right of their owning service
Queue / Bus nodes → excluded from Dagre entirely; manually placed
as a horizontal strip below-centre of all other
nodes with spacing*2 vertical gap
Child nodes → reattached unchanged (relative to parent group)
Edge deduplication prevents Dagre from seeing repeated source→target pairs
(child nodes resolved to their parent group before adding to the graph).
Overlap resolution runs after all positioning to fix any residual collisions.
applyDagreLayout is kept as a thin backward-compat wrapper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
markerEnd: "arrow"added to service-flow, data-flow, and container-diagram edges so dependency direction is unambiguousarchmap.ymlvia aninfrastructure:block; scanner resolvesref:fields from same-repo YAML files (and cross-repo on GitHub scan)Changes
Types (all 3 type files)
InfraType,InfraNode;RawInfraDeclin scanner for partial YAML declarationsViewEdgewithmarkerEnd?andtype?ViewNodewithparentId?,extent?,style?for React Flow subflowsinfrastructure?toAnalyzedServiceandcontainerDiagramtoGraphData.viewsScanner
parseRepoConfigparsesinfrastructure[]from archmap.ymlresolveInfraRefsLocal(same-repo./path.yml) andresolveInfraRefsGithub(same-repo + cross-reporepo/path.yml?ref=tag); inline fields override ref fieldsGraph Builder
markerEnd: "arrow"on all edges in service-flow and data-flowcontainer-diagram.tsview: domain group nodes, service child nodes, infra nodes with type-mapped node types, directed smoothstep edgesWeb UI
DatabaseNode,QueueNode,CacheNode,ExternalNodeGraphTabs: Container tab added as 4th tabGraphView: registers new node types, container diagram empty stateSample services
order-serviceandinventory-servicearchmap.yml updated withinfrastructure:blocksinfra/postgres-archmap.ymlandinfra/kafka-archmap.ymlref files under each service (sharedid: kafkadeduplicates to one Kafka node)Docs
configuration.md:infrastructurefield reference, InfraNode table, ref file format, Container Diagram view descriptionuse-cases.md: Example commerce org with order-service + inventory-service, local run instructionsTest plan
pnpm build— no TypeScript errorspnpm test— 49 tests passservices[].infrastructurewith resolvedname/technology/descriptionfrom ref filesrefpath in footerCo-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com