md2hd

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.

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.

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 by works; runs → run by and knows → known by do 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.

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.