Skip to content

Markdown to Graph [[markdown_to_graph: Explanation]]Explanation

πŸ€– Content Generator

Prompt [[markdown_to_graph_gen_prompt: text]]text

Explain how QMDC turns plain Markdown into a queryable graph. This is the "aha moment" page.

Structure:

  1. Start with a familiar Markdown document (headings, lists, links)
  2. Show how QMDC interprets it: headings β†’ objects, lists β†’ fields, [[#ref]] β†’ edges
  3. Show the resulting graph visually (describe nodes and edges in text, or use a simple mermaid diagram)
  4. Show a SQL query against the graph: "find all objects that reference X"
  5. Explain: the Markdown IS the database. No export, no sync, no drift.

Key insight to convey: you're not "annotating" Markdown β€” you're writing Markdown that happens to be structured. The structure emerges from conventions you already use (headings for sections, lists for properties).

Use concrete examples from the format specification objects.

You already know how to write Markdown. Headings, bullet lists, links β€” that's all QMDC needs to build a queryable graph. No special tooling, no export step, no schema files. The Markdown is the database.

Start with familiar Markdown

Here's a document describing two services:

## API Gateway [[gateway: Service]]

- port: 8080
- depends: [[#user_service]]

## User Service [[user_service: Service]]

- port: 8081
- database: [[#users_db]]

Nothing exotic β€” headings, bullet lists, and a couple of [[...]] annotations. But QMDC sees structure here.

How QMDC interprets it

Each Markdown element maps to a graph concept:

Markdown element Graph concept
Heading with [[id: Kind]] Object β€” a node in the graph
- key: value list items Field β€” data on that node
[[#id]] in a value Reference β€” a typed edge to another node
Heading level (H1β†’H6+) Nesting β€” parent-child relationships

From the document above, QMDC produces:

  • Two object nodes: gateway and user_service, both of Kind Service
  • Fields on each: port, depends, database
  • Edges: gateway β†’dependsβ†’ user_service, user_service β†’databaseβ†’ users_db

The resulting graph

graph LR gateway["gateway: Service<br/>port: 8080"] user_service["user_service: Service<br/>port: 8081"] users_db["users_db"] gateway -->|depends| user_service user_service -->|database| users_db

Every edge carries a type β€” the field name that holds the reference. depends, database, author β€” these aren't generic "links," they're semantically meaningful relationships you defined by naming your fields.

Query it with SQL

Once parsed, query the graph directly:

-- Find everything that depends on user_service
SELECT source_id, edge_type FROM edges WHERE target_id = 'user_service'

Result: gateway depends on user_service.

-- Get all Service objects and their ports
SELECT __id, json_extract(data, '$.port') as port
FROM objects WHERE __kind = 'Service'

Result: gateway: 8080, user_service: 8081.

No export. No sync. No drift between your docs and your data.

The key insight

You're not "annotating" Markdown with metadata. You're writing Markdown that happens to be structured β€” and the structure emerges from conventions you already use:

  • Headings for sections β†’ become Object nodes
  • Bullet lists for properties β†’ become Field data
  • Links between things β†’ become Reference edges

Add [[id]] to a heading and it becomes addressable. Add [[#target]] to a field value and it becomes a graph edge. That's it.

Nesting creates hierarchy

Subheadings express parent-child relationships and Array collections:

## Team [[team]]

### Members [[members: [User]]]

#### Alice [[alice]]

- role: admin

#### Bob [[bob]]

- role: dev

This creates a team object with a members array containing two User objects. Each child automatically gets __parent: [[#team]] and __parent_field: members β€” no manual wiring needed. The child IDs become hierarchical: team.members.alice, team.members.bob.

The whole workspace is the graph

A Workspace is a directory of .qmd.md files. References work across files β€” [[#user_service]] resolves whether the target is in the same file or a different one. The parser indexes every object, validates all references, and reports broken links.

Your file system is your namespace. Your Markdown is your schema. Your headings are your nodes. There's nothing else to maintain.


For complete syntax details β€” objects, fields, references, arrays, and workspaces β€” see the Format Specification.