DEV Community

Cover image for A Free Prerequisite Graph of Everything Kids Learn: Exploring Marble's os-taxonomy
ArshTechPro
ArshTechPro

Posted on

A Free Prerequisite Graph of Everything Kids Learn: Exploring Marble's os-taxonomy

If you have ever tried to build anything in education tech, you have probably hit the same wall: curriculum data is either a flat list of standards in a PDF, or it is locked inside someone's product.

A flat list tells you what a child should learn in Year 2. It does not tell you what they need to know first. And that second question is the one that matters if you are building adaptive practice, a tutoring app, a learning-path generator, or an AI tutor that needs to know where a kid is stuck.

os-taxonomy from Marble is an attempt to fix that. It is an open dataset that breaks primary and elementary learning into small, teachable ideas and connects them with prerequisite edges. It has picked up around 4.8k stars, which is a lot for a pure data repo.

Here is what is in it, how to use it, and whether it is worth your time.

What you actually get

It is a graph, shipped as plain JSON.

  • 1,591 micro-topics (nodes). Each is one teachable idea, like "Building sentences" or "Apparent brightness of stars".
  • 3,225 prerequisite edges. "Topic X depends on topic Y", each tagged hard or soft, with a one-line reason.
  • Curriculum alignment. Topics link to the standards they came from: Common Core, NGSS, the UK National Curriculum, the C3 social studies framework, and IB PYP.
  • 176 domain clusters. Short, parent-friendly summaries per subject, domain, and age band.
  • Teaching research. 1,051 records on how to teach Science and Mathematics topics, with activities, feedback ideas, and assessment guidance. More on this below.

Coverage is weighted toward the core subjects:

Subject Topics
Science 547
Mathematics 504
English 286
History 90
Personal & Social Development 88
Life Skills 37
Computing 21
Learning to Learn 18

There is no runtime, no package, and no dependencies. You clone the repo and read JSON files.

The data model

Everything lives in data/:

File Contents
topics.json The micro-topics (nodes)
dependencies.json Prerequisite edges
curriculum-standards.json Source standards, grouped by curriculum
clusters.json Domain summaries
teaching-research.json Teaching guidance per topic (about 23 MB)
manifest.json Counts and SHA-256 checksums

JSON Schemas for each file are in schema/.

A topic looks like this (trimmed):

{
  "id": "mt_N8CpN1EJrP",
  "type": "CONCEPTUAL",
  "subject": "English",
  "domain": "Grammar & Punctuation",
  "name": "Building sentences",
  "ageRangeStart": 4,
  "ageRangeEnd": 6,
  "centrality": 0.257,
  "evidence": [
    "Distinguish between complete sentences and fragments",
    "Compose a complete sentence with a subject and verb"
  ],
  "assessmentPrompt": "If {{name}} says something like \"The dog\", can they tell you...",
  "standards": ["ccss-ela:L.K.1f", "uk-nc-2013:Eng.App2.Y1.Sent.1"]
}
Enter fullscreen mode Exit fullscreen mode

A few fields are worth calling out:

  • type classifies the kind of knowledge: conceptual, procedural, representational, language, or meta.
  • evidence is a list of observable mastery criteria. This is the useful bit for anyone building assessments.
  • centrality gives you a rough sense of how connected a topic is in the graph.
  • assessmentPrompt is a natural-language check with a {{name}} placeholder for the child's name. Replace or strip it before showing it to anyone.

And an edge:

{
  "topicId": "mt__00ZSLnB7p",
  "prerequisiteId": "mt_VBl1T1sFCM",
  "strength": "hard",
  "reason": "Must understand vibrations make sound before finding volume patterns"
}
Enter fullscreen mode Exit fullscreen mode

Read it as "topicId depends on prerequisiteId". Flip it and you get "unlocks".

Getting started in five minutes

git clone https://github.com/withmarbleapp/os-taxonomy.git
cd os-taxonomy
node scripts/validate.mjs   # checks structure, references, and checksums
Enter fullscreen mode Exit fullscreen mode

Find the direct prerequisites of a topic

This uses JSON import attributes, so use a recent Node version (22 or newer is safest):

import topics from './data/topics.json' with { type: 'json' };
import deps from './data/dependencies.json' with { type: 'json' };

const byId = new Map(topics.topics.map(t => [t.id, t]));

const prereqsOf = id =>
  deps.dependencies
    .filter(d => d.topicId === id)
    .map(d => byId.get(d.prerequisiteId));

// "Addition and subtraction word problems"
console.log(prereqsOf('mt_yJmvUCCym7').map(t => t.name));
// [ 'Representing Addition and Subtraction' ]
Enter fullscreen mode Exit fullscreen mode

Build a full learning path

The interesting thing about a prerequisite graph is that you can walk it. Since the graph is a DAG (no cycles), a depth-first walk gives you every topic a learner needs before the target, in an order they could actually study them:

const edgesByTopic = new Map();
for (const d of deps.dependencies) {
  if (!edgesByTopic.has(d.topicId)) edgesByTopic.set(d.topicId, []);
  edgesByTopic.get(d.topicId).push(d);
}

function learningPath(targetId, { hardOnly = true } = {}) {
  const seen = new Set();
  const order = [];

  function visit(id) {
    if (seen.has(id)) return;
    seen.add(id);
    for (const d of edgesByTopic.get(id) ?? []) {
      if (hardOnly && d.strength !== 'hard') continue;
      visit(d.prerequisiteId);
    }
    order.push(byId.get(id));
  }

  visit(targetId);
  return order; // prerequisites first, target last
}

for (const t of learningPath('mt_yJmvUCCym7')) {
  console.log(`${t.ageRangeStart}-${t.ageRangeEnd}  ${t.subject}  ${t.name}`);
}
Enter fullscreen mode Exit fullscreen mode

Running it on "Addition and subtraction word problems" prints:

4-6  Mathematics  One-to-one counting
4-6  Mathematics  How Many in Total?
4-6  Mathematics  Addition as combining or putting together two
4-6  Mathematics  Subtraction as taking away or separating
4-6  Mathematics  Representing Addition and Subtraction
4-6  Mathematics  Addition and subtraction word problems
Enter fullscreen mode Exit fullscreen mode

That is a sensible sequence: count, combine, take away, represent it, then solve word problems.

The hardOnly flag is handy. Hard edges are true blockers. Soft edges are "helpful to know", so include them when you want a gentler path and drop them when you want the shortest one.

Prefer Python?

Same idea with networkx:

import json
import networkx as nx

topics = {t["id"]: t for t in json.load(open("data/topics.json"))["topics"]}
deps = json.load(open("data/dependencies.json"))["dependencies"]

G = nx.DiGraph()
for d in deps:
    G.add_edge(d["prerequisiteId"], d["topicId"], strength=d["strength"])

target = "mt_yJmvUCCym7"
needed = nx.ancestors(G, target) | {target}
path = list(nx.topological_sort(G.subgraph(needed)))

for tid in path:
    print(topics[tid]["name"])
Enter fullscreen mode Exit fullscreen mode

Once it is in networkx, you also get the usual graph tools for free: finding the most "foundational" topics, spotting bottlenecks, or checking which topics unlock the most downstream learning. Note that this version follows soft edges too, so it can return a longer path than the JavaScript one.

Add the teaching guidance

The newest file, teaching-research.json, covers what to do with a topic. Each record joins to a topic by topicId and includes a teaching summary, concrete activities with feedback ideas, common misconceptions, assessment guidance, and sources.

import research from './data/teaching-research.json' with { type: 'json' };

const guidanceByTopic = new Map(research.records.map(r => [r.topicId, r]));
const guidance = guidanceByTopic.get('mt_yJmvUCCym7');

console.log(guidance?.learn.summary);
for (const a of guidance?.learn.activities ?? []) console.log('-', a.title);
// - Story-modelling with counters and a mat
// ...
Enter fullscreen mode Exit fullscreen mode

Only Science and Mathematics are covered so far. For English and the other subjects, guidance will be undefined, so keep that ?. in place.

What you could build with it

  • Adaptive practice. When a kid fails a topic, walk back one hard edge and test the prerequisite instead of repeating the same question.
  • AI tutors. Give an LLM the topic, its evidence list, its prerequisites, and (for maths and science) its teaching activities as structured context. That grounds the model far better than "teach my kid fractions".
  • Placement and diagnostics. Use evidence and assessmentPrompt to build quick checks, then use the graph to infer what a child probably already knows.
  • Curriculum mapping. Because topics link to both Common Core and the UK National Curriculum, you can roughly map content between the two systems.
  • Visualizations. The repo includes a 3D graph render, and Marble has an interactive version where you can click a topic and see everything that leads to it.

The caveats, honestly

The licensing needs a careful read. This is the most important part. The dataset has three layers with different terms:

  • The database (structure, IDs, relationships) is under ODbL 1.0.
  • Marble's written text (names, descriptions, evidence, prompts, reasons) is under CC BY-SA 4.0.
  • curriculum-standards.json is not Marble's to license. Each source keeps its upstream terms.

So, is it worth a try?

If you work anywhere near education tech, yes. It takes minutes to load, and a well-structured prerequisite graph with mastery criteria is the kind of thing teams usually spend months building internally. Even if you do not use it as-is, it is a good reference model for how to structure learning data.

It is especially useful as grounding data for AI tutoring tools, where the hard problem is often not generating explanations but knowing what to teach next.

Just read the license section before shipping anything commercial, and treat v1 as a strong foundation that you validate, not a finished curriculum.

A good first experiment: pick a topic your own kid (or a niece, nephew, or student) is struggling with, run learningPath() on it, and see whether the prerequisites match what you see in real life.

Links

Top comments (0)