Layouts
A layout decides where nodes go. You add nodes and edges with no positions (or arbitrary ones), run a layout, and Nodus computes coordinates that make the structure readable. Layouts are the bridge between “I have a graph” and “I can see it.”
This page explains what each layout is for and how to run one. For task-focused examples see Applying Layouts; for signatures see the Layouts API.
Running a layout
Layouts live under nodus.layouts.*. Each returns a Promise<void> that
resolves when the layout has finished (or its animation has played out):
import { Nodus } from '@kortexya/nodus';
const nodus = new Nodus({ container: document.getElementById('graph') });
await nodus.setGraph({ nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }], edges: [ { source: 'a', target: 'b' }, { source: 'b', target: 'c' }, ],});
await nodus.layouts.force();await nodus.view.locateGraph(); // fit the result on screenThe full set:
nodus.layouts.force(opts?);nodus.layouts.forceLink(opts?);nodus.layouts.hierarchical(opts?);nodus.layouts.radial(opts?);nodus.layouts.concentric(opts?);nodus.layouts.grid(opts?);nodus.layouts.sequential(opts?);nodus.layouts.stop();Async and cancellable
Layouts are asynchronous because they can be iterative and may run off the main thread. Two consequences:
- Await them (or chain
.then) so you act on final positions, not mid-computation ones. - Stop them with
nodus.layouts.stop()— useful when the user triggers a new layout before the previous one finishes, or navigates away.
const running = nodus.layouts.force(); // start (don't await yet)// ... user clicks "cancel" ...nodus.layouts.stop();await running; // resolves promptlyThe duration option
Every layout accepts a duration (in milliseconds) that controls how the
graph reaches its new positions:
duration: 0— jump straight to the final positions. Static and instant; best for first paint or large graphs.duration: 800(any positive value) — animate the transition, tweening nodes from their current spots to the computed ones.
await nodus.layouts.force({ duration: 0 }); // instantawait nodus.layouts.hierarchical({ duration: 600 }); // animatedChoosing a layout
Different structures want different layouts. Use this as a starting point.
Try it live — run the same graph through all seven layouts and compare:
Force (force)
A physics simulation: nodes repel, edges pull. It produces organic clusters that reveal communities and overall shape without any hierarchy. The general-purpose default when you don’t know the structure in advance, and the right choice for exploratory views of social, citation or network data.
Force-link (forceLink)
A force layout that treats edges as springs with a target length. Use it when edge length should mean something — keeping connected nodes a consistent distance apart, or letting weighted edges pull harder. Good for weighted networks where you want spacing to reflect connection strength.
Hierarchical / Sugiyama (hierarchical)
A layered layout for directed acyclic graphs, trees and pipelines. It assigns nodes to layers and orders them to minimise edge crossings — the classic Sugiyama approach. Reach for it for flowcharts, dependency graphs, org charts and anything with a clear flow direction.
Radial (radial)
Places nodes on concentric rings around a root, with distance from the root
encoding depth. Ideal for trees or ego-networks where one node is the focus and
you want hop-distance to read as radius. Requires a centralNode (the root’s
id): nodus.layouts.radial({ centralNode: 'root' }).
Concentric (concentric)
Arranges nodes in rings by a ranking — the highest-ranked nodes in the
centre, lower-ranked ones further out. Use it to foreground important nodes (by
degree, score, or any metric you map to rank) regardless of connectivity. Like
radial, it requires a centralNode:
nodus.layouts.concentric({ centralNode: 'root' }).
Grid (grid)
Snaps nodes to a regular grid. Tidy, predictable, and crossing-agnostic — handy for catalogues, small multiples, or any view where uniform spacing beats revealing structure.
Sequential (sequential)
Lays nodes out in a single line / sequence. The right tool for inherently linear data — timelines, ordered steps, or a path you want to read left to right.
Where layouts run
Layouts are compute-heavy, so Nodus runs them in compiled Rust/WASM code, and by default in a Web Worker so the main thread stays responsive while a large graph settles. This is why they’re async. The threading needs no special cross-origin headers. For the full picture see The WebAssembly Backend and Architecture.
Layout factories (advanced)
The everyday API is nodus.layouts.*. For advanced use — registering or
pre-configuring a layout instance — Nodus also exports factory functions:
import { forceFactory, forceLinkFactory, gridFactory, hierarchicalFactory, radialFactory, concentricFactory, sequentialFactory,} from '@kortexya/nodus';Most applications never need these — reach for them only when you want to build and hold a configured layout yourself rather than call the instance methods.
Where to go next
- Applying Layouts — practical recipes and the per-layout options.
- API: Layouts — method signatures and the factory exports.
- Camera & Coordinates — fitting and framing the
result with
locateGraph. - The WebAssembly Backend — where the heavy computation happens.