1. Architecture Overview
Web Dev for Beginners is a 24-lesson, project-based web development curriculum maintained as a monorepo on GitHub. The repository is structured as a collection of independent lesson modules — each containing markdown content, runnable code projects, visual assets, and translations — organized around progressive learning goals.
The curriculum is not a single application. It is a coordinated set of static lesson content (markdown + images), seven independent runnable sub-projects (each with its own technology stack), a Vue 3 quiz application, and a translation infrastructure spanning 50+ languages.
Repository Architecture
Web-Dev-For-Beginners/
├── 1-getting-started-lessons/ Lessons 1–3: Programming intro, GitHub, accessibility
├── 2-js-basics/ Lessons 4–7: Data types, functions, decisions, loops
├── 3-terrarium/ Lessons 8–10: HTML/CSS/DOM project
├── 4-typing-game/ Lesson 11: Event-driven JS project
├── 5-browser-extension/ Lessons 12–14: Browser extension project (webpack)
├── 6-space-game/ Lessons 15–20: Canvas + OOP game project
├── 7-bank-project/ Lessons 21–24: SPA + REST API project
│ └── api/ Express.js REST API server
├── 8-code-editor/ Lesson 25: VS Code usage
├── 9-chat-project/ AI chat: FastAPI backend + JS frontend
├── 10-ai-framework-project/ LangChain tool-calling examples (Python)
├── memory-game/ Bonus: React 19 / Next.js 16 card game
├── quiz-app/ Vue 3 + Vite quiz SPA
├── Git-Basics/ Supplementary Git tutorials
├── sketchnotes/ Visual lesson summaries (images)
├── teaching-files/ Classroom support materials
├── lesson-template/ Template for creating new lessons
├── translated_images/ Localized sketchnotes (50+ languages)
├── translations/ Full lesson translations (50+ languages)
├── pdf/ Generated PDF output
├── docsifytopdf.js PDF generation config (Puppeteer-based)
└── package.json Root: docsify-to-pdf devDependency only
Note
The 13,611 file count is driven almost entirely by translations and translated images. The English source content (lessons + projects) accounts for fewer than 500 files. Each translation language adds ~240 files (lesson markdown + localized sketchnotes).
Component Inventory
| Component | Path | Technology | Role |
|---|---|---|---|
| Lesson content | {1..8}-*/README.md |
Markdown + Mermaid diagrams | Core curriculum material |
| Terrarium project | 3-terrarium/solution/ |
Vanilla JS, HTML, CSS | Teaches closures and DOM events |
| Typing game | 4-typing-game/solution/ |
Vanilla JS, HTML | Teaches event handling and timing |
| Browser extension | 5-browser-extension/solution/ |
JS + webpack + axios | Teaches browser APIs and bundling |
| Space game | 6-space-game/solution/ |
Vanilla JS, Canvas API | Teaches OOP and game development |
| Bank project API | 7-bank-project/api/ |
Express.js + body-parser + cors | REST API for bank app |
| Bank project client | 7-bank-project/solution/ |
Vanilla JS SPA | Teaches routing and state management |
| Chat backend | 9-chat-project/solution/backend/python/ |
FastAPI + uvicorn + OpenAI SDK | AI chat API |
| Chat frontend | 9-chat-project/solution/frontend/ |
Vanilla JS | Chat UI with typing indicators |
| AI framework | 10-ai-framework-project/code/python/ |
LangChain + OpenAI | LLM tool-calling demos |
| Memory game | memory-game/ |
React 19, Next.js 16, Tailwind CSS 4 | Card matching game |
| Quiz app | quiz-app/ |
Vue 3.4, Vue Router 4.3, Vite 6.4 | Pre/post-lesson quiz platform |
| PDF generator | docsifytopdf.js |
docsify-to-pdf 0.0.5 (Puppeteer) | Curriculum PDF export |
| Translations | translations/{lang}/ |
Markdown | 50+ language community translations |
| Translated images | translated_images/{lang}/ |
WebP images | Localized sketchnotes |
Technology Stack
| Layer | Technologies |
|---|---|
| Lesson content | Markdown, Mermaid diagrams, GitHub-Flavored Markdown |
| Client-side projects | Vanilla JavaScript (ES6+), HTML5, CSS3, Canvas API |
| Build tools | webpack 5 (browser extension), Vite 6 (quiz app), Next.js Turbopack (memory game) |
| Server-side | Node.js + Express 4 (bank API), Python + FastAPI + uvicorn (chat API) |
| AI/ML | LangChain (OpenAI provider), GitHub Models API |
| Frontend frameworks | Vue 3 (quiz app), React 19 + Next.js 16 (memory game) |
| CSS | Tailwind CSS 4 (memory game), vanilla CSS (all other projects) |
| Static serving | npx http-server (space game, chat frontend) |
| Translation | Azure AI Co-op Translator (automated), community PRs (manual) |
Data Flow — Bank Project (Most Complex Sub-Project)
Browser (SPA client)
│
├── localStorage ← accounts[], savedAccount, schemaVersion
│ │
│ └── storage event → cross-tab sync
│
└── fetch → Bank API (Express, port 5000)
│
├── GET / → welcome message
├── POST /accounts → create account (in-memory)
├── GET /accounts/:user → get account
├── DELETE /accounts/:user → delete account
├── POST /accounts/:user/transactions → add transaction
└── DELETE /accounts/:user/transactions/:id → delete transaction
The client solution operates in dual mode: it can work standalone with localStorage persistence (no server needed), or connect to the Express API for server-side demonstrations.
2. System Requirements
Development Environment
| Requirement | Version | Notes |
|---|---|---|
| Git | Any modern version | Required for cloning |
| Node.js | ≥ 10 (bank API), ≥ 18 (extensions, memory game, quiz app) | LTS recommended |
| npm | ≥ 9 (for extension and memory game package.json engines field) |
Ships with Node.js |
| Python | ≥ 3.8 | AI projects only (sections 9–10) |
| pip | Any | For Python dependency installation |
| Browser | Chrome, Edge, Firefox, or Safari | Chrome/Edge preferred for extension development |
| Disk | ~200 MB (clone), ~500 MB (with all node_modules) | Translations dominate file count |
Per-Project Dependencies
| Project | Runtime Dependencies | Dev Dependencies |
|---|---|---|
| Root | — | docsify-to-pdf@0.0.5 |
| Browser extension | axios@^1.13.5 |
webpack@^5.105, webpack-cli@^5.1.4 |
| Space game (all stages) | — | — (package.json has http-server via npx) |
| Bank API | express@^4.21.2, body-parser@^1.20.3, cors@^2.8.5 |
eslint@^7.5, prettier@^2.0.5 |
| Memory game | next@16.1.5, react@19.1.0, react-dom@19.1.0 |
tailwindcss@^4, eslint-config-next@15.5.2 |
| Quiz app | vue@^3.4.29, vue-router@^4.3.3 |
vite@^6.4.1, @vitejs/plugin-vue@^5.2.4, eslint@^8.57, eslint-plugin-vue@^9.23 |
| Chat backend | openai, fastapi, uvicorn, python-dotenv |
— |
| AI framework | langchain[openai], requests |
— |
Important
Each sub-project has its own
package.jsonwith its ownnode_modules. There is no monorepo-level workspace or shared dependency management. Runningnpm installat the root only installsdocsify-to-pdf.
3. Configuration Reference
Configuration Files
| File | Format | Location | Purpose |
|---|---|---|---|
package.json |
JSON | Root | PDF generation script (npm run convert) |
docsifytopdf.js |
JS module | Root | PDF output options (margins, media type, sidebar source) |
package.json |
JSON | 5-browser-extension/solution/ |
webpack build scripts, axios dependency |
webpack.config.js |
JS | 5-browser-extension/solution/ |
Extension bundling configuration |
manifest.json |
JSON | 5-browser-extension/solution/ |
Browser extension manifest (permissions, popup, icons) |
package.json |
JSON | 6-space-game/solution/ |
http-server start script (port 5000) |
package.json |
JSON | 7-bank-project/api/ |
Express server start, lint, format scripts |
package.json |
JSON | memory-game/ |
Next.js dev/build/start scripts |
jsconfig.json |
JSON | memory-game/, quiz-app/ |
Path alias (@/* → ./src/* or ./*) |
package.json |
JSON | quiz-app/ |
Vite dev server, ESLint |
Environment Variables
| Variable | Type | Default | Description | Required? |
|---|---|---|---|---|
PORT |
Integer | 5000 |
Bank API server listen port | No |
GITHUB_TOKEN |
String | — | GitHub Models API authentication token for AI projects | Yes (AI projects) |
PDF Generation Configuration (docsifytopdf.js)
module.exports = {
contents: ['docs/_sidebar.md'],
pathToPublic: 'pdf/readme.pdf',
pdfOptions: {
margin: { top: '100px', bottom: '100px' }
},
removeTemp: true,
emulateMedia: 'print',
};
| Key | Type | Value | Description |
|---|---|---|---|
contents |
Array | ['docs/_sidebar.md'] |
Table of contents source file |
pathToPublic |
String | 'pdf/readme.pdf' |
Output PDF file path |
pdfOptions.margin |
Object | { top: '100px', bottom: '100px' } |
Page margins for Puppeteer PDF rendering |
removeTemp |
Boolean | true |
Clean up intermediate .md and .html files |
emulateMedia |
String | 'print' |
CSS media type for Puppeteer rendering |
Space Game Settings (Runtime Configuration)
The space game solution stores settings in JavaScript objects at runtime (not persisted to disk):
| Setting | Type | Default | Options |
|---|---|---|---|
difficulty |
String | 'normal' |
easy, normal, hard, insane |
graphics |
String | 'medium' |
low, medium, high, ultra |
musicVolume |
Float | 0.6 |
0.0–1.0 |
sfxVolume |
Float | 0.8 |
0.0–1.0 |
controlScheme |
String | 'wasd' |
wasd, arrows, custom |
muted |
Boolean | false |
— |
Difficulty parameters:
| Difficulty | Enemy Spawn Rate (s) | Enemy Speed (px/s) | Max Enemies |
|---|---|---|---|
easy |
1.6 | 60 | 12 |
normal |
1.2 | 90 | 16 |
hard |
0.9 | 120 | 22 |
insane |
0.7 | 160 | 28 |
Graphics parameters:
| Level | Glow Effects | Blur | Star Layers |
|---|---|---|---|
low |
Off | 0 | 1 |
medium |
Off | 0 | 2 |
high |
On | 0 | 3 |
ultra |
On | 2 | 4 |
Bank Project Client Constants
| Constant | Value | Description |
|---|---|---|
serverUrl |
'http://localhost:5000/api' |
API base URL (reserved for future server integration) |
storageKey |
'savedAccount' |
localStorage key for active session |
accountsKey |
'accounts' |
localStorage key for all accounts |
schemaKey |
'schemaVersion' |
localStorage key for migration tracking |
schemaVersion |
1 |
Current data schema version |
Note
The bank client uses
navigator.language(falling back to'en-IN') for locale-sensitive currency and date formatting viaIntl.NumberFormatandIntl.DateTimeFormat.
4. Deployment & Scaling
This is an educational curriculum repository, not a deployed service. "Deployment" in this context means classroom adoption, LMS integration, or self-hosted serving.
Classroom Deployment
- Fork the repository for your institution
- Optionally remove translations you do not need to reduce clone size
- Host lesson content via GitHub Pages, a local wiki, or an LMS
- Direct students to clone the fork and follow lessons sequentially
- Use the quiz app (
quiz-app/) for assessments — deploy it to Netlify, Vercel, or any static hosting
Self-Hosting the Quiz App
cd quiz-app
npm install
npm run build
The build output in dist/ is a static SPA that can be served by any web server (nginx, Apache, Netlify, Vercel, GitHub Pages).
GitHub Codespaces
The repository runs in GitHub Codespaces without modification. All projects with package.json can be installed and run within the Codespace terminal. AI projects benefit from the automatic GITHUB_TOKEN available in Codespaces.
Tip
For classroom settings, create a Codespace template from a fork of this repository. Students get a pre-configured development environment with no local installation required.
5. Operations
Automated Checks
The repository includes GitHub Actions workflows:
| Workflow | Purpose |
|---|---|
| Daily Repo Status | Automated daily status check (issues #1709–#1719) |
| Link Checker | Validates external URLs in lesson content (issues #1712–#1717) |
| Agentic Workflows | Automated repo maintenance tasks (issues #1696–#1697) |
Note
The agentic workflow runs have shown failures (issue #1696, #1697). These are automated maintenance bots, not user-facing features.
Content Maintenance
Updating lesson content: Edit the lesson README.md directly. Translations in translations/ may need corresponding updates — automated translation via Azure AI Co-op Translator can regenerate them.
Adding a new lesson: Copy lesson-template/ to the appropriate section directory. Follow the template structure (README with quiz links, assignment, solution directory).
Updating project dependencies: Each sub-project manages its own package.json and package-lock.json independently. Update them individually:
cd 7-bank-project/api
npm update
npm audit fix
Warning
The root
package-lock.jsonuses lockfileVersion 2 (npm 7+ era). Sub-projects use lockfileVersion 3 (npm 9+). Mixing npm versions across projects may cause lockfile churn in pull requests.
6. Performance
Clone Size Optimization
The full repository is large (13,611 files) due to translations and images. For faster cloning:
# Shallow clone (latest commit only)
git clone --depth 1 https://github.com/microsoft/Web-Dev-For-Beginners.git
# Partial clone (download blobs on demand)
git clone --filter=blob:none https://github.com/microsoft/Web-Dev-For-Beginners.git
Sub-Project Performance
Space game: Renders via HTML5 Canvas with a requestAnimationFrame game loop. Canvas resolution scales with devicePixelRatio for high-DPI displays. The graphicsTable settings control visual effects (glow, blur, star layers) to trade quality for frame rate.
Memory game: Uses React 19 with Next.js 16 Turbopack for fast development builds. The fisherYatesShuffle algorithm provides unbiased card randomization.
Quiz app: Uses Vite 6 with the Vue plugin for instant HMR during development. The About view is lazy-loaded (component: () => import(...)) for route-level code splitting.
7. Security
Input Handling
Chat project frontend: The escapeHtml() function in 9-chat-project/solution/frontend/app.js sanitizes all user and AI messages before DOM insertion, preventing XSS:
function escapeHtml(str){
if(!str) return '';
return str.replace(/&/g,'&')
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/"/g,'"')
.replace(/'/g,''');
}
Bank project client: Uses crypto.randomUUID() (with a fallback for non-HTTPS contexts) for transaction IDs. Currency codes are validated against Intl.supportedValuesOf('currency') when the API is available, preventing injection via the currency field.
Bank API — No Authentication
Warning
The bank API (
7-bank-project/api/server.js) has no authentication or authorization. It stores data in-memory (no database) and is designed purely as a learning tool. Do not expose it to the public internet.
The API uses cors middleware with default (open) settings, allowing any origin.
AI Project Credentials
The AI projects require a GITHUB_TOKEN environment variable. This token is read via os.environ["GITHUB_TOKEN"] — it is never hardcoded in source files. The LangChain ChatOpenAI client sends this token to https://models.github.ai/inference.
Caution
Never commit a
GITHUB_TOKENor any personal access token to the repository. Use environment variables or GitHub Codespaces (which provides the token automatically).
Browser Extension Permissions
The Carbon Trigger extension stores the CO2 Signal API key in localStorage within the extension's popup context. The extension sends a chrome.runtime.sendMessage to update the browser action icon color but does not request broad permissions.
8. Developer Internals
Repository Structure
Web-Dev-For-Beginners/
├── 1-getting-started-lessons/ 3 foundational lessons
│ ├── 1-intro-to-programming-languages/
│ ├── 2-github-basics/
│ └── 3-accessibility/
├── 2-js-basics/ 4 JavaScript fundamentals lessons
│ ├── 1-data-types/
│ ├── 2-functions-methods/
│ ├── 3-making-decisions/
│ └── 4-arrays-loops/
├── 3-terrarium/ 3 HTML/CSS/DOM lessons + solution
│ ├── 1-intro-to-html/
│ ├── 2-intro-to-css/
│ ├── 3-intro-to-DOM-and-closures/
│ └── solution/ script.js (draggable elements)
├── 4-typing-game/ 1 lesson + solution
│ ├── typing-game/
│ └── solution/ index.js (typing speed tracker)
├── 5-browser-extension/ 3 lessons + starter + solution
│ ├── 1-about-browsers/
│ ├── 2-forms-browsers-local-storage/
│ ├── 3-background-tasks-and-performance/
│ ├── start/ Starter code with webpack config
│ └── solution/ Complete extension with CO2 API
├── 6-space-game/ 6 progressive lessons
│ ├── 1-introduction/
│ ├── 2-drawing-to-canvas/ solution/ + your-work/
│ ├── 3-moving-elements-around/ solution/ + your-work/
│ ├── 4-collision-detection/ solution/ + your-work/
│ ├── 5-keeping-score/ solution/ + your-work/
│ ├── 6-end-condition/ solution/ + your-work/
│ └── solution/ Complete game (app.js, 19KB)
├── 7-bank-project/ 4 lessons + API + client solution
│ ├── 1-template-route/
│ ├── 2-forms/
│ ├── 3-data/
│ ├── 4-state-management/
│ ├── api/ Express REST API (server.js)
│ └── solution/ SPA client (app.js, 15KB)
├── 8-code-editor/
│ └── 1-using-a-code-editor/
├── 9-chat-project/
│ └── solution/
│ ├── backend/python/ FastAPI + OpenAI
│ └── frontend/ Chat UI (app.js)
├── 10-ai-framework-project/
│ ├── code/python/ 3 LangChain scripts
│ └── solution/
├── memory-game/ Next.js 16 + React 19 app
│ ├── app/ layout.js, page.js, globals.css
│ └── components/ MemoryGame.jsx
├── quiz-app/ Vue 3 + Vite SPA
│ └── src/
│ ├── App.vue
│ ├── main.js
│ ├── router/index.js
│ ├── components/ QuizGreeting.vue, QuizComponent.vue
│ └── views/ HomeView.vue, AboutView.vue
├── Git-Basics/ Supplementary git content
├── sketchnotes/ Visual summaries
├── teaching-files/ Classroom materials
├── lesson-template/ Template for new lessons
├── translations/ 50+ language translations
├── translated_images/ Localized images
├── pdf/ PDF output directory
├── docsifytopdf.js PDF config
├── package.json Root dependencies
└── package-lock.json Root lockfile
Space Game — Class Hierarchy
The space game uses ES6 class inheritance for game entities:
EventEmitter Custom pub/sub event system
└── (used by game loop for KEY_EVENT_UP/DOWN/SPACE/LEFT/RIGHT)
GameObject Base: x, y, width, height, type, img, dead
├── Hero Player: speed, cooldown, life, points
├── Enemy NPC: value points
└── Laser Projectile: fired by Hero
All variants of the space game (from lesson 3 through lesson 6 + final solution) implement this same hierarchy, progressively adding features:
| Lesson Stage | Classes | New Feature |
|---|---|---|
3-moving-elements-around |
EventEmitter, GameObject, Hero, Enemy | Keyboard input + movement |
4-collision-detection |
+ Laser | Collision detection, laser firing |
5-keeping-score |
Same | Score tracking, enemy waves |
6-end-condition |
Same | Lives, game over, restart |
solution/ (final) |
Flat refactor (no classes) | Settings dialog, difficulty, audio, particles, HiDPI canvas |
Note
The final
solution/app.jsrefactors away from the class-based approach used in the progressive lessons. It uses plain objects and functional patterns instead, with a comprehensive settings system (difficulty, graphics, audio, controls) that the incremental lessons do not include.
Bank Project — API Endpoints
| Method | Path | Request Body | Response | Description |
|---|---|---|---|---|
GET |
/ |
— | "Bank API v1" |
Health check / welcome |
POST |
/accounts |
{ user, currency, description, balance } |
Account object | Create new account |
GET |
/accounts/:user |
— | Account object | Retrieve account by username |
DELETE |
/accounts/:user |
— | 204 No Content |
Delete account |
POST |
/accounts/:user/transactions |
{ date, object, amount } |
Transaction object | Add transaction to account |
DELETE |
/accounts/:user/transactions/:id |
— | 204 No Content |
Delete specific transaction |
The API stores data in-memory (a JavaScript array) — data is lost when the server restarts. The Bank API uses Express 4 with body-parser for JSON parsing and cors for cross-origin requests.
Bank Project — Client State Management
The client (7-bank-project/solution/app.js) implements a frozen state pattern:
let state = Object.freeze({
account: null
});
function updateState(property, newData) {
state = Object.freeze({ ...state, [property]: newData });
localStorage.setItem(storageKey, JSON.stringify(state.account));
}
State mutations create a new frozen object, preventing accidental direct mutations. The storage event listener enables cross-tab synchronization — when accounts or the active account change in another tab, the current tab refreshes automatically.
The client also includes a schema migration framework:
function migrateSchema() {
const v = Number(localStorage.getItem(schemaKey) || 0);
if (v >= schemaVersion) return;
// Migration logic here
localStorage.setItem(schemaKey, String(schemaVersion));
}
Browser Extension — Architecture
5-browser-extension/solution/
├── src/
│ └── index.js Main popup logic (axios → CO2 Signal API)
├── dist/ webpack output (loaded as unpacked extension)
├── manifest.json Extension manifest
├── webpack.config.js Bundling configuration
└── package.json axios + webpack dependencies
The extension uses chrome.runtime.sendMessage({ action: 'updateIcon', value: { color } }) to dynamically change the browser action icon based on carbon intensity. The color scale maps CO2 values to a 5-step gradient: [0, 150, 600, 750, 800] → ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02'].
Memory Game — React Component Architecture
memory-game/
├── app/
│ ├── layout.js Root layout (Geist fonts, metadata)
│ ├── page.js Renders MemoryGame component
│ └── globals.css Tailwind CSS import
└── components/
└── MemoryGame.jsx Game logic (single component)
The MemoryGame component manages all state via React hooks:
| Hook | State Variable | Purpose |
|---|---|---|
useState |
gridSize |
Grid dimensions (2–10, even only) |
useState |
array |
Shuffled card objects { id, number } |
useState |
flipped |
Currently flipped card IDs |
useState |
selectedPairs |
Matched pair IDs |
useState |
disabled |
Click lock during match animation |
useState |
won |
Victory state |
useCallback |
initializeGame |
Memoized game reset (depends on gridSize) |
useEffect |
— | Re-initialize when gridSize changes |
useEffect |
— | Check win condition when selectedPairs changes |
Card shuffling uses the Fisher-Yates algorithm for unbiased randomization.
Quiz App — Vue 3 Architecture
quiz-app/
├── src/
│ ├── main.js Vue 3 app creation + router mount
│ ├── App.vue Root component (header nav + RouterView)
│ ├── router/index.js Route definitions
│ ├── components/
│ │ ├── QuizGreeting.vue Header greeting component
│ │ └── QuizComponent.vue Quiz display + interaction
│ └── views/
│ ├── HomeView.vue Landing page
│ └── AboutView.vue About page (lazy-loaded)
└── jsconfig.json Path alias: @/* → ./src/*
Routes:
| Path | Component | Loading |
|---|---|---|
/ |
HomeView |
Eager |
/quiz/:id |
QuizComponent |
Eager |
/about |
AboutView |
Lazy (() => import(...)) |
The quiz app uses createWebHistory for clean URLs (no hash routing) with Vite's import.meta.env.BASE_URL for base path configuration.
AI Project — LangChain Integration Patterns
Three Python scripts demonstrate LLM integration via LangChain with GitHub Models:
app.py — Basic invocation:
llm = ChatOpenAI(
api_key=os.environ["GITHUB_TOKEN"],
base_url="https://models.github.ai/inference",
model="openai/gpt-4o-mini",
)
response = llm.invoke("What is the capital of France")
app-chat.py — Multi-turn conversation:
Uses SystemMessage and HumanMessage objects. Appends responses to the message list for multi-turn context.
app-tools.py — Tool calling:
Defines tools as TypedDict subclasses with annotated fields. The LLM decides which tool to call based on the prompt, and the script dispatches to local Python functions:
class add(TypedDict):
"""Add two integers."""
a: Annotated[int, ..., "First integer"]
b: Annotated[int, ..., "Second integer"]
class joke(TypedDict):
"""Tell a joke."""
category: Annotated[str, ..., "The joke category"]
functions = {
"add": lambda a, b: a + b,
"joke": lambda category: get_joke(category)
}
The get_joke function calls the Chuck Norris API (https://api.chucknorris.io/jokes/random?category={category}) as an external tool implementation.
Code Patterns and Conventions
Closure-based event handling (Terrarium):
The terrarium project uses closures to create independent drag handlers per element. Each call to dragElement(el) creates a new scope with its own position tracking variables (pos1–pos4), demonstrating JavaScript's lexical scoping.
IIFE encapsulation (Space Game, Chat):
Both the space game solution and the chat frontend wrap their code in IIFEs ((() => { ... })() or (function(){ ... })()) to avoid polluting the global scope.
Frozen state pattern (Bank Project):
The bank client uses Object.freeze() on state objects to prevent accidental mutation, creating new frozen objects on each update.
Module bundling vs. direct usage:
The browser extension uses webpack to bundle ES modules (the import axios from 'axios' pattern). All other client-side projects load scripts via <script> tags without a bundler — reflecting the curriculum's progressive introduction of tooling concepts.
Testing
The repository does not include a formal test suite. The following npm scripts exist but are stubs:
"test": "echo \"Error: no test specified\" && exit 1"
This appears in all sub-project package.json files except the quiz app (which uses ESLint for linting only).
The bank API has ESLint and Prettier configured:
cd 7-bank-project/api
npm run lint # ESLint
npm run format # Prettier (single quotes, write mode)
Contributing
The repository accepts contributions via pull requests on GitHub. Key areas for contribution:
- Translations: Add or improve lesson translations in
translations/{lang}/ - Bug fixes: Fix broken links (frequently flagged by the Link Checker workflow)
- New lessons: Follow the
lesson-template/structure - Project improvements: Enhance solution code or add new starter templates
The MIT license allows free use, modification, and redistribution for both personal and commercial purposes.
9. Integration Points
External APIs
| API | Used By | Endpoint | Auth |
|---|---|---|---|
| CO2 Signal | Browser extension | https://api.co2signal.com/v1/latest |
auth-token header |
| GitHub Models | AI projects | https://models.github.ai/inference |
GITHUB_TOKEN |
| Chuck Norris API | AI tool-calling demo | https://api.chucknorris.io/jokes/random |
None |
| Netlify (quiz hosting) | Quiz links in lessons | https://ff-quizzes.netlify.app/web/ |
None |
Microsoft Learn Integration
Multiple lessons are cross-published on Microsoft Learn with WT.mc_id=academic-77807-sagibbon tracking parameters. These links provide an alternative interactive learning environment but are not required for the curriculum.
Translation Infrastructure
Translations use Azure AI Co-op Translator for initial machine translation, followed by community review via pull requests. Each translated lesson includes a disclaimer noting the AI translation origin:
This document was translated using AI translation service Co-op Translator. While we strive for accuracy, please be aware that automated translations may contain errors or inaccuracies.
Translated images (sketchnotes) in translated_images/ are WebP format, localized per language.