Guide6 min read
Relationships
Four ways to draw an edge, and the rule that keeps a fact written from both ends as one line on the canvas.
Everything that connects two nodes ends up as an edge. There are four ways to write one, and you should use whichever fits how you already take notes.
The four ways
A rel: map
The explicit form. A map of relation name to id, or to a list of ids.
---
id: acme
rel:
employs: [jane-doe, sam-webb]
runs: records-portal
---
rels: and links: are accepted as the same field, so you do not have to
remember which one you picked last time.
Any frontmatter value that is a wikilink
If a value is a wikilink and the key is not one md2hd reserves, the key becomes the relation name.
---
id: jane-doe
works_at: '[[acme]]'
reports_to: '[[sam-webb]]'
---
This is usually the most natural form, because it reads as a fact about the node you are writing rather than as configuration.
An inline field in the prose
owns:: [[records-portal]]
Anywhere in the body. Useful when the relationship is something you realised while writing the note, not something you planned in the frontmatter.
A bare wikilink
Talked to [[jane-doe]] about the portal.
Produces an untyped mentions link. If a named relation already connects the
same two nodes, the bare link is dropped — it adds nothing, and dropping it
removes most of the unlabelled grey lines from a real map.
One fact, one line
You will write the same relationship from both ends. jane owns portal in one
note, portal owned_by jane in the other. Drawn naively that is two lines
between the same pair, which reads as two different facts.
md2hd turns every link to face one way before drawing it. Three rules do it:
Passive voice flips. Any label ending in _by is the same relationship seen
backwards, so owned_by, attended_by and run_by are stored as owns,
attended and run pointing the other way. This needs no vocabulary list and is
right every time.
Declared pairs flip. Where the two sides use different words entirely, declare them in the map block:
---
type: map
inverse:
works_at: employs # "X works_at Y" is "Y employs X"
met: attended_by
---
Whatever still coincides collapses. Matching is on a crude stem, so owns
and owned count as one verb.
Automatic inflection is deliberately not attempted.
owns → owned byworks;runs → run byandknows → known bydo not, and half-working morphology is worse than none, because you cannot predict which half you are getting.
Two voices, one direction
A relationship runs one way but reads differently from each end. An organisation employs a person; that person works at the organisation.
Select a node and every link states itself in that node’s voice, with a compass chevron pointing at the node on the other end. On the canvas only the voice you are reading from appears, so a link stays one line with one label. The detail panel has room for both, and shows both.
md2hd learns the second voice one of two ways: either you wrote both sides
somewhere in your notes, or you declared the pair under inverse:. Where only
one wording has ever been written, it keeps that one and aims the chevron inward
instead — meaning “something informs this”.
Relations with no direction
Some relations read the same from both ends. List them:
---
type: map
symmetric: [knows, met, partner]
---
They draw with no arrowhead and a chevron at each end, pointing at both nodes.
You can also just write the relation from both sides — A knows B in one note
and B knows A in the other — and md2hd folds them into a single symmetric link
without being told.
Two relations between the same pair
Two different relations between the same two nodes would leave and land on the same handles and draw byte-identical curves. Their control points are pushed sideways instead, so they fan into distinct arcs, and their labels and compass badges travel with them.
Where links point from
Cards carry invisible ports on all four sides. Which face a link leaves by is chosen from where the other card actually landed, weighted by the card’s own proportions — which is what stops a link between two cards in the same column from wrapping all the way around.
You never drag a connection here. The ports exist so an edge can always take the short way round.