# Apply layout routes and label positions Graphora accepts explicit world-space edge polylines and measured label centers from a custom layout or a manually computed stage. Built-in Dagre still returns node positions only; accepting a route does not promise obstacle avoidance. ```ts const geometry = engine.createLayoutGeometry({ padding: 8 }) engine.setLayoutGeometry(geometry) engine.applyLayoutResult({ positions: [], bounds: engine.viewSnapshot().bounds, provenance: geometry.provenance, edgeRoutes: { mode: 'replace', items: [ { id: 'a-b', key: 'a-b', kind: 'polyline', // Must start/end at these nodes' actual final world-space centers. points: [ { x: 0, y: 0 }, { x: 0, y: 100 }, { x: 200, y: 100 }, { x: 200, y: 0 } ] } ] } }) ``` This example assumes positioned nodes at the stated centers and an edge whose public ID and normalized key are `a-b`. Obtain actual IDs/positions from `engine.viewSnapshot()` in applications. Unknown edges, duplicate IDs, mismatched centers, non-finite coordinates or stale provenance reject the whole update. To place a label, include its measured box in the installed geometry's `labels` array. Use the active label ID (`node::label` or `edge::label`) and exact owner tuple, then return `labelPlacements: { mode: 'replace', items: [...] }` with the same tuple and a world-space `center`. Canvas draws centered screen-sized text there while retaining visibility/collision policy. ## Stage ownership `engine.getLayoutArtifacts()` returns frozen provenance, `edgeRoutes` and `labelPlacements`. Null means no current stage; `[]` means the stage explicitly produced an empty result. Omitted updates preserve current state unless an upstream dependency changed. `mode: 'clear'` removes a stage. A position patch clears previous routes and labels. Replacing/clearing routes clears previous labels unless the same result supplies replacements. Label-only updates keep routes and camera unchanged. Graph/view/geometry changes clear artifacts; callers rerun their stages when appropriate. The engine protects against late Worker results and synchronous mutations during publication. For engine-run layouts, advertise `capabilities.edgeRoutes` and/or `capabilities.labelPlacements`; call `runLayout({ output: { edgeRoutes: 'required' } })`. Defaults are `ignore`. A supported requested stage must return an update; unsupported required output or missing geometry rejects before work. An `if-supported` request without geometry is downgraded to ignored in the context. ## Rendering Canvas clips route endpoint legs to node bodies and uses the same polyline for drawing, arrows, midpoint fallback labels, picking and viewport image export. Repeated points and interior endpoint waypoints are skipped. A route with no visible non-zero path falls back to the existing derived edge geometry. Unrouted edges retain their current curves, parallel lanes and loops. Custom renderers may support optional `edge.route` and `label.layoutCenter` in render snapshots without importing layout types. Document any fallback if your renderer does not consume these fields. Route/label extents do not automatically change camera fitting; fit a complete scene bound explicitly when needed. See the **Apply routed view** and **Move gateway** actions in the measured-layout example for stage application, Canvas picking and automatic invalidation.