How ROADMAP.md Tracks Lesson Completion Status in AI Engineering from Scratch

ROADMAP.md tracks lesson completion status through three Unicode glyphs—✅, 🚧, and ⬚—which are parsed by site/build.js into plain-text status strings that power the curriculum website and llms.txt.

The rohitg00/ai-engineering-from-scratch repository uses a single markdown file to coordinate progress across its entire curriculum. According to the project source code, ROADMAP.md serves as the human-editable source of truth for lesson completion status, encoding state information with plain Unicode characters that automated build scripts consume during site generation. This lightweight architecture keeps the curriculum state in sync without requiring contributors to edit JSON or configuration files directly.

Status Glyphs in ROADMAP.md

ROADMAP.md encodes progress with three distinct Unicode symbols that are easy to scan and simple to update:

  • ✅ Complete – the lesson has been implemented and passes its tests.
  • 🚧 In Progress – work is underway but not yet finished.
  • ⬚ Planned – the lesson is defined but not started.

Phase-Level and Lesson-Level Status Tracking

These glyphs appear in two specific locations inside the roadmap file.

  1. Phase headers – for example, ## Phase 0: Setup & Tooling — ✅ indicates the overall status of the entire phase.

  2. Lesson rows – each lesson is listed in a Markdown table row such as | 01 | Dev Environment | ✅ | ~75 min |. The third column holds the lesson’s status glyph.

Parsing ROADMAP.md in site/build.js

During site generation, the Node script site/build.js reads ROADMAP.md and converts glyphs into structured status data. The parseRoadmap() function iterates over every line, applying regular expressions to capture both phase headers and lesson rows.

// site/build.js – extract status from ROADMAP.md
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 … — ✅"

    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;
}

The resulting statuses object is merged with lesson links extracted from README.md so that the generated site/data.js contains both a destination URL and a real-time status field for every lesson.

Downstream Consumption and Site Generation

The structured data produced by parseRoadmap() drives multiple outputs across the curriculum site. It populates the visual roadmap page (prereqs.html), powers badge counts for total and completed lessons, and feeds the llms.txt file used by AI agents to discover the curriculum. Because the site generator combines ROADMAP.md statuses with README.md links, the entire curriculum state is kept in a single, human-readable file.

Page components can consume the generated status field to render colour-coded badges:

// Example: rendering a lesson list with colour‑coded badges
function renderLesson(lesson) {
  const colour = { complete: 'green', 'in-progress': 'orange', planned: 'gray' }[lesson.status];
  return `<li style="color:${colour}">${lesson.name}</li>`;
}

Manually Updating Lesson Completion Status

Because the glyphs are plain Unicode characters, contributors can edit ROADMAP.md directly without touching JSON or configuration files. For example, changing a table cell from to marks the lesson as finished:

| 03 | Matrix Transformations & Eigenvalues | ✅ | ~75 min |

After the commit merges, the CI pipeline reruns site/build.js, which rebuilds site/data.js and updates all derived artefacts automatically.

You can verify the parser locally by reading the markdown file and asserting the expected phase and lesson statuses:

const roadmap = fs.readFileSync('ROADMAP.md', 'utf8');
const statuses = parseRoadmap(roadmap);
console.assert(statuses['Phase 0'].phaseStatus === 'complete');
console.assert(statuses['Phase 0'].lessons['Dev Environment'] === 'complete');

Summary

  • ROADMAP.md uses three Unicode glyphs—, 🚧, and —to encode lesson completion status at both phase and lesson levels.
  • The parseRoadmap() function in site/build.js scans the markdown with regexes and converts glyphs into the strings complete, in-progress, and planned.
  • Parsed status data is merged with README.md lesson links to produce site/data.js, which drives prereqs.html, badge counts, and llms.txt.
  • Manual updates to ROADMAP.md propagate automatically through the CI pipeline, keeping the curriculum state in sync without extra tooling.

Frequently Asked Questions

What do the status emojis in ROADMAP.md represent?

The three glyphs serve as a lightweight visual tracker: means the lesson is complete and passes tests, 🚧 means work is actively in progress, and means the lesson is planned but not yet started. These symbols appear in both phase headers and individual lesson table rows, making the curriculum state readable at a glance.

How does site/build.js parse the roadmap statuses?

The parseRoadmap() function in site/build.js scans every line of ROADMAP.md using regular expressions that match phase headers (/^##\s+Phase\s+(\d+).*?—\s*(✅|🚧|⬚)/) and lesson rows (/^\|\s*\d+\s*\|\s*(.+?)\s*\|\s*(✅|🚧|⬚)\s*\|/). It maps each matched glyph to the string complete, in-progress, or planned, then returns a nested statuses object organized by phase and lesson name.

Can I manually update a lesson's completion status?

Yes. Because the glyphs are plain Unicode characters, you can edit ROADMAP.md directly and commit the change. The CI pipeline then reruns site/build.js, which propagates the updated status into site/data.js, the visual roadmap page, and the llms.txt file automatically.

What downstream assets depend on ROADMAP.md?

The parsed status object is merged with README.md links to produce site/data.js, which fuels the prereqs.html roadmap page and badge counters across the site. The same data set also populates llms.txt, allowing AI agents to discover the current curriculum state as implemented in rohitg00/ai-engineering-from-scratch.

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 →