Build and draw with Linnest
Linnest is the Typst and WebAssembly interface to Linnet’s graph model, DOT parser, layout algorithms, graph queries, and generic drawing styles. This guide follows one graph from construction through layout and drawing; the separate Typst API reference carries the supported symbol inventory.
Use Linnet’s Rust or Python interfaces for graph construction and algorithms in an application. Use Linnest when the graph, layout, or final drawing is owned by a Typst document.
Linnet
The linnet crate wrapped by this package is built around a half-edge graph data structure. This means that instead of a graph being represented as a set of nodes and edges, it is represented as a set of half-edges , and a set of vertices . The graph structure is then encoded through two maps. The first map, maps each half-edge to its corresponding vertex. The preimage of any vertex is the set of half-edges that map to it, called the crown of . The second map, , is an involution that glues half-edges together to form edges. If a half-edge is glued to itself, we call that an external half-edge. This means that linnet graphs are strictly more capable than normal edge and vertex graphs.
Native half-edges also make subgraphs more granular because they can be encoded as sets of half-edges. This directly supports vertex-induced subgraphs: the union of the crowns of a set of vertices.
Linnest
Linnest is the Typst and WebAssembly interface to Linnet. It provides layout algorithms, DOT parsing, and selected graph algorithms without a separate runtime process.
Graphs can be constructed in two ways: parse a DOT string with parse:
#let g = parse("digraph { a -> b }")or build from edges and nodes with build, using a Fletcher-inspired syntax:
#let g = build({
node(<a>, label: [$v$])
node(<b>)
edge(source(<a>), <a-b>, sink(<b>), label: [e])
edge(source(<a>), <in-a1>, label: [e])
edge(source(<a>), <in-a2>, label: [e])
})In either case, type(g) is dictionary: graph values wrap an archived Linnet graph together with native Typst data. Rust owns topology, layout state, statement metadata, and internal opaque payload bytes. User data captured from Typst stays in Typst and is merged back into query records.
The main use case is to place nodes and edges on a canvas with the layout function and render the result with draw.
graphfor construction, parsing, inspection, directed cuts, joins, and graph algorithms.subgraphfor half-edge selection, annotations, and inspection.layoutfor the separate layout pass.drawfor rendering a laid-out graph object with CeTZ.
Domain-specific styles are ordinary Typst data and callbacks composed with graph.style and draw; Linnest does not reserve a domain or export a physics module.
Choose an import path
Linnest and Kurvst are currently bundled source packages, not Typst Universe packages. A Clinnet run writes both package trees below build/templates/. From a custom template in that directory, import Linnest with:
#import "crates/linnest/typst/src/lib.typ": draw, graph, layout, subgraphFrom this repository’s crates/linnest/typst/examples/ directory, the equivalent checkout-relative import is ../src/lib.typ. Keep the package directory and its linnest.wasm file together when copying it elsewhere. The examples below use the checkout-relative form because they are also compiled as repository tests.
Minimal Build Example
#import "../src/lib.typ": draw, graph, layout, subgraph
#import graph: build, dot, edge, edges, node, nodes, parse, sink, source
#let g = build({
node(<a>)
node(<c>)
edge(
source(<a>, compass: "e"),
<a-c>,
sink(<c>, compass: "w"),
label: [a-c],
statements: (
color: "0055ff",
source-color: "d72638",
sink-color: "1b7f4c",
),
)
},
name: "demo",
)
#let g = layout(g)
#let east = subgraph.compass(g, "e")
#let edge-records = edges(g, subgraph: east)
#let dot-text = dot(g)
#let edge-label(edge) = text(fill: rgb("#" + edge.color))[#edge.label]
#let source-style(edge) = (stroke: rgb("#" + edge.source-color) + 0.5pt)
#let sink-style(edge) = (stroke: rgb("#" + edge.sink-color) + 0.5pt)
#html.frame(draw(
g,
subgraph: east,
edge-label: edge-label,
edge-label-style: (anchor: "south"),
source-style: source-style,
sink-style: sink-style,
))Graph Objects
Graph values combine archived Linnet topology with native Typst data. The focused graph reference documents their constructors, transforms, queries, and update operations.
Continue into the API
Use the graph module for construction and queries, the layout functions for placement, and the drawing functions for CeTZ output. Domain-template composition and subgraph objects have their own focused reference pages.