Build and draw with Linnest
Linnest is the Typst and WebAssembly interface to Linnet’s graph model, DOT parser, layout algorithms, graph queries, and physics-aware 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, joins, and graph algorithms.subgraphfor subgraph object construction and inspection.layoutfor the separate layout pass.drawfor rendering a laid-out graph object with CeTZ.physicsfor reusable particle-line edge styles.
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)
#context if target() == "paged" {
draw(
g,
subgraph: east,
edge-label: edge-label,
edge-label-style: (anchor: "south"),
source-style: source-style,
sink-style: sink-style,
)
} else {
[The downloadable PDF renders this CeTZ result. The HTML manual keeps the
copyable source because Typst's experimental HTML target does not yet emit
the drawing content.]
}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. Physics styles and subgraph objects have their own focused reference pages.