How the ROADMAP Feature Tracks Completion Status in the AI Engineering Curriculum

The ROADMAP feature tracks completion status by parsing emoji markers from ROADMAP.md and injecting them into lesson data during the automated build process, generating a static site/data.js file that serves as the single source of truth for the web interface.

The rohitg00/ai-engineering-from-scratch repository implements a deterministic build system that transforms human-readable markdown tables into structured curriculum data. This approach treats ROADMAP.md as the authoritative source for progress tracking, ensuring that lesson completion statuses automatically synchronize with content availability every time the site rebuilds.

Parsing the ROADMAP.md Source of Truth

The build process begins in site/build.js, where the parseRoadmap() function scans the curriculum's roadmap file line-by-line. This function identifies phase headers and lesson rows using regex patterns to extract status emojis and map them to standardized string values.

Extracting Phase and Lesson Statuses

The script processes ROADMAP.md using two distinct regex patterns. Phase headers follow the format ## Phase N: Title — <emoji>, while lesson rows appear as table pipes | Lesson Name | <emoji> |. The function maps ✅ to "complete", 🚧 to "in-progress", and ⬚ to "planned".

// site/build.js – parseRoadmap()
function parseRoadmap(content) {
  const statuses = {};                // { "Phase 0": { phaseStatus, lessons: {} } }
  let currentPhase = null;
  let currentPhaseStatus = null;

  for (const line of content.split(/\r?\n/)) {
    // Phase header, e.g. "## Phase 0: Setup & Tooling — ✅"

    const phaseMatch = line.match(/^##\s+Phase\s+(\d+).*?\s*(✅|🚧|⬚)/);
    if (phaseMatch) {
      const phaseId = parseInt(phaseMatch[1]);
      const statusEmoji = phaseMatch[2];
      currentPhaseStatus =
        statusEmoji === '✅' ? 'complete' :
        statusEmoji === '🚧' ? 'in-progress' : 'planned';
      currentPhase = `Phase ${phaseId}`;
      statuses[currentPhase] = { phaseStatus: currentPhaseStatus, lessons: {} };
      continue;
    }

    // Lesson row, e.g. "| 01 | Dev Environment | ✅ |"
    if (currentPhase) {
      const lessonMatch = line.match(/^\|\s*\d+\s*\|\s*(.+?)\s*\|\s*(✅|🚧|⬚)\s*\|/);
      if (lessonMatch) {
        const lessonName = lessonMatch[1].trim();
        const statusEmoji = lessonMatch[2];
        const status =
          statusEmoji === '✅' ? 'complete' :
          statusEmoji === '🚧' ? 'in-progress' : 'planned';
        statuses[currentPhase].lessons[lessonName] = status;
      }
    }
  }
  return statuses;
}

Enriching README.md Data with Roadmap Statuses

After extracting the roadmap map, the script processes README.md to locate lesson tables. The parseReadme() function performs fuzzy matching between lesson names in the README and those recorded in the roadmap, normalizing text by removing hyphens and extra whitespace.

Cross-Referencing and Auto-Correction

The system implements a safety mechanism that automatically upgrades a lesson's status to complete if it detects a GitHub repository link, regardless of the roadmap entry. This ensures that published content never appears as unplanned.

// site/build.js – inside parseReadme()
if (lessonMatch) {
  // Look up status from the roadmap map
  const roadmapKey = `Phase ${currentPhase.id}`;
  const roadmapPhase = roadmapStatuses[roadmapKey];
  let status = 'planned';
  if (roadmapPhase) {
    const lessonNameClean = lessonName.replace(/[-–—:]/g, ' ')
                                     .replace(/\s+/g, ' ')
                                     .trim()
                                     .toLowerCase();
    for (const [rName, rStatus] of Object.entries(roadmapPhase.lessons)) {
      const rNameClean = rName.replace(/[-–—:]/g, ' ')
                               .replace(/\s+/g, ' ')
                               .trim()
                               .toLowerCase();
      if (rNameClean.includes(lessonNameClean) ||
          lessonNameClean.includes(rNameClean)) {
        status = rStatus;
        break;
      }
    }
  }

  // If a GitHub link exists, force "complete" (the lesson is published)
  if (url && status === 'planned') {
    status = 'complete';
  }
}

Generating the Static Data File

The enriched data structure is written to site/data.js during the build process (lines 68-78 of site/build.js). This file exports a PHASES array containing nested lesson objects with resolved status fields, serving as the immutable data source for the frontend application.

The data.js Output Structure

The generated file contains lesson records with standardized status values that the UI renders as visual progress indicators.

const PHASES = [
  {
    id: 0,
    name: "Setup & Tooling",
    status: "complete",
    lessons: [
      {
        name: "Dev Environment",
        status: "complete",
        type: "Build",
        lang: "Python, Node, Rust",
        url: "https://github.com/rohitg00/ai-engineering-from-scratch/tree/main/phases/00-setup-and-tooling/01-dev-environment"
      }
    ]
  }
];

Continuous Integration and Automated Synchronization

The build script executes automatically via the GitHub Action defined in .github/workflows/curriculum.yml. This CI workflow triggers on every push to the repository, ensuring that any edits to ROADMAP.md immediately propagate to the generated site/data.js and the live web interface.

Summary

  • ROADMAP.md serves as the human-editable source of truth, using emoji markers (✅ 🚧 ⬚) to indicate completion states.
  • site/build.js contains the parseRoadmap() and parseReadme() functions that transform markdown tables into structured JSON.
  • Auto-correction logic guarantees that lessons with GitHub links always display as complete, preventing stale data.
  • .github/workflows/curriculum.yml automates the build process, ensuring the website always reflects the current curriculum state.

Frequently Asked Questions

How does the ROADMAP feature handle lessons that exist in README.md but lack entries in ROADMAP.md?

The system defaults to a "planned" status for any lesson not found in the roadmap map. However, if the lesson contains a valid GitHub repository link, the auto-correction logic immediately upgrades it to "complete", ensuring published content is never mislabeled as unavailable.

Can contributors update completion status without modifying code?

Yes. Contributors simply edit the emoji markers in ROADMAP.md (✅ for complete, 🚧 for in-progress, ⬚ for planned). The next push triggers the GitHub Action, which regenerates site/data.js and updates the website automatically.

What happens if the emoji markers in ROADMAP.md use different characters?

The regex patterns in parseRoadmap() specifically match only ✅, 🚧, and ⬚ characters. Any other characters would fail to match, causing the status to fall back to the default "planned" value or remain unrecognized until standardized.

How does the system prevent the website from showing outdated completion statuses?

The continuous integration workflow in .github/workflows/curriculum.yml runs site/build.js on every push. This deterministic rebuild ensures that the generated data.js file never diverges from the current state of ROADMAP.md and README.md.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →