Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

ML-For-Beginners — Admin & Contributor Guide

Generated May 2026 from microsoft/ML-For-Beginners at 000d594

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Operational reference for teachers, curriculum maintainers, translation reviewers, and contributors of the Microsoft Machine Learning for Beginners curriculum. If you are a student looking for how to run the lessons, read the User Guide instead — this document covers what the learner-facing guide deliberately skips: architecture, authoring contracts, the multi-language translation pipeline, classroom delivery patterns, and the Microsoft contribution workflow.


1. Executive Summary

ML-For-Beginners is a 12-week, 26-lesson curriculum repository published by Microsoft's cloud-advocacy team. It is not a runtime system. It is an authoring and delivery artifact that ships four distinct kinds of content in one repository:

Artifact Technology Purpose
Lesson content Markdown + Jupyter notebooks (Python) + R notebooks Core curriculum: 26 lessons across 7 topic areas
Quiz front-end Vue 3 + vue-router + vue-i18n (Vue CLI 5) in quiz-app/ Pre/post-lecture quizzes with i18n
Demo web app Flask + scikit-learn + ufo-model.pkl in 3-Web-App/ Lesson 9 teaches how to wrap a trained model in Flask
Documentation site Docsify (zero-build) via root index.html Renders the curriculum as a browsable site

Everything else in the repo exists to support these four artifacts: translations of every Markdown file into 50+ languages (generated by the Co-op Translator GitHub Action), mirrored image assets in translated_images/, GitHub issue/PR templates, a dev container, and housekeeping workflows (stale-issue closure, SLSA provenance on releases, closed-issue locking).

What this means operationally:

  1. No production runtime to operate. There are no servers to patch, no databases to back up, no queues to drain. "Operating" the project is authoring content and reviewing pull requests.
  2. The translation pipeline is the most complex subsystem. It runs as a GitHub Action and is the single largest source of repository churn — most of the 17,000+ tracked files are translation artifacts.
  3. Sub-projects (Flask, Vue) are illustrative, not production. They are pinned to older, lesson-compatible versions and are not security-hardened. Do not use them as templates for production apps.
  4. Authorship contracts matter more than code quality. Because the project is pedagogical, the authoring conventions (lesson sections, quiz wiring, sketchnote placement) carry more weight than typical software engineering concerns like test coverage.

This guide is organized around those realities.

Note

This documentation is generated from the repository at commit 000d5941. Version numbers, file paths, and configuration values refer to that exact snapshot. Behavior in newer commits may differ.


2. Architecture

The repository has four loosely coupled content systems that share a common top-level layout. There is no service mesh, no inter-process communication, no shared database — each system is a static or self-contained asset. The diagram below shows how they relate.

                    ┌──────────────────────────────────────────┐
                    │            Source of truth               │
                    │   English Markdown + notebooks in repo   │
                    └────────────────────┬─────────────────────┘
                                         │
      ┌──────────────────┬───────────────┼──────────────────────┬───────────────┐
      │                  │               │                      │               │
      ▼                  ▼               ▼                      ▼               ▼
┌───────────┐   ┌────────────────┐  ┌──────────┐       ┌────────────────┐  ┌─────────┐
│  Docsify  │   │ Co-op Trans-   │  │ docsify- │       │  Lesson quizzes│  │   PDF   │
│  static   │   │ lator GitHub   │  │ to-pdf   │       │  rendered by   │  │  output │
│  site     │   │ Action         │  │ (Pup-    │       │  Vue quiz-app  │  │ pdf/    │
│           │   │                │  │  peteer) │       │                │  │         │
└───────────┘   └───────┬────────┘  └────┬─────┘       └────────┬───────┘  └─────────┘
                        │                │                      │
                        ▼                ▼                      ▼
                translations/      pdf/readme.pdf        ff-quizzes.netlify.app
                translated_images/                       (external quiz host)
                                                         + local quiz-app build

2.1 Docsify documentation site (root)

The root index.html is a 27-line Docsify bootstrap that turns the repo into a static documentation site without a build step. Docsify fetches README.md and any linked Markdown on demand from the hosting server. Configuration:

window.$docsify = {
  name: 'Machine Learning for Beginners',
  repo: 'https://github.com/Microsoft/ML-For-Beginners',
  relativePath: true,
  auto2top: true,
}

Theming is pulled from the CDN (docsify-themeable@0/dist/css/theme-simple.css). The .nojekyll file prevents GitHub Pages from rewriting underscore-prefixed paths. A sidebar at docs/_sidebar.md provides the navigation tree.

Why this matters: every Markdown file in the repo is potentially linkable from the site. When authoring, assume that any relative link in a lesson README will resolve correctly via Docsify's relativePath: true mode.

2.2 Translation pipeline

Translations live under translations/{lang-code}/... mirroring the English tree, and translated images live under translated_images/. Both are generated artifacts produced by the Co-op Translator GitHub Action (see §6). They are committed to the repo rather than built on demand because Docsify has no build step and the site must serve pre-translated files.

Supported languages at this snapshot include: ar, bg, bn, cs, da, de, el, en, es, fa, fi, fr, he, hi, hk, hr, hu, id, it, ja, ko, lt, mo, mr, ms, nl, ne, no, pa, pl, pt, ro, ru, sk, sl, sr, sv, sw, ta, te, th, tl, tr, tw, uk, ur, vi, zh-CN, zh-TW, among others.

2.3 Quiz system

Quizzes are authored as data in Vue components under quiz-app/src/ and consumed in two places:

  1. Inline in the lesson README — each lesson links to the pre- and post-lecture quiz on the external host https://ff-quizzes.netlify.app/en/ml/. This is the path students actually use.
  2. Locally via the quiz-app — teachers or offline classrooms can run npm run serve in quiz-app/ to host the same quizzes on localhost, or deploy them to Azure Static Web Apps (see §11.3).

The quiz-app is a Vue 3 SPA with vue-router for lesson navigation and vue-i18n for in-app translation. It is version-pinned to Vue CLI 5 (@vue/cli-service ~5.0.8) and Vue 3.5.12.

2.4 Demo Flask web app (Lesson 9)

3-Web-App/1-Web-App/solution/web-app/app.py is a 20-line Flask application that loads a pickled scikit-learn model and predicts "likely country of a UFO sighting" from form input:

from flask import Flask, request, render_template
import pickle, numpy as np
app = Flask(__name__)
model = pickle.load(open("../ufo-model.pkl", "rb"))
@app.route("/predict", methods=["POST"])
def predict():
    int_features = [int(x) for x in request.form.values()]
    final_features = [np.array(int_features)]
    prediction = model.predict(final_features)
    countries = ["Australia", "Canada", "Germany", "UK", "US"]
    return render_template("index.html",
        prediction_text="Likely country: {}".format(countries[output]))

requirements.txt: scikit-learn, pandas, numpy, flask. This is a teaching artifact — see §10 for the security properties you must explicitly call out when students use it as a template.

2.5 PDF generation

docsifytopdf.js configures docsify-to-pdf (a Puppeteer wrapper) to crawl docs/_sidebar.md and emit pdf/readme.pdf. The top-level package.json exposes this as npm run convert. Output is checked into the repo under pdf/.

module.exports = {
  contents: ['docs/_sidebar.md'],
  pathToPublic: 'pdf/readme.pdf',
  pdfOptions: { margin: { top: '100px', bottom: '100px' } },
  removeTemp: true,
  emulateMedia: 'print',
};

3. Repository Layout

ML-For-Beginners/
├── 1-Introduction/          Lessons 1–4: ML intro, history, fairness, tools
├── 2-Regression/            Lessons 1–4: regression, Scikit-learn pipeline
├── 3-Web-App/               Lesson 1: Flask web app wrapping a trained model
├── 4-Classification/        Lessons 1–4: classification, cuisine dataset
├── 5-Clustering/            Lessons 1–2: K-Means, Nigerian music dataset
├── 6-NLP/                   Lessons 1–5: NLP tasks, translation, sentiment
├── 7-TimeSeries/            Lessons 1–3: time series, ARIMA, SVR
├── 8-Reinforcement/         Lessons 1–2: Q-learning, Gym environment
├── 9-Real-World/            Post-script: ML in production
├── docs/
│   └── _sidebar.md          Docsify navigation, also the TOC for PDF export
├── quiz-app/                Vue 3 pre/post-lecture quiz SPA
│   ├── src/
│   │   ├── App.vue, main.js
│   │   ├── router/          vue-router config
│   │   ├── views/           Lesson quiz views
│   │   ├── components/      Shared UI
│   │   └── assets/          Translation JSON files
│   ├── public/
│   ├── package.json         Vue CLI 5 + Vue 3.5.12
│   └── README.md            Quiz-app build/deploy docs
├── translations/            {lang-code}/ mirror of English content (generated)
├── translated_images/       Translated image assets (generated)
├── sketchnotes/             Lesson cover sketchnotes (Nitya Narasimhan)
├── images/                  Shared imagery, favicon
├── .devcontainer/           VS Code dev container (Python 3.10-bullseye)
├── .github/
│   ├── workflows/           stale.yml, lock.yml, SLSA publish
│   ├── ISSUE_TEMPLATE/
│   ├── PULL_REQUEST_TEMPLATE/
│   └── chatmodes/           Copilot chat modes for curriculum authoring
├── README.md                Master curriculum table, sparse-checkout recipe
├── AGENTS.md                Pre-structured project overview (for AI agents)
├── TROUBLESHOOTING.md       Lesson-by-lesson error recipes
├── for-teachers.md          GitHub Classroom integration notes
├── CONTRIBUTING.md          Microsoft CLA + community translation note
├── SECURITY.md              MSRC reporting boilerplate
├── SUPPORT.md               Issue + Discord channels
├── CODE_OF_CONDUCT.md       Microsoft Open Source CoC pointer
├── LICENSE                  MIT
├── package.json             Root: docsify-to-pdf devDependency
├── docsifytopdf.js          PDF export config
├── index.html               Docsify bootstrap
├── .nojekyll                Disable Jekyll processing on GitHub Pages
├── pdf/                     Checked-in PDF exports
├── PyTorch_Fundamentals.ipynb  Supplementary PyTorch notebook (~73 KB)
└── .gitignore

Inside each lesson directory the layout is:

{N}-Topic/{lesson-number}-{lesson-name}/
├── README.md                Lesson body (English source of truth)
├── notebook.ipynb           Python Jupyter (when applicable)
├── solution/                Reference implementation
│   ├── notebook.ipynb
│   └── R/                   Tidymodels equivalent (when applicable)
├── assignment.md            End-of-lesson exercise
├── images/                  Lesson-local figures
└── translations/            {lang-code}/ per-lesson mirror (generated)

4. System Requirements

4.1 Authoring machine

Component Version Notes
Git 2.25+ Required for sparse-checkout filter
Python 3.9–3.11 Lessons and solution notebooks; 3.10 matches the devcontainer
Jupyter / JupyterLab any recent Install via pip install notebook or conda install jupyter
Node.js 18 LTS or 20 LTS Required for quiz-app and docsify-to-pdf
npm bundled with Node npm install from repo root pulls docsify-to-pdf
R 4.1+ Only for R-track lessons; see solution/R/
RStudio 2022.02+ Recommended when editing .Rmd files

4.2 Curriculum Python dependencies

There is no top-level requirements.txt. Each lesson that runs code either imports from the standard scientific-Python stack (scikit-learn, pandas, numpy, matplotlib, seaborn) or declares its own deps inline. The demo Flask app is the only place where a pinned list lives:

# 3-Web-App/1-Web-App/solution/web-app/requirements.txt
scikit-learn
pandas
numpy
flask

For the full curriculum we recommend creating a conda environment with:

conda create -n ml4beginners python=3.10
conda activate ml4beginners
conda install -c conda-forge jupyter scikit-learn pandas numpy matplotlib seaborn
pip install flask

4.3 Optional: dev container

The repo ships a VS Code dev container at .devcontainer/:

  • Base image: mcr.microsoft.com/vscode/devcontainers/python:0-3.10-bullseye
  • Pylance + Python linting (pylint) preconfigured
  • Node version: "none" — students wanting to run the quiz-app or docsify-to-pdf must edit devcontainer.json to set NODE_VERSION to lts/* or rebuild with --build-arg NODE_VERSION=18.

Open the repo in VS Code → Reopen in Container and everything Python-side works out of the box.

4.4 GitHub/org requirements for deployment

  • Docsify site hosting — GitHub Pages (free) or any static host. The site needs only index.html, README.md, and the Markdown tree.
  • Quiz-app deployment — see §11.3. Requires an Azure subscription and the Static Web Apps service, or any static host.
  • Co-op Translator — the Action requires repository secrets for the translation provider; see §6.3.

5. Lesson Authoring Contract

The single most important constraint when editing or adding content: lessons follow a 10-section structure. Deviations break the Docsify sidebar, the quiz wiring, and the expectations set in the root README.

5.1 Lesson Markdown template

# Lesson Title

![sketchnote](../../sketchnotes/{lesson}.jpg)
> Sketchnote by [Tomomi Imura](https://twitter.com/girlie_mac)

## [Pre-lecture quiz](https://ff-quizzes.netlify.app/en/ml/)

### Introduction
Two to four paragraphs framing why the learner should care and
what they will be able to do after.

### What you'll learn
- Bulleted skills list
- Written in outcome language ("You will be able to …")

### Prerequisites
- References to earlier lessons
- Required libraries installed

## {Main body — H2-level sections specific to the topic}
### H3 subsections with code blocks, images, and exercises

## 🚀Challenge
A stretch exercise that goes beyond the lesson.

## [Post-lecture quiz](https://ff-quizzes.netlify.app/en/ml/)

## Review & Self Study
Three to five external links for deeper reading.

## Assignment
[Assignment Title](assignment.md)

5.2 Quiz linking rules

  • Pre-lecture quiz link is always immediately after the sketchnote H1 title and before the Introduction.
  • Post-lecture quiz link is immediately after the main body, before "Review & Self Study".
  • Both links point at the external host https://ff-quizzes.netlify.app/en/ml/. The quiz-id is resolved from the URL path configured inside the quiz-app. Do not link to localhost or a relative path — translated lessons rely on the external host being resolvable.

5.3 Images and sketchnotes

  • Lesson-local images live in {lesson}/images/ and are referenced relatively: ![caption](images/foo.png).
  • Cover sketchnotes live in sketchnotes/ at the repo root and are referenced as ../../sketchnotes/{name}.jpg.
  • All images are candidates for translation. The Co-op Translator walks the tree, extracts text, and writes translated copies under translated_images/{lang}/. Do not hand-edit anything in translated_images/ — it is regenerated.

5.4 Code blocks

  • Fenced with a language tag: ```python, ```r, ```bash, ```javascript.
  • No language tag = no syntax highlighting in Docsify and no translation exemption. Always tag code blocks so Co-op Translator leaves them alone.
  • Shell commands prefer POSIX form; call out Windows differences with a blockquote: > On Windows, use \ instead of /.`

5.5 Notebooks

  • Notebooks are the actual teaching artifact for any lesson that runs code. The Markdown README explains the why; the notebook delivers the how.
  • Use solution/notebook.ipynb for the reference implementation and keep the lesson-level notebook.ipynb as a scaffolded "fill in the blanks" version for students.
  • For R-track lessons, mirror under solution/R/ using tidymodels.

5.6 Assignment files

Each lesson's end-of-lesson exercise is a standalone assignment.md with this template:

# Assignment Title

## Instructions
What the student must do.

## Rubric
| Exemplary | Adequate | Needs Improvement |
|-----------|----------|-------------------|
|  …        |  …       |  …                |

The rubric table is expected by graders; omitting it breaks the grading workflow documented in for-teachers.md.

5.7 README master table

README.md at the repo root carries the canonical 26-lesson inventory as a Markdown table. When adding or renumbering a lesson, update this table as the same commit — the sidebar, the quiz IDs in quiz-app/, and the translation outputs all key off lesson ordering.


6. Translation Subsystem

6.1 What Co-op Translator does

Co-op Translator is an Azure-published GitHub Action that:

  1. Walks the repository for English Markdown, notebooks, and images.
  2. Sends text to an LLM translator (typically Azure OpenAI).
  3. Writes translated Markdown/notebooks under translations/{lang-code}/.
  4. Renders translated images (preserving layout) under translated_images/{lang-code}/.
  5. Commits the results back to the repo via a workflow-authored commit.

This is why most of the ~17,000 tracked files are translation artifacts — a single lesson plus its image set expands across 50 language codes.

6.2 Languages supported

The language list is driven by a Co-op Translator config (typically co-op-translator-config.yaml or similar). To change the language set, edit that config, not the committed translation trees. The set visible in this snapshot includes Western European, Slavic, East Asian, Middle Eastern, South Asian, and Southeast Asian language groups — a full inventory is in translations/.

6.3 Required secrets and permissions

For the Action to run in your fork you need:

  • Azure OpenAI endpoint and API key (repository secrets)
  • contents: write permission on the workflow (to commit translated files)
  • pull-requests: write if you configure the Action to open PRs instead of pushing directly

Consult the Co-op Translator README for the exact secret names at the commit you are using.

6.4 Community translation override

Machine translations can be overridden by human volunteers. CONTRIBUTING.md is explicit:

Important: when translating text in this repo, please ensure that you do not use machine translation. We will verify translations via the community, so please only volunteer for translations in languages where you are proficient.

This means human-translated content should land as direct edits inside translations/{lang}/ and must be protected from being overwritten on the next Action run. The review policy is: a human translation, once merged, is treated as ground truth for that language; re-runs of Co-op Translator must either skip files marked as human-reviewed or be constrained to new content only. If you operate the Action, audit its config for this behavior before scheduling large re-runs.

6.5 Review responsibilities for maintainers

Task Owner Cadence
Triage translation PRs from volunteers Curriculum maintainer Per PR
Audit Co-op Translator output on new lessons Curriculum maintainer Per new lesson merge
Add/remove supported languages Lead maintainer Ad hoc
Investigate garbled translation reports Translation reviewer for that language Per issue

7. Sub-Project: Flask Web App (3-Web-App/)

7.1 Purpose

Teaches students how to serialize a trained scikit-learn model with pickle and serve predictions through a minimal Flask route. It is intentionally minimal — the lesson goal is "a trained model is just a file; Flask is just a function router" — not production deployment.

7.2 Layout

3-Web-App/
└── 1-Web-App/
    ├── notebook.ipynb           Lesson notebook: train + pickle ufo-model.pkl
    ├── README.md                Lesson walkthrough
    ├── assignment.md            End-of-lesson challenge
    └── solution/
        ├── ufo-model.pkl        Pre-trained classifier (checked in)
        └── web-app/
            ├── app.py           Flask application (full source in §2.4)
            ├── requirements.txt scikit-learn, pandas, numpy, flask
            ├── static/
            │   └── css/styles.css
            └── templates/
                └── index.html   Single-page form + prediction display

7.3 Running locally

cd 3-Web-App/1-Web-App/solution/web-app
python -m venv .venv && source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python app.py
# Flask dev server on http://127.0.0.1:5000 with debug=True

7.4 Security properties (important to call out when teaching)

Property State Reason What students must know before reuse
pickle.load on a model file Used Teaches the canonical scikit-learn persist pattern pickle executes arbitrary code on load; never load a .pkl from an untrusted source
debug=True in app.run() Used Shows tracebacks in the browser when students break things Never set in production — the Werkzeug debugger is an RCE if exposed
Input validation Absent int_features = [int(x) for x in request.form.values()] is the only coercion Any field that is not an int raises ValueError — which debug=True then exposes. In production, validate and coerce explicitly.
Authentication Absent Irrelevant to the teaching goal Add Flask-Login / a reverse proxy with auth for any real deployment
CSRF protection Absent Form posts use no token Add Flask-WTF for real forms
Content Security Policy Absent Templates render directly Set headers in front of Flask in production
HTTPS Absent Dev server is HTTP Terminate TLS at the proxy
Rate limiting Absent Dev server is single-threaded Use a production WSGI server + gateway

All of these are deliberate teaching tradeoffs. When a student forks this as a template, the above table is the conversation to have with them.

7.5 Swapping the model

The lesson's own notebook.ipynb trains the classifier and writes ufo-model.pkl. To replace the model:

  1. Re-run the notebook (or train in your own script) and emit a .pkl with a compatible predict() signature (takes an n_samples × n_features 2D array, returns an array of class indices).
  2. Replace 3-Web-App/1-Web-App/solution/ufo-model.pkl.
  3. Update the countries list in app.py so the class index → label mapping stays consistent.

8. Sub-Project: Vue Quiz App (quiz-app/)

8.1 Purpose

Locally hostable version of the pre/post-lecture quizzes. The canonical student experience uses the externally hosted ff-quizzes.netlify.app, but teachers can self-host for air-gapped classrooms, for LMS integration, or when the external host is unreachable.

8.2 Stack at this commit

Package Version Role
vue ^3.5.12 UI framework
vue-router ^3.5.3 Client-side routing (note: paired with Vue 3 — intentional lesson-era pinning)
vue-i18n ^8.26.7 In-app language switching
@vue/cli-service ~5.0.8 Build tool (Vue CLI 5)
eslint ^9.33.0 Linter; eslint-plugin-vue ^10.4.0
core-js ^3.6.5 Polyfill

The quiz-app also lives under src/ with:

quiz-app/src/
├── App.vue         Root component
├── main.js         Bootstrap: router + i18n mount
├── router/         Routes per lesson/quiz
├── views/          Per-quiz views
├── components/     Shared UI (Quiz, Question, Result)
└── assets/         Per-language quiz JSON

8.3 Scripts

Command Action
npm install Install deps into quiz-app/node_modules/
npm run serve Vue CLI dev server with HMR (default port 8080)
npm run build Production bundle to quiz-app/dist/
npm run lint ESLint with plugin:vue/essential + eslint:recommended

8.4 Adding a quiz

  1. Add the question objects to the appropriate language JSON under quiz-app/src/assets/translations/ (or wherever the quiz data lives for the version you are on).
  2. If it is a new lesson, add a route in quiz-app/src/router/ and a view in quiz-app/src/views/.
  3. Update the root README.md master table and the lesson README's quiz links so the quiz-id matches.
  4. npm run build and test the production bundle locally before pushing.

8.5 Deployment to Azure Static Web Apps

The quiz-app's README documents the Azure SWA flow. Summary of the Action config:

uses: Azure/static-web-apps-deploy@v1
with:
  azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
  repo_token: ${{ secrets.GITHUB_TOKEN }}
  action: "upload"
  app_location: "/quiz-app"      # App source code path
  api_location: ""               # No API
  output_location: "dist"        # Vue CLI build output

Portal steps (condensed from quiz-app/README.md):

  1. Fork the repo.
  2. Azure Portal → Create resource → Static Web App. Select GitHub as source, authorize Azure, pick the fork and branch.
  3. Build preset: Vue. App location: /quiz-app. Output location: dist.
  4. Azure writes a workflow file at .github/workflows/azure-static-web-apps-<name>.yml and runs it on every push to the selected branch.

9. Classroom Delivery Patterns

The for-teachers.md file is short but prescriptive. The core patterns:

Because GitHub Classroom expects one repo per assignment, teachers extract each lesson folder into its own repo so Classroom can assign them individually:

  1. Fork this repo.
  2. For each lesson you want to assign, extract the lesson folder into a standalone repo.
  3. In GitHub Classroom, create an assignment pointing at the lesson repo.
  4. Each student gets an auto-forked copy; submissions are managed through Classroom.

9.2 Repo-as-is (informal or cohort-based delivery)

Simplest pattern — the teacher just directs students to specific lessons in the upstream repo. Quizzes and assignments are submitted via:

  • Public submission — students file GitHub Issues on the teacher's classroom repo with their answers.
  • Private submission — students fork each lesson to a private repo, grant the teacher access, and submit via issues on those private forks.

9.3 Online classroom (Zoom/Teams/breakout rooms)

The recommended pattern in for-teachers.md:

  • Pre-lecture quiz → breakout rooms of 3–4. Each room submits collective answers as an issue on the classroom repo before the lecture starts.
  • Lecture → live-coded walkthrough of the lesson notebook.
  • Breakout work → students work the assignment in pairs, TAs rotate rooms.
  • Post-lecture quiz → back in the main room, quick recap.

9.4 Feedback channel

Teachers are asked to fill the feedback form referenced in for-teachers.md so Microsoft can iterate on the curriculum.


10. Security & Trust Boundary

10.1 Reporting vulnerabilities

SECURITY.md directs all reports to the Microsoft Security Response Center (MSRC):

Never report via a public GitHub issue. The curriculum is watched by students — a public disclosure would expose them to copy-paste exploitation before MSRC can respond.

10.2 What counts as a vulnerability here

Because the repo has no production runtime, the attack surface is:

Surface Concern Reporting route
Flask demo app in student forks RCE via debug=True Werkzeug console; pickle-load of hostile .pkl; form-value coercion MSRC (as the upstream template)
Quiz-app dependencies Supply-chain CVEs in Vue / vue-cli / eslint-plugin-vue MSRC or Dependabot PR
docsify-to-pdf Puppeteer/Chromium CVEs reachable during PDF generation MSRC or Dependabot PR
Notebooks Embedded `!curl … sh` or other remote-execution patterns
Translations Garbage content from MT pipeline that alters meaning in harmful ways GitHub issue (quality), MSRC (if intentional malicious insertion)

10.3 Intentional non-security for teaching clarity

The demo Flask app runs with debug=True, loads a local pickle, and has no auth. This is documented as intentional. The authoring contract is that lessons optimize for learner clarity; the operational mitigation is §7.4 — when reusing this code, the security table is the conversation.

10.4 Dependency hygiene

  • Dependabot is available (free for public repos on GitHub); enabling it catches CVEs in the quiz-app and docsify-to-pdf stacks automatically.
  • The .github/workflows/generator-generic-ossf-slsa3-publish.yml workflow produces SLSA level-3 provenance on releases. It currently ships artifact1/artifact2 placeholders — adapt the Build artifacts step before cutting a tagged release if you want provenance to cover real binaries.

10.5 Secret handling

The repo holds no secrets. The Co-op Translator workflow consumes secrets (Azure OpenAI keys) stored in GitHub repository settings. When forking:

  • Do not copy secrets from the upstream — they are not accessible anyway.
  • Generate your own Azure OpenAI deployment and add its credentials as repo secrets before enabling the Action.

11. Operations Reference

11.1 Building the Docsify site

Docsify has no build step. Verifying the site locally:

# From repo root
npm install -g docsify-cli    # one-time
docsify serve .               # http://localhost:3000

Deployment: push to GitHub with Pages enabled for the branch. The .nojekyll file is already in place so Pages serves the tree as-is.

11.2 Generating the PDF

npm install            # pulls docsify-to-pdf@0.0.5 from root package.json
npm run convert        # runs node_modules/.bin/docsify-to-pdf
# Output: pdf/readme.pdf

docsify-to-pdf requires a Chromium binary (bundled via Puppeteer). On Linux CI you need the usual Chromium deps (libnss3, libatk-bridge2.0-0, libcups2, libdrm2, libxcomposite1, libxrandr2, libgbm1, libxkbcommon0, libasound2).

11.3 Deploying the quiz-app

Two supported paths:

Target Mechanism Detail
Azure Static Web Apps GitHub Action Azure/static-web-apps-deploy@v1 See §8.5. Preset: Vue. app_location /quiz-app, output_location dist.
Any static host (Netlify, Vercel, S3+CloudFront, GitHub Pages) npm run build and upload quiz-app/dist/ No SPA routing gotchas — vue-router uses hash mode by default in this config.

11.4 Running Co-op Translator

Run on demand via the Action UI (workflow_dispatch) or on a schedule. For a full re-translation of the repo:

  1. Confirm Azure OpenAI quota — a full run hits every English Markdown and every image with text.
  2. Decide the commit policy (direct push vs. PR). PRs are safer but add review overhead.
  3. Kick off the workflow.
  4. Expect a large commit (thousands of files). Use git log --stat on the generated commit to spot-check.

11.5 Repository maintenance workflows

Workflow Trigger Behavior
.github/workflows/stale.yml Cron 35 8 * * * daily Uses actions/stale@v10 to comment on and close issues/PRs with no activity. Labels: no-issue-activity, no-pr-activity.
.github/workflows/lock.yml On issue closed Uses OSDKDev/lock-issues@v1.1 to prevent new comments on closed issues.
.github/workflows/generator-generic-ossf-slsa3-publish.yml workflow_dispatch or release created SLSA level-3 provenance on release artifacts.

Adjusting close timing: edit stale.yml — defaults of actions/stale@v10 apply (typically 60-day warn + 7-day close) unless overridden. Adjusting issue-lock grace: edit the lock.yml step or swap in dessant/lock-threads@v5 for more configuration.

11.6 Sparse-checkout recipe for maintainers

To work with a specific lesson without cloning translations:

git clone --filter=blob:none --no-checkout https://github.com/microsoft/ML-For-Beginners.git
cd ML-For-Beginners
git sparse-checkout init --cone
git sparse-checkout set 2-Regression 3-Web-App docs quiz-app
# Exclude translation noise from the working tree
git sparse-checkout set --no-cone \
    '/*' \
    '!/translations' \
    '!/translated_images'
git checkout main

This trims the working tree from thousands of generated files to only the English source. Cuts clone size by ~95%.


12. Contributing Workflow

12.1 Microsoft CLA (Contributor License Agreement)

Per CONTRIBUTING.md, all non-trivial contributions require a signed Microsoft CLA. The flow:

  1. Open a PR against main.
  2. The CLA-bot auto-comments on the PR with a signing link (first-time contributors).
  3. Sign once at https://cla.microsoft.com — valid across all Microsoft CLA repositories.
  4. The bot re-verifies and labels the PR accordingly.

12.2 Code of Conduct

The repo adopts the Microsoft Open Source Code of Conduct. Reports go to [email removed]. The Code of Conduct FAQ explains enforcement.

12.3 Pull request categories

PR type Expectations Extra steps
Typo / copy fix in English Markdown Single-file PR, no translation update CLA sign-off (one-time)
New lesson content or substantial rewrite Follows §5 authoring contract; includes sketchnote; updates root README table; updates docs/_sidebar.md CLA; re-run Co-op Translator after merge
Human translation Direct edit under translations/{lang}/; marks file as human-reviewed so MT does not overwrite CLA; proficiency declaration in PR description
Quiz change Updates quiz-app JSON and lesson README quiz links in the same PR CLA; npm run lint must pass
Dependency bump quiz-app/package.json or root package.json CLA; verify npm run build locally
Security fix Route through MSRC first — do not open a public PR with an exploit description Per §10.1

12.4 Commit signing

Not required by repo config at this commit, but Microsoft repos commonly adopt DCO or signed commits over time. Check the PR template and main branch protection rules before submitting.

12.5 Issue templates

Located in .github/ISSUE_TEMPLATE/. Use them — triagers depend on the structured fields to route issues. The default templates cover bug reports, feature/content requests, and translation issues.


13. Troubleshooting Runbook (Maintainer View)

A full learner-facing troubleshooting list lives in TROUBLESHOOTING.md. The items below are the maintainer failures that recur and how to triage them.

13.1 "Co-op Translator commit broke lesson N"

Symptom: a translation PR or push lands and a lesson's sidebar link 404s, or the post-lecture quiz link is missing in translations/{lang}/.

Triage:

  1. Diff the generated commit against the English source: git diff HEAD~1 -- translations/{lang}/{lesson-path}/README.md.
  2. Check whether the English README.md uses an uncommon Markdown construct (nested code fence, HTML embed) that the translator stripped.
  3. Fix the English source to use the standard constructs, then re-run the Action for that language only.

13.2 Docsify site shows a blank page after a push

Symptom: Docsify hits a parsing error on a Markdown file and stops rendering.

Triage:

  1. Open browser DevTools → Console. Docsify prints the failing URL.
  2. Load that Markdown file directly in the browser — invalid YAML front matter or unbalanced fences are common.
  3. For translated files, look for a dropped closing ``` — the Co-op Translator historically has had sporadic issues with fence preservation.

13.3 npm run convert hangs during PDF generation

Symptom: docsify-to-pdf launches Chromium and never completes.

Triage:

  1. On Linux CI, missing Chromium libs — install per §11.2.
  2. On large repos (this one qualifies), memory pressure. Increase the CI runner, or scope docsifytopdf.js contents: to a subset of docs/_sidebar.md.
  3. Network timeouts on CDN-loaded theme — retry, or self-host the Docsify theme.

13.4 Quiz-app npm install fails on a fresh clone

Symptom: peer-dependency warnings escalate to errors with newer npm versions.

Triage:

  1. The package set was authored for npm 7/8. On npm 9+ you may need --legacy-peer-deps.
  2. If a devDependency (e.g. babel-eslint) is deprecated, do not unilaterally bump it — it affects how lesson-era quizzes tokenize. File a PR and test npm run build + the generated SPA against the full quiz set.

13.5 Stale workflow closes an active issue

Symptom: a discussion issue is auto-closed by actions/stale@v10 mid-conversation.

Triage:

  1. Add a non-stale label (e.g. pinned or keep) and configure stale.yml's exempt-issue-labels to exclude it.
  2. Reopen the issue. The lock.yml workflow locks issues on close, so a freshly reopened issue is unlocked again.

13.6 SLSA provenance workflow fails on release

Symptom: release job succeeds but the provenance job errors with signing/permission failures.

Triage:

  1. The provenance job needs id-token: write and contents: write. Confirm the workflow block still includes them.
  2. The called workflow is pinned to slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0. If GitHub has deprecated the runner image or the action version, bump both and re-run.

14. Forking Guidance

Common reasons to fork:

Reason What to change What to leave alone
Running a cohort-specific course README.md cohort notes, for-teachers.md Lesson content, quiz IDs, translations
Translating to a new language Add language in Co-op Translator config; may seed translations/{new-lang}/ with a run English source (never branch English lesson content for translation work)
Derivative curriculum (different order, extra lessons) Lesson tree, README.md master table, docs/_sidebar.md Microsoft-specific files (CLA ref, SECURITY.md, CODE_OF_CONDUCT.md) unless you are replacing them with your own
Training-only material for an org Private fork, add org-specific material alongside Upstream lesson folders — makes future rebasing easier

Attribution: The root README and LICENSE (MIT) document attribution. If you use the curriculum under MIT, keep LICENSE and the author credits in AGENTS.md / README.md. Translations retain the upstream authorship notice at the top (the Co-op Translator adds a standard attribution block).

What to strip before re-publishing under your own brand:

  • SECURITY.md — replace with your org's reporting channel; MSRC is not appropriate outside Microsoft.
  • CONTRIBUTING.md — the Microsoft CLA does not apply to a non-Microsoft fork.
  • SUPPORT.md — swap in your support channels.
  • .github/ISSUE_TEMPLATE/ and PULL_REQUEST_TEMPLATE/ — adjust to match your processes.

15. External Dependencies and References

15.1 Build-time dependencies

Package Scope Role Pin location
docsify-to-pdf@0.0.5 root devDependency PDF export package.json
vue@^3.5.12 quiz-app dependency SPA framework quiz-app/package.json
vue-router@^3.5.3 quiz-app dependency Routing quiz-app/package.json
vue-i18n@^8.26.7 quiz-app dependency i18n quiz-app/package.json
@vue/cli-service@~5.0.8 quiz-app devDependency Build quiz-app/package.json
eslint@^9.33.0 quiz-app devDependency Linting quiz-app/package.json
eslint-plugin-vue@^10.4.0 quiz-app devDependency Vue lint rules quiz-app/package.json
flask Lesson 9 runtime Web framework 3-Web-App/1-Web-App/solution/web-app/requirements.txt
scikit-learn, pandas, numpy Lesson 9 + most Python lessons ML stack same requirements.txt

15.2 Runtime external hosts

Host Purpose
https://ff-quizzes.netlify.app/en/ml/ External quiz host referenced from every lesson README
https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js Docsify runtime for the docs site
https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css Docs site theme
https://aka.ms/ml-beginners Canonical short URL for the curriculum
https://aka.ms/foundry/discord Community Discord (#ml-for-beginners channel)
https://cla.microsoft.com Microsoft CLA signing
https://msrc.microsoft.com/create-report MSRC vulnerability reporting

15.3 Upstream references


16. Quick Reference

16.1 Key paths

Path What it is
/README.md Master curriculum table — update on any lesson add/remove
/AGENTS.md AI-agent-readable project overview — keep in sync with README
/docs/_sidebar.md Docsify nav + PDF TOC source
/index.html Docsify bootstrap; change site name/repo URL here
/docsifytopdf.js PDF export config
/quiz-app/src/ Vue quiz SPA source
/3-Web-App/1-Web-App/solution/web-app/app.py Demo Flask app
/translations/{lang}/ Generated translations — do not hand-edit MT output
/translated_images/{lang}/ Generated image translations
/.github/workflows/ stale, lock, SLSA
/.devcontainer/ VS Code dev container

16.2 Commands cheat sheet

# Author and preview site
docsify serve .

# PDF export
npm install && npm run convert    # writes pdf/readme.pdf

# Quiz-app dev
cd quiz-app && npm install && npm run serve    # http://localhost:8080
cd quiz-app && npm run build                   # dist/
cd quiz-app && npm run lint                    # ESLint

# Flask demo
cd 3-Web-App/1-Web-App/solution/web-app
pip install -r requirements.txt && python app.py   # http://127.0.0.1:5000

# Sparse-checkout without translation noise
git clone --filter=blob:none --no-checkout https://github.com/microsoft/ML-For-Beginners.git
cd ML-For-Beginners
git sparse-checkout init --cone
git sparse-checkout set --no-cone '/*' '!/translations' '!/translated_images'
git checkout main

16.3 Decision matrix: where to report or ask

Situation Channel
Bug in lesson content or broken link GitHub Issue (use the issue template)
Security vulnerability MSRC: https://msrc.microsoft.com/create-report
Translation quality problem GitHub Issue; tag the language
Code-of-conduct concern [email removed]
Feature request GitHub Issue with enhancement label
Community help / classroom questions Discord #ml-for-beginners at aka.ms/foundry/discord
Teacher feedback Form linked in for-teachers.md
Tooling/translation pipeline Co-op Translator repo: github.com/Azure/co-op-translator