Tracking Phase Prerequisites and Dependencies in the AI Engineering from Scratch Curriculum
The AI Engineering from Scratch curriculum tracks phase prerequisites and dependencies through a directed acyclic graph (DAG) implemented via a static PREREQS JavaScript object in site/prereqs.html, merged with dynamically generated PHASES data from site/data.js to render an interactive SVG roadmap.
The rohitg00/ai-engineering-from-scratch repository structures its learning path as a directed acyclic graph where each phase may depend on one or more earlier phases. Understanding how the system tracks these dependencies is essential for contributors adding new content or learners navigating the curriculum. The implementation combines static dependency maps with auto-generated catalog data to create a robust prerequisite tracking system that maintains synchronization between documentation, code, and the visual roadmap.
How Prerequisites Are Stored
The system stores prerequisite information in three interconnected locations, balancing manual curation with automated generation.
Static Dependency Map in site/prereqs.html
The canonical source of dependency edges lives in site/prereqs.html as a JavaScript object called PREREQS. This static mapping lists, for every phase ID, the IDs of its direct prerequisite phases.
// In site/prereqs.html (around line 523)
var PREREQS = {
0: [],
1: [0],
2: [1],
// ...
19: [14, 15, 16, 17]
};
Generated Phase Catalogue in site/data.js
The build pipeline generates site/data.js via site/build.js, which processes the output of scripts/build_catalog.py. This file contains a PHASES array where each element includes the phase id, name, and status (complete, in-progress, or planned).
Runtime Graph Construction
When the roadmap page loads, the system merges PREREQS with PHASES and builds two auxiliary structures for traversal: CHILDREN (the reverse of PREREQS mapping parents to children) and POS (absolute SVG coordinates derived from TIER_ORDER). A sanity-check loop (lines 887-891 in site/prereqs.html) ensures every phase in PHASES has an entry in PREREQS, automatically assigning an empty array to phases without explicit prerequisites.
The Build Pipeline
The end-to-end flow transforms markdown lesson files into a navigable dependency graph.
Phase Definition Structure
Each phase resides under phases/<phase-number>-<slug>/ with its human-readable title extracted from the H1 in docs/en.md. The front-matter includes a Prerequisites: field listing upstream lessons.
Catalog Generation with build_catalog.py
The scripts/build_catalog.py script walks the phases/* directory tree, parses front-matter, collects code files and quiz metadata, and outputs a JSON representation. This catalog captures the phase identifiers that keep documentation and code synchronized.
Site Generation with build.js
The site/build.js script consumes the catalog to produce site/data.js, injecting the PHASES array into the static site. This separation allows the visual map to reference the same phase identifiers used in lesson front-matter.
Visualizing the Dependency Graph
The visualization logic in site/prereqs.html (lines 523-800) renders the DAG as an interactive SVG diagram.
Layout Algorithm and TIER_ORDER
The layout matrix TIER_ORDER defines visual groupings of phases. The script computes node positions automatically, adding a catch-all tier for any phase not explicitly placed in the matrix. Directed edges render as cubic-bezier curves (edgePath) with arrowheads (arrowPoints) to show prerequisite flow.
Interactive Traversal Functions
The UI exposes getAncestors(pid) and getDescendants(pid) functions for highlighting prerequisite chains and unlocked content. Clicking a phase highlights its ancestors (required prerequisites) and descendants (what it unlocks) while displaying completion status from the PHASES array.
Adding New Phases with Prerequisites
To extend the curriculum with a new phase, update both the static map and the directory structure.
First, edit the PREREQS object in site/prereqs.html:
// Add to PREREQS object
var PREREQS = {
// ... existing entries ...
20: [19], // New phase 20 depends on phase 19
};
Then create the phase directory:
mkdir -p phases/20-new-research/01-intro
echo "# Intro to New Research\n\n**Prerequisites:** Phase 19" > phases/20-new-research/01-intro/docs/en.md
After the next CI build, site/data.js includes the new phase automatically.
Querying Dependencies Programmatically
You can inspect prerequisite relationships via browser console using the helper functions:
// Get all prerequisite phase IDs for phase 12
const ancestors = getAncestors(12);
console.log(Object.keys(ancestors)); // → ['4', '6', '11', ...]
To customize the visual layout, modify TIER_ORDER before the graph renders:
var TIER_ORDER = [
[0],
[1],
[2],
[3, 5, 7, 4, 6],
[8, 10],
[11, 12, 13],
[14, 15, 16],
[19, 20] // Place new phase 20 next to 19
];
Summary
- The prerequisite system uses a static
PREREQSobject insite/prereqs.htmlmerged with auto-generatedPHASESdata fromsite/data.js. - Build pipeline:
scripts/build_catalog.pyparses lesson front-matter,site/build.jsgenerates the site data, andsite/prereqs.htmlrenders the interactive DAG. - Visualization relies on
TIER_ORDERfor layout,getAncestors()for prerequisite chains, andgetDescendants()for unlocked content. - Safety checks ensure every phase has a dependency entry, preventing graph breakage when adding new curriculum content.
Frequently Asked Questions
How does the curriculum prevent circular dependencies between phases?
The system implements a directed acyclic graph (DAG) structure where PREREQS defines edges from child to parent phases. While the JavaScript rendering logic assumes acyclic data, the static nature of the PREREQS object in site/prereqs.html allows maintainers to review dependency chains manually during curriculum updates. The getAncestors() function performs recursive traversal up the parent chain, which would theoretically run indefinitely if cycles existed, but the build process and manual review ensure phase 19 cannot list phase 20 as a prerequisite while phase 20 lists phase 19.
Can I modify prerequisites without rebuilding the entire site?
Yes. The PREREQS object in site/prereqs.html is static JavaScript that loads at runtime, so you can edit dependency edges directly in that file without running scripts/build_catalog.py or site/build.js. However, changes to phase titles, descriptions, or completion status require regenerating site/data.js through the build pipeline, as that data derives from lesson front-matter in the phases/ directory.
What happens if a phase is missing from the PREREQS map?
The runtime initialization code includes a safety check (lines 887-891 in site/prereqs.html) that iterates through all phase IDs in PHASES and verifies their presence in PREREQS. If a phase lacks an entry, the script automatically assigns it an empty array (PREREQS[pid] = []), effectively marking it as having no prerequisites. This prevents the visualization from breaking while allowing the curriculum to scale without immediate manual updates to the dependency map.
How does the system handle multiple prerequisites for a single phase?
The PREREQS object supports arrays of parent IDs for each phase. For example, phase 19 declares [14, 15, 16, 17] as its prerequisites, meaning learners must complete all four preceding phases before accessing phase 19. The visualization draws separate cubic-bezier curves from each parent to the child node, and the getAncestors() function recursively collects the entire upstream chain, ensuring complete dependency tracking for complex curriculum paths.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →