# Web Dev for Beginners — Administrator & Developer Guide

## 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

```text
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)

```text
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.json` with its own `node_modules`. There is no monorepo-level workspace or shared dependency management. Running `npm install` at the root only installs `docsify-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`)

```javascript
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 via `Intl.NumberFormat` and `Intl.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

1. Fork the repository for your institution
2. Optionally remove translations you do not need to reduce clone size
3. Host lesson content via GitHub Pages, a local wiki, or an LMS
4. Direct students to clone the fork and follow lessons sequentially
5. Use the quiz app (`quiz-app/`) for assessments — deploy it to Netlify, Vercel, or any static hosting

### Self-Hosting the Quiz App

```bash
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:

```bash
cd 7-bank-project/api
npm update
npm audit fix
```

> [!WARNING]
> The root `package-lock.json` uses 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:

```bash
# 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:

```javascript
function escapeHtml(str){
  if(!str) return '';
  return str.replace(/&/g,'&amp;')
            .replace(/</g,'&lt;')
            .replace(/>/g,'&gt;')
            .replace(/"/g,'&quot;')
            .replace(/'/g,'&#039;');
}
```

**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_TOKEN` or 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

```text
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:

```text
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.js` refactors 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:

```javascript
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:

```javascript
function migrateSchema() {
  const v = Number(localStorage.getItem(schemaKey) || 0);
  if (v >= schemaVersion) return;
  // Migration logic here
  localStorage.setItem(schemaKey, String(schemaVersion));
}
```

### Browser Extension — Architecture

```text
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

```text
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

```text
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:**

```python
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:

```python
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:

```json
"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:

```bash
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.

---

_Generated May 2026 from microsoft/Web-Dev-For-Beginners at 1db4ae0. 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. Unofficial; not affiliated with or reviewed by the project._
