Markdown to RDF
This is the mechanism that makes LOKF both “markdown-friendly” and “RDF-native”.
The identity: frontmatter + context = JSON-LD
Section titled “The identity: frontmatter + context = JSON-LD”A JSON-LD document is just JSON plus an @context that maps its keys to IRIs.
LOKF’s frontmatter keys are precisely the LinkML slots, and the generated
lokf.context.jsonld maps each of them to its slot_uri. Therefore:
flowchart LR
A["Concept frontmatter<br/>(YAML)"] --> C["JSON-LD document"]
B["lokf.context.jsonld<br/>(generated @context)"] --> C
C -- expand --> D[("RDF triples")]
D --> E["SPARQL queries"]
D --> F["SHACL validation"]
D --> G["OWL reasoning"]
No new syntax, no parallel file. The author writes OKF; the context supplies the meaning.
Worked example
Section titled “Worked example”The frontmatter of the reference bundle’s WAU metric (abridged — see the full file), and the triples it expands to:
---type: Metricid: https://acme.example/knowledge/metrics/weekly-active-userstitle: Weekly Active Usersunit: userstags: [growth, engagement]timestamp: 2026-06-30T12:00:00Zauthor: - type: Person id: https://acme.example/people/jsmith name: Jordan Smithmeasures: [ https://acme.example/knowledge/glossary/active-user ]derivedFrom: [ https://acme.example/knowledge/tables/user-events ]dependsOn: [ https://acme.example/knowledge/glossary/active-user ]---@prefix lokf: <https://w3id.org/lokf/> .@prefix schema: <http://schema.org/> .@prefix prov: <http://www.w3.org/ns/prov#> .@prefix dcterms: <http://purl.org/dc/terms/> .@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<…/metrics/weekly-active-users> a lokf:Metric ; schema:name "Weekly Active Users" ; schema:unitText "users" ; schema:keywords "growth", "engagement" ; schema:dateModified "2026-06-30T12:00:00Z"^^xsd:dateTime ; schema:author <…/people/jsmith> ; lokf:measures <…/glossary/active-user> ; prov:wasDerivedFrom <…/tables/user-events> ; dcterms:requires <…/glossary/active-user> .
<…/people/jsmith> a schema:Person ; schema:name "Jordan Smith" .The type: Metric field became rdf:type lokf:Metric; the typed relations
became prov:, dcterms:, and lokf: predicates pointing at other concepts’
IRIs.
The two aliases
Section titled “The two aliases”The published context makes exactly two changes on top of the raw LinkML output, both standard JSON-LD keyword aliasing, so that unmodified OKF frontmatter behaves as Linked Data:
type→@type— OKF’s required field designates the RDF class.id→@id— the concept’s IRI is the RDF subject.
Everything else (title, derivedFrom, tags, …) maps to its ontology
property directly from the model.
Do it yourself
Section titled “Do it yourself”You never have to wire the context by hand — lokf convert (and the
lokf.rdf.serialize function underneath it) does the expansion for you:
# a single concept -> Turtle on stdoutuv run lokf convert examples/acme-knowledge/metrics/weekly-active-users.md --format ttl
# the same thing behind the just recipejust gen-rdf-turtle examples/acme-knowledge/metrics/weekly-active-users.md--format also takes nt, jsonld, xml, n3, and trig; --output FILE
writes to disk instead of stdout. Point convert at the bundle directory
(examples/acme-knowledge) to project all six concepts at once.
Prefer to stay in Python? lokf.rdf.serialize is the same projection the CLI
calls:
from lokf import rdf
# a concept file, or the bundle directory — either resolves IRIs correctlyprint(rdf.serialize("examples/acme-knowledge/metrics/weekly-active-users.md", "ttl"))See Convert for the full command, every output
format, and the matching just recipe.