Appearance
Knowledge Round Trip
FreshKnowledge lives in documents. A researcher writes notes in the margin of a paper. A project lead drafts meeting minutes in a shared file. A student keeps a journal of observations. A team maintains a contacts list. These are human acts — writing things down, organizing thoughts, recording what happened — and the documents they produce are the primary artifacts of knowledge. Not databases, not platforms, not APIs. Documents.
MD-LD begins from a single observation: a document can be simultaneously human-readable and machine-parseable without either quality compromising the other.
The Core Cycle
graph LR
A[MD-LD Document] --> B[parse]
B --> C[Quad Array]
C --> D[Transform/Query/Validate]
D --> E[generate]
E --> F[MD-LD Document]
F --> A- Text — An MD-LD document is plain text. Readable without any tool.
- Parse — One function call turns it into RDF quads.
- Quads — A plain JavaScript array. No query engine required.
- Transform — Standard JS operations: filter, map, reduce.
- Generate — One function call turns quads back into readable text.
- Text again — The output is still readable. The round trip is complete.
The Document Is the Source of Truth
Consider a contacts document — a single MD-LD file that declares organizations, lists people with their relationships, and defines validation shapes:
markdown
[my] <tag:me@example.org,2026:>
# My Contacts {=my:contacts .Container label}
## ACME Inc. {=my:orgs/acme .prov:Organization label}
## Alice {=my:person/alice .prov:Person my:name}
Born on [1994-09-21] {my:birthdate ^^xsd:date}
Email: [alice@example.com] {my:email}
Works at [ACME Inc.] {+my:orgs/acme ?my:worksAt}
Knows [Bob] {+my:person/bob ?my:knows}
## Bob {=my:person/bob .prov:Person my:name}
Email: [bob@example.com] {my:email}
Works at [ACME Inc.] {+my:orgs/acme ?my:worksAt}Read this document without parsing it. It reads: "Alice knows Bob." "Bob works at ACME Inc." Now parse it, and the same text produces a complete RDF graph. The document did not become something else in the process. It revealed what was already there.
From Text to Array
Parsing is one function call:
javascript
import { parse } from 'mdld-parse';
const { quads, statements, origin, context, primary } = parse({ text: contacts });The quads array is the computational representation — a plain JavaScript array where each element is an RDF quad. That array is the runtime. Not a database. Not a triple store. Not a query engine. An array.
The Array Is the Engine
Every question about your data becomes a JavaScript expression:
javascript
const RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
const PROV_PERSON = 'http://www.w3.org/ns/prov#Person';
const personIRIs = new Set(
quads
.filter(q => q.predicate.value === RDF_TYPE && q.object.value === PROV_PERSON)
.map(q => q.subject.value)
);
const WORKS_AT = 'tag:me@example.org,2026:worksAt';
const ACME = 'tag:me@example.org,2026:orgs/acme';
const acmePeople = quads
.filter(q => q.predicate.value === WORKS_AT && q.object.value === ACME)
.map(q => q.subject.value);No query language to learn. No endpoint to configure. No result format to parse. The graph is already in memory in the shape JavaScript expects.
When you need performance, you build indexes from the same array using Map objects. Lookups become O(1). The index is not a special database feature — it is a derived data structure you create on demand and discard when done.
From Array Back to Text
Generating is one function call:
javascript
import { generate } from 'mdld-parse';
const { text } = generate({ quads, context });The output is readable MD-LD. The same document structure, the same headings and prose, but now reflecting only the current state of the quads. You can read it, edit it, share it, version it.
Round-Trip Safety
The round trip is always safe. The same quads always produce the same text. The same text always produces the same quads:
javascript
const result1 = parse({ text: original });
const { text: regenerated } = generate({ quads: result1.quads, context: result1.context });
const result2 = parse({ text: regenerated });
// Same quad count
console.log(result1.quads.length === result2.quads.length); // true
// Semantically equivalent
const key = q => `${q.subject.value}|${q.predicate.value}|${q.object.value}`;
const keys1 = new Set(result1.quads.map(key));
const keys2 = new Set(result2.quads.map(key));
// keys1 equals keys2No information is lost. No inference is added. What goes in comes back out.
The Document May Literally Be Written on Paper
The MD-LD specification requires no runtime for the knowledge to exist. A document written with a pen on paper following the specification contains the quads implicitly — they can be extracted manually at any future time.
The runtime is required for computation. The knowledge is already there, in the text.
Composable Text Records
Because generate produces human-readable text, MD-LD documents are composable. You can:
- Merge two contacts lists:
merge([contacts1, contacts2]) - Extract a subset: filter quads, generate a new document
- Transform: augment quads with computed properties, generate
- Validate: run SHACL shapes against quads
- Query: standard JavaScript array operations
- Visualize: graph layout algorithms on the quads
- Export: serialize to Turtle or JSON-LD using n3.js
At every stage, the output can be written back to MD-LD text. The round trip is not just parse-and-generate — it is the entire computational cycle that keeps knowledge legible.
Naming Things: IRIs, Prefixes, and Authority
Every node in a knowledge graph needs a unique identifier. MD-LD gives you three strategies:
tag: scheme (RFC 4151) — Self-sovereign identity:
tag:alice@example.com,2026:No central registry required. Authority is yours by right of controlling the email address.
nih: scheme (RFC 6920) — Content-addressed identity: Identifies what something is by its cryptographic hash. Two documents with the same content get the same IRI regardless of who wrote them.
https:// — Open web identity: For things that already have web addresses: Wikipedia articles, Wikidata entities, Schema.org types.
All three interoperate in the same document. Your personal nodes use tag:. Shared resources use https://. Content-addressed references use nih:.