Turn a Pile of Notes Into a Connected Brain

Turn a flat pile of Markdown notes into a connected graph. Model topics as neurons and links as synapses, then generate the maps and region tags automatically from frontmatter.

On this page
  1. The anatomy
  2. Declaring the graph in frontmatter
  3. Generating the glia
  4. Guarding against drift with --check
  5. Why generation beats hand-linking
  6. The swap-in box
  7. What you have now

A vault full of disconnected notes is a filing cabinet. A brain is notes plus the connections between them — and the connections are where the value compounds. This post gives you the mental model for structuring the graph, then shows how to generate it automatically so you never hand-maintain an index again.

The principle

Model knowledge as a brain: topic pages are neurons (one home per fact), links are synapses, regions are clusters, and the generated maps are glia — the scaffolding that holds regions together. You declare relationships in frontmatter; a generator derives the graph. Declared once, always consistent.

First: make these values your own

The topic:, relates:, and region/* values shown here are examples from my lab — use your own subjects. Paths like scripts/build-topic-map.mjs assume the vault layout from earlier in this series; point them at wherever your vault keeps its tooling.


The anatomy

The knowledge braintopic Atopic Btopic Ctopic Dtopic Eneurons= topic pagessynapses= relates: linksbuildahomelab.dev
Brain part Vault reality Made of
Neuron A topic page — one canonical owner per subject topic: in frontmatter
Axon / synapse A link between two topics relates: in frontmatter
Region A cluster of related topics region/* tag
Glia Generated maps that hold a region together MOC pages, tags, backlinks

The important move: you never draw the graph. You annotate each neuron with its topic: id and the neurons it relates: to, and a generator turns those declarations into the visible graph — MOC index pages, region tags, and synapse backlinks.


Declaring the graph in frontmatter

Every topic page names itself and its relationships in its YAML frontmatter:

infrastructure/proxmox-cluster.md — frontmatter

---
title: "Proxmox Cluster"
type: topic
status: active
topic: proxmox-cluster
relates: [storage-layout, cluster-networking, backup-strategy]
tags: [infrastructure, proxmox]
---

That’s the entire input the generator needs. topic: marks this page as the neuron that owns “proxmox-cluster”; relates: declares the synapses to three other neurons. Do this on every topic page and you’ve described a whole graph without drawing a single link by hand.


Generating the glia

A small script walks every page, reads the topic: / relates: frontmatter, and writes the derived scaffolding: one MOC per region, region/* tags on member pages, and a brain-region backlink block on each neuron. In my lab that’s scripts/build-topic-map.mjs.

Declare once, generate the graphfrontmattertopic: …relates: [ … ]you write thisbuild-topic-map.mjsthe generatorMOC pages (glia)region/* tagsbacklink blocks–check: fail the commit if these drift
1Run the generator to build the maps2 min
In the vault root

node scripts/build-topic-map.mjs . --write --date 2026-07-15

The positional . is the vault root to scan; --write commits the derived files (omit it for a dry run); --date stamps the regeneration so the output is deterministic.

2Inspect what it generated2 min
Generated artifacts

topics/infrastructure.md     # MOC: every page in the region, linked
topics/ai.md                 # MOC for the AI region
# ...plus region/* tags and a brain-region block appended to each topic page

The MOC is a page you read but never hand-edit — it’s glia, regenerated from the neurons every time.

A generated file is a liability if it silently drifts

The graph is only trustworthy if it always matches the pages. The failure mode is editing a page’s relates:, forgetting to regenerate, and shipping a MOC that lies. Solve it with a check mode in your commit workflow (next section) so drift becomes a hard error, not a quiet inconsistency.

Regenerate after every topic: or relates: change — including new and removed pages

Any time you change a page’s topic: or relates: frontmatter field, add a new topic-bearing page, or remove one, you must regenerate the topic map and stage the derived files alongside your change. Committing without regenerating leaves the region MOCs, region/* tags, and brain-region synapse blocks out of date. The --check mode makes this a hard error in automated writes, but if you’re running the manual path, this is the step most often forgotten. Make it muscle memory: edit frontmatter → run --write → stage the output.


Guarding against drift with --check

The generator has a check mode that regenerates in memory and diffs against what’s committed. Wire it into your commit workflow so you cannot commit a stale graph.

1Add a --check gate before committing3 min
Fails (non-zero exit) if the committed maps are stale

node scripts/build-topic-map.mjs . --check
# exit 0 → maps are in sync
# exit non-zero → regenerate with --write, then stage the changes
Build the CLI to fail loudly — a lesson learned the hard way

An early version of this generator would hang or throw a cryptic ENOENT when invoked without its root positional, or with a stray flag. The fix that matters: validate arguments and print usage instead of hanging or crashing. The hardened CLI now rejects a missing or malformed root positional with a clear usage message, refuses unknown flags, and honors -h / --help. A knowledge-base tool you run half-asleep at midnight must tell you exactly what it wants — a tool that hangs silently trains you to distrust it.

The full generator invocation, the --check gate, and a commit-workflow wrapper are in the paired playbook: The Topic-Map Generator.


Why generation beats hand-linking

Hand-linked graph
Rename a page → hunt every link. Drifts constantly. Index is one more thing to maintain.
Generated graph
Declare relationships once; regenerate in seconds. –check makes staleness impossible to commit.

This is the same instinct as infrastructure-as-code: describe the desired state declaratively, generate the artifacts, and let a check catch drift. Your knowledge graph deserves the same rigor as your containers.


The swap-in box

On other tools

Obsidian: its graph view visualizes [[wikilinks]] for free, and the Dataview plugin can generate MOC-style index pages from frontmatter queries — a no-code path to the same idea. Logseq: page properties and queries cover the relates:-and-generate pattern natively. Foam / Dendron (VS Code): both derive backlinks and hierarchy maps from frontmatter and filenames. The durable idea is identical everywhere: declare relationships as data, derive the graph from the data.


What you have now

A vault that’s a genuine graph — topic pages as neurons, relates: links as synapses, regions clustered, and MOCs generated as glia — with a --check gate that keeps the graph honest. That connected structure is exactly what makes the later payoffs possible: a published wiki that mirrors the graph, and AI agents that traverse it as context.

Next in the series we leave a short note on the discipline that keeps this graph stable over years — identity over status — then move into projections: deriving a published Wiki.js view from the one authoritative vault.


Related posts:

Comments

Comments are powered by GitHub Discussions — sign in with a GitHub account to join the conversation.