# JavaScript Questions — Administrator & Developer Guide

This guide is written for **fork operators**, **translation maintainers**, **content stewards**, and **engineers integrating the catalogue** into derivative tooling (interview platforms, training materials, quiz apps, Anki decks, search-engine sitemaps). It is a deliberate counterpart to the User Guide: where the User Guide says *how to read*, this document says *how the repository works internally and how to keep it healthy as a piece of community infrastructure*.

The repository itself ships **no executable code, no build pipeline, no CI workflow, no test harness, and no runtime**. The "platform" is GitHub itself: GFM rendering, the `<details>` disclosure widget, the issue tracker, and the pull-request system. Every operational concern below therefore reduces to one of five flavours: **content correctness**, **translation drift**, **PR-review workflow**, **link rot**, and **fork hygiene**.

---

## Table of Contents

1. Executive Summary
2. Repository Architecture
3. System Requirements
4. Configuration Surface
5. Question Schema (Implicit Template)
6. Internationalization Implementation
7. Operations Playbook
8. Security & Threat Model
9. Repository Structure
10. Code Patterns and Conventions
11. Quality Heuristics
12. Improvements Roadmap
13. Troubleshooting
14. Quick Reference

---

## 1. Executive Summary

`lydiahallie/javascript-questions` is a **community-maintained question catalogue** of advanced JavaScript multiple-choice puzzles, distributed as plain markdown across one canonical English `README.md` and 22 locale-specific translation directories. The repository is **content, not software** — there is no service to operate, no version to release, no dependency tree to audit. The maintenance burden is editorial: vetting question correctness, propagating errata into translations, reviewing pull requests, and triaging issues.

### Why this guide exists

Despite being "just markdown", the repository is **non-trivial to fork or integrate**. Surprises that bite operators of derivative platforms include:

- The H6 (`######`) heading convention for question titles, which **breaks markdown TOC generators** that default to H1–H4.
- The locale directory naming convention is **not standardised** — some directories ship a plain `README.md`, others ship `README-{locale}.md`, others ship `README_{LOCALE}.md`. Each variation has historical reasons but trips up bulk discovery scripts.
- The `<details>`/`<summary>` answer disclosure relies on **HTML inside markdown**, which means tools that strip HTML (some LaTeX-via-pandoc paths, some sanitised CMS imports) lose all the answers in one pass.
- Translation completeness ranges from **155 / 155 (100%)** to **43 / 155 (28%)**. Treating all locales as interchangeable produces broken UX in derivative apps.
- The **English edition is canonical**. Errata corrections land in English first; propagation to 22 translations is best-effort. Operators of multilingual derivative apps must decide whether they prefer "freshness" (English-first display + on-the-fly translation) or "consistency" (display the local-language file even if it lags by months).

### Who maintains it

A single primary maintainer (Lydia Hallie, [@lydiahallie](https://github.com/lydiahallie)) reviews and merges PRs at her own cadence. Translation maintainership is **informal** — there is no `CODEOWNERS` file delegating per-locale review. Whoever opens the most recent PR for a translation is, in practice, that translation's de facto steward until someone else takes over.

> [!NOTE]
> The single-maintainer model is a deliberate constraint. It keeps editorial voice consistent across the canonical English edition, which in turn keeps translations stable targets. The trade-off is that PR queues can sit for weeks. Forks that need faster review velocity should plan to maintain their own divergent branch rather than wait on upstream.

### License

**MIT**, copyright © 2019 Lydia Hallie. Reuse is permitted with attribution. The `LICENSE` file in the repository root is the authoritative text.

### Source documented here

This Admin Guide describes the repository at commit **`a8b427b`** (merged 2024-03-10), which carries the merge commit *Merge pull request #767 from abbas-roholamin/fix-typos*. The repository structure documented below is stable across surrounding commits — the catalogue's architecture has not shifted since 2019.

---

## 2. Repository Architecture

### 2.1 What "architecture" means for a content repo

There is no application, no module graph, and no runtime call tree to diagram. The "architecture" is the **layout convention** — which files exist, what they contain, how they reference each other — and the **editorial conventions** that govern how content is added or amended.

### 2.2 Component inventory

| Component | Path | Role |
|---|---|---|
| Canonical English content | `README.md` | The 155-question source-of-truth catalogue. All translations are derived from this file. |
| Translation editions | `{locale}/README*.md` | 22 community-maintained mirrors of the English content, each in its own top-level directory. |
| License | `LICENSE` | MIT, applies to the entire repository. |
| Issue tracker | `https://github.com/lydiahallie/javascript-questions/issues` | Errata reports, feature requests, translation-update threads. **No** dedicated forum, mailing list, or Discord. |
| Pull-request queue | GitHub PRs | The only ingestion mechanism for changes. |

There is **no** `package.json`, **no** `.github/workflows/*.yml`, **no** CONTRIBUTING.md, **no** CODEOWNERS, **no** ISSUE_TEMPLATE, **no** Dockerfile, **no** Makefile, **no** test directory, and **no** generated artefacts (no `dist/`, no `build/`, no `gh-pages` branch tracking a deployed site). The repository is exactly what you see in `git ls-files`.

> [!NOTE]
> The intentional minimalism is itself a design decision. Every file added to the repository is a file that has to be maintained across 22 translations. By keeping the surface to one markdown file per locale plus a license, the maintainer keeps drift to a manageable shape: "is each translation up to date with English?" instead of "is each translation up to date with English **and** with the contributor guide **and** with the issue templates?"

### 2.3 Data flow (such as it is)

```
                     ┌──────────────────────────┐
                     │ Canonical English README │
                     │ lydiahallie/main         │
                     └────────────┬─────────────┘
                                  │ (typo fix, errata,
                                  │  new question, edit)
                                  ▼
                  ┌───────────────────────────────────┐
                  │ PR opened on lydiahallie/main     │
                  │  - reviewed by maintainer         │
                  │  - merged if accepted             │
                  └────────────┬──────────────────────┘
                               │ (merged commit)
                               ▼
              ┌────────────────────────────────────────┐
              │ 22 translation files now LAG canonical │
              │ Each translation maintainer must open  │
              │ a follow-up PR mirroring the change    │
              └────────────────────────────────────────┘
                               │
                               ▼
                     Out-of-band coordination
                     (issue threads, none formal)
```

There is no automation that watches the English file and notifies translators. Mirroring is **purely social** — translators check the file's git history when they next pick up a maintenance pass. This is the dominant source of translation drift documented in Section 6.4.

### 2.4 Technology stack

| Layer | Technology |
|---|---|
| Format | GitHub-Flavoured Markdown (GFM) |
| Embedded HTML | `<details>`, `<summary>`, `<div>`, `<p>`, `<b>`, `<i>` |
| Syntax highlighting | GitHub's built-in linguist (uses ` ```javascript ` fences) |
| Hosting | github.com |
| Issue tracking | GitHub Issues |
| Build / generate | None — files are checked in as-is |
| Deploy | None — github.com IS the rendering layer |

> [!NOTE]
> The decision to embed raw HTML inside markdown (specifically `<details>`/`<summary>`) is what enables the "click to reveal answer" mechanic. CommonMark allows pass-through HTML; GFM does too; most derivative tools (pandoc, MkDocs, Hugo, etc.) handle it correctly **as long as they don't sanitise embedded HTML**. CMSes that strip HTML (Jekyll without `allow_html: true`, some Confluence importers) will lose every answer.

---

## 3. System Requirements

### 3.1 For readers

A web browser, or any markdown viewer that:

- Renders GitHub-Flavoured Markdown.
- Honours embedded `<details>`/`<summary>` HTML.
- Optionally honours `<div dir='rtl'>` for the Arabic editions.

There is no minimum hardware requirement worth listing. The largest README is ~5,151 lines / ~340 KB; an entry-level smartphone renders it without issue.

### 3.2 For translation contributors

| Requirement | Notes |
|---|---|
| Native or fluent reading proficiency in target language | Translation quality matters more than English-side fluency. |
| Reading proficiency in English | To consume the canonical edition. |
| Working JavaScript knowledge | To preserve technical accuracy across translation choices. |
| Git + GitHub account | For PR submission. |
| Markdown viewer | To preview your changes before submitting. |
| Basic awareness of locale-specific quoting conventions | Smart quotes, dashes, RTL handling for Arabic / Hebrew / Persian. |

### 3.3 For maintainers

Single-maintainer model. The de facto requirements are **GitHub repo-admin access**, JavaScript expertise sufficient to vet question accuracy without help, and editorial bandwidth — no formal cadence is enforced.

### 3.4 For fork operators integrating into a quiz platform

| Requirement | Notes |
|---|---|
| Markdown parser supporting GFM + raw HTML | `markdown-it` with `html: true` works; vanilla CommonMark does not parse `<details>`. |
| HTML-to-data transformer | To extract question/options/answer triples from prose. |
| Storage for parsed catalogue | SQLite, JSON, whatever fits your platform. |
| Update / sync mechanism | Cron-pulling the upstream branch, or a manual quarterly sync. |
| Strategy for translation lag | Decide: serve English fallback, or hide untranslated questions, or mark them as "untranslated". |

### 3.5 Hardware

None. There is no service to deploy. Hosting your fork costs whatever your git host costs (free on github.com; cheap-to-free on most alternatives).

---

## 4. Configuration Surface

There is no configuration file in the repository. The only knobs are **editorial conventions**, enforced by review rather than by code.

### 4.1 Editorial knobs (review-enforced)

| Convention | Value | Enforced by |
|---|---|---|
| Question heading level | H6 (`###### N. <text>?`) | PR review |
| Answer verdict heading | H4 (`#### Answer: <letter>`) | PR review |
| Code fence language tag | `javascript` | PR review |
| Option list style | `- A: <code>` (bulleted, not ordered) | PR review |
| Disclosure tag | `<details><summary><b>Answer</b></summary>` (or localised) | PR review |
| Closing triple | `</p>` then `</details>` then `---` then blank line | PR review |
| Section separator | `---` (horizontal rule) between every question | PR review |
| Question numbering | Continuous, monotonically increasing, **never re-numbered** | PR review |

> [!IMPORTANT]
> Renumbering questions is **the** breaking change for the entire ecosystem of translations and derivative apps. A reviewer must reject any PR that shifts existing question numbers, even to fix a "gap" (there are no gaps in the canonical edition; numbers run 1 to 155 sequentially).

### 4.2 What is NOT configurable

- The repository name (`lydiahallie/javascript-questions`) is referenced by every translation's relative-link index. Renaming would break all those links.
- The default branch name (`main`) is referenced from the maintainer's blog and external mirrors.
- The license (MIT) is the project-wide license; relicensing would require approval from every contributor whose changes are still in the history.

---

## 5. Question Schema (Implicit Template)

Every question in every translation conforms to a strict schema, even though no tooling validates it. This section formalises the schema so derivative parsers can rely on it.

### 5.1 Canonical structure

```markdown
###### {N}. {QUESTION TEXT}?

```javascript
{SNIPPET}
```

- A: `{OPTION A}`
- B: `{OPTION B}`
- C: `{OPTION C}`
- D: `{OPTION D}`

<details><summary><b>Answer</b></summary>
<p>

#### Answer: {LETTER}

{EXPLANATION PARAGRAPH(S)}

</p>
</details>

---
```

### 5.2 Field-by-field semantics

| Field | Allowed values | Notes |
|---|---|---|
| `{N}` | Integer 1–155 (canonical edition) | Translations may have fewer; numbers must align with canonical. |
| `{QUESTION TEXT}` | Free-form question | Always ends with `?`. Often "What's the output?" but see UG §4 for variants. |
| `{SNIPPET}` | Self-contained JavaScript | No imports, no external state. Must be runnable in any modern browser console. |
| `{OPTION X}` | Lettered option (A, B, C, D, occasionally E/F) | Wrapped in inline backticks **except** when the option is itself prose (e.g. "True" / "False" / "Throws an error"). |
| `Answer` summary text | Localised label | "Answer", "Antwort", "Cevap", "答え", "정답", "Ответ", etc. |
| `{LETTER}` | Single uppercase letter A–F | Matches one of the option labels above. |
| `{EXPLANATION}` | Free-form prose, 1–4 paragraphs | May contain inline `<i>`, `<b>`, additional code blocks, or nested examples. |

### 5.3 Required structural elements

Every question MUST contain:

1. The H6 numbered heading.
2. At least one fenced JavaScript code block.
3. At least two lettered options.
4. The `<details>` block enclosing the answer.
5. The H4 `#### Answer: <letter>` line inside the disclosure.
6. The `</p></details>` closing pair (note: in some editions the order is `</p>` then `</details>`; in others it is just `</details>` — both render correctly because GFM closes orphan `<p>` automatically).
7. The trailing `---` horizontal rule that separates the question from the next.

### 5.4 Forbidden modifications

- **Do not** change the H6 to H3 — it inflates the table of contents to unreadable size.
- **Do not** convert option bullets to ordered lists — letter labels become double-numbered ("1. A:", "2. B:") in many viewers.
- **Do not** drop the language tag from code fences — GitHub will not syntax-highlight, and pandoc derivatives lose semantic info.
- **Do not** translate the option **letters** (`A`, `B`, `C`, `D`) outside locales that have an established convention for it (Egyptian Arabic uses `أ`, `ب`, `ج`, `د`). Letter labels function as cross-translation indices.
- **Do not** introduce ` ```js `, ` ```jsx `, or ` ```ts ` — the canonical fence is ` ```javascript `.

> [!WARNING]
> **Schema drift breaks parsers.** A derivative quiz platform that grep-extracts the H6 heading + first ` ```javascript ` block + bulleted options + `#### Answer:` line will silently miss any question that uses a non-conforming variant. If you accept a PR that breaks the schema in one place, you have entered a slow-moving compatibility crisis with every downstream tool. Prefer rejecting the PR and asking the contributor to conform.

---

## 6. Internationalization Implementation

The translation system is the most operationally complex aspect of the repository. This section documents how it actually works.

### 6.1 Locale directory naming

The 22 translation directories use the **`{language}-{REGION}`** convention with a two-letter ISO 639-1 language code and a two-letter ISO 3166-1 region code, separated by a hyphen. Both halves are lowercased except where regional usage dictates uppercase (which is the dominant pattern here):

```
ar-AR   ar-EG   bs-BS   de-DE   es-ES   fr-FR   id-ID   it-IT   ja-JA
ko-KR   nl-NL   pl-PL   pt-BR   ro-RO   ru-RU   sq-KS   th-TH   tr-TR
uk-UA   vi-VI   zh-CN   zh-TW
```

> [!NOTE]
> Two of these codes are arguably non-standard: `ar-AR` (the language code is `ar`, but `AR` is not a country region — Arabic is supranational) and `sq-KS` (Kosovo's ISO code is `XK`, not `KS`). The maintainer accepts these because changing them would break every existing inbound link to those translation files.

### 6.2 Filename convention matrix

There are **three filename patterns** in active use, plus a Romanian special case. Pattern is locale-specific and reflects whichever convention the original translator chose:

| Pattern | Used by | Example path |
|---|---|---|
| Plain `README.md` | de-DE, id-ID, it-IT, nl-NL, pl-PL, ru-RU, th-TH, uk-UA | `de-DE/README.md` |
| `README-{LOCALE_VAR}.md` | bs-BS, es-ES, ja-JA, ko-KR, tr-TR, vi-VI, zh-CN | `bs-BS/README-bs_BS.md`, `es-ES/README-ES.md` |
| `README_{LOCALE_VAR}.md` | ar-AR, ar-EG, fr-FR, pt-BR, sq-KS, zh-TW | `ar-AR/README_AR.md`, `pt-BR/README_pt_BR.md` |
| `README.ro.md` | ro-RO **only** | `ro-RO/README.ro.md` |

The Romanian filename is unique. It uses a `.ro.md` middle-dot suffix (which is a multi-extension pattern uncommon in this project but used elsewhere in software). It still ends in `.md` so GitHub renders it correctly, but auto-discovery scripts that hard-code `README.md` will miss it.

> [!IMPORTANT]
> If you are writing a fork-discovery script, treat the locale directory as the source of truth and accept ANY `README*.md` file inside it. Do not assume `README.md`. Concretely:
> ```bash
> find . -mindepth 2 -maxdepth 2 -name 'README*.md' -not -path './.git/*'
> ```

### 6.3 Translation discovery mechanism

There is no manifest file. The English README contains a `<details>` block titled *"See 20 Available Translations"* with a hand-maintained markdown list of relative links to each translation's path:

```markdown
- [🇸🇦 العربية](./ar-AR/README_AR.md)
- [🇪🇬 اللغة العامية](./ar-EG/README_ar-EG.md)
- [🇧🇦 Bosanski](./bs-BS/README-bs_BS.md)
- [🇩🇪 Deutsch](./de-DE/README.md)
- ...
```

Each translation file should reciprocally link back to peer translations near the top of the file (most do; some are inconsistent). The list is **manually edited** when a new locale is added — there is no script that walks the filesystem and regenerates it.

> [!NOTE]
> The "20 Available Translations" header in the English README is **stale by two locales** — the actual count is 22. The maintainer hasn't updated the heading text as new translations have been added. The list itself is correct (22 entries); only the summary count is outdated. This is a known cosmetic drift; not a content bug.

### 6.4 Translation drift snapshot

Coverage (questions translated / 155) at commit `a8b427b`:

| Locale | Questions | Coverage | Drift class |
|---|---:|---:|---|
| English (canonical) | 155 | 100% | n/a |
| `it-IT` | 155 | 100% | Caught up |
| `ko-KR` | 155 | 100% | Caught up |
| `ro-RO` | 155 | 100% | Caught up |
| `ru-RU` | 155 | 100% | Caught up |
| `sq-KS` | 155 | 100% | Caught up |
| `zh-TW` | 155 | 100% | Caught up |
| `id-ID` | 153 | 99% | Lagging by 2 |
| `vi-VI` | 152 | 98% | Lagging by 3 |
| `zh-CN` | 150 | 97% | Lagging by 5 |
| `nl-NL` | 144 | 93% | Lagging by 11 |
| `de-DE` | 127 | 82% | Stale |
| `es-ES` | 115 | 74% | Stale |
| `th-TH` | 107 | 69% | Stale |
| `tr-TR` | 95 | 61% | Stale |
| `ja-JA` | 83 | 54% | Heavily stale |
| `pt-BR` | 80 | 52% | Heavily stale |
| `pl-PL` | 75 | 48% | Heavily stale |
| `ar-AR` | ~65 | 42% | Heavily stale |
| `fr-FR` | 64 | 41% | Heavily stale |
| `uk-UA` | 46 | 30% | Mostly empty |
| `bs-BS` | 43 | 28% | Mostly empty |
| `ar-EG` | 43 | 28% | Mostly empty |

> [!CAUTION]
> If you fork the catalogue into a multilingual quiz platform, **declare a coverage policy explicitly**. Three reasonable policies: (1) hide untranslated questions in non-canonical locales; (2) show them in English when the local translation is missing; (3) display a "translation incomplete after Q{N}" banner. Silently truncating the catalogue at the locale's last translated question is the worst option — users see a working app that ends abruptly with no explanation.

### 6.5 Cross-locale errata propagation

When the canonical English answer is corrected, propagation to the 22 translations is **not automatic**. The historical pattern is:

1. An issue is opened against the English answer (e.g. #782 against Q61).
2. A PR fixes the English README. Merged.
3. The English question now has a different correct answer than its 22 translation counterparts.
4. The discrepancy persists until a translation maintainer notices and opens a follow-up PR for their locale.

Because there is no automation watching for English changes, the median time-to-propagation across locales is **months to years**. Forks that need timely propagation should script their own diff: monitor `git log --follow README.md` and emit a notification when a question's content (snippet, options, or answer) changes.

> [!TIP]
> A useful audit query against the upstream repo: identify every commit that touches `README.md` since a given date, then for each touched line, identify which question it falls inside (by walking backwards to the previous H6 heading). The output is a per-question changelog that translation maintainers can prioritise from.

---

## 7. Operations Playbook

### 7.1 New-question PR review

Inbound PRs adding a question (rare in 2024+; the catalogue is mostly stable) should be evaluated against a fixed checklist:

- [x] Numbered as **N+1** where N is the current canonical maximum (currently 155).
- [x] Conforms to the schema in §5.
- [x] Snippet is **runnable** as-is in a browser console without errors.
- [x] Snippet does **not** depend on a feature post-2019 unless the maintainer explicitly opens that scope.
- [x] At least one option label maps to the correct answer.
- [x] Explanation cites the language behaviour, not a library or framework.
- [x] No copyright violations (the snippet is original or trivially small).
- [x] No PII in the snippet (no real-looking email addresses, API keys, etc.).

Reject (with comment) if any item fails.

### 7.2 Errata PR review

Inbound PRs fixing an existing question (the dominant PR type) should be evaluated against a different checklist:

- [x] PR description references the issue number (`Fixes #NNN`).
- [x] Change is **scoped** to a single question (or to a coordinated multi-question fix if the same bug affects several).
- [x] Updated explanation can be verified by running the snippet against a current JavaScript engine.
- [x] Question numbering is **unchanged**.
- [x] Translation files are **untouched** in this PR (translations get follow-up PRs).
- [x] Diff doesn't accidentally re-flow surrounding questions due to whitespace changes.

Accept if all check; merge with a squash commit so the history stays linear.

### 7.3 Translation PR review

Translations are reviewed by the primary maintainer because there is no formal per-locale CODEOWNER. The review is necessarily lighter on linguistic accuracy:

- [x] PR is scoped to **one locale**.
- [x] Question numbering aligns with the English edition for every translated question.
- [x] Code blocks are unchanged from the English source (variable names, string literals, output strings remain LTR JavaScript).
- [x] Heading levels match (H6 for question, H4 for answer verdict).
- [x] No Unicode-direction glitches (RTL Arabic doesn't accidentally pull the closing markdown fence into reverse direction).
- [x] No accidental untranslated stretches (a translation that reverts to English mid-explanation needs another pass).

### 7.4 Issue triage cadence

There is no formal SLA. The historical pattern is:

| Issue type | Typical time-to-first-response | Typical time-to-close |
|---|---|---|
| Typo / clear errata | Days | Weeks (when a PR lands) |
| Disputed answer | Weeks | Months (or never if community consensus shifts) |
| Translation request for new locale | Days (welcoming response) | Open until someone submits a PR |
| Vague "this is wrong" without specifics | Weeks if at all | Often closes stale |
| Author-personal link broken (e.g. #647) | Variable | Slow; these are not a high priority |

Forks that need predictable triage should fork rather than depend on upstream cadence.

### 7.5 Adding a new locale

1. Open an issue titled **`Translation request: {Language}`**. Wait for maintainer ack to avoid duplicating someone else's in-flight work.
2. Create a new top-level directory: **`{lang}-{REGION}/`** following the convention in §6.1.
3. Pick a filename pattern matching one of the three patterns in §6.2. There is no formal preference; pick whichever pattern is closest to the prevailing style of similar locales.
4. Translate at least the first 30 questions in the initial PR. PRs with fewer questions are sometimes accepted but get less review attention.
5. Add an entry to the English README's translation index, in alphabetical order by locale code.
6. Optionally add a peer-translation index inside your new file.
7. Submit the PR with a description committing to maintenance ("I will keep this translation up to date with the English edition").

### 7.6 Maintaining the LICENSE

The `LICENSE` file is unchanged since the repository's creation. Modifications should be rejected unless there is a fundamental relicensing decision (which would require dual-licensing or explicit consent from significant historical contributors). The current MIT terms are sufficient for the catalogue's intended use.

---

## 8. Security and Threat Model

### 8.1 What this repository does NOT need

| Threat | Why it doesn't apply |
|---|---|
| Code injection | No user input flows anywhere — content is static. |
| Dependency vulnerabilities | Zero runtime dependencies. |
| Authentication / authorisation | No protected resources; everything is public. |
| Secret management | No secrets in the repository (verify with `git log -p` on a regular cadence anyway). |
| API rate limiting | No API. |
| DoS protection | github.com handles rendering. |

### 8.2 What it DOES benefit from

- **Branch protection** on `main` to prevent force pushes that would invalidate inbound links and historical permalinks.
- **Required PR review** before merge — already enforced as the de facto policy.
- **Two-factor authentication** on the maintainer account. Compromise of the account would be the only realistic catastrophic failure mode.
- **GitHub's secret-scanning** to flag any accidental secret committed by a contributor (e.g. someone pasting an actual API key into a Q&A snippet for "realism"). Free for public repositories.
- **`SECURITY.md`** documenting how to report security-flavoured issues. Currently absent. A **content-correctness vulnerability** (e.g. a question whose answer is silently wrong) can damage learners' careers; a reporting channel for those is worth having.

### 8.3 Fork-operator threats

Operators of derivative tools should consider:

- **Question-stem injection.** If you accept user-submitted questions in addition to the canonical catalogue, sanitise them for embedded `<script>`/`<iframe>` HTML. The original repository can rely on github.com's renderer; a custom platform cannot.
- **Cross-locale spoofing.** Don't trust user-supplied "language preference" cookies blindly to select a translation file — pick from a server-side allowlist of the 23 known locale codes.
- **Stale-cache attacks.** Aggressive caching of the catalogue can hide errata for weeks. Build cache-invalidation logic that respects errata-PR merge timestamps.

> [!WARNING]
> A particularly subtle integration bug: when serving a translation, several locales' files use the same filename (`README.md`) inside their locale directory. Hard-coding a static path like `i18n/{lang}/README.md` works for *some* locales but produces 404s for `bs-BS`, `es-ES`, `fr-FR`, and a dozen others. Always discover translation files at run-time from the filesystem, not from a hard-coded path.

---

## 9. Repository Structure

### 9.1 Top-level layout

```
javascript-questions/
├── LICENSE                            # MIT, copyright (c) 2019 Lydia Hallie
├── README.md                          # Canonical English edition — 155 questions
├── ar-AR/
│   └── README_AR.md                   # Modern Standard Arabic — ~65 questions, RTL
├── ar-EG/
│   └── README_ar-EG.md                # Egyptian colloquial Arabic — 43 questions
├── bs-BS/
│   └── README-bs_BS.md                # Bosnian — 43 questions
├── de-DE/
│   └── README.md                      # German — 127 questions
├── es-ES/
│   └── README-ES.md                   # Spanish — 115 questions
├── fr-FR/
│   └── README_fr-FR.md                # French — 64 questions
├── id-ID/
│   └── README.md                      # Indonesian — 153 questions
├── it-IT/
│   └── README.md                      # Italian — 155 questions (full)
├── ja-JA/
│   └── README-ja_JA.md                # Japanese — 83 questions
├── ko-KR/
│   └── README-ko_KR.md                # Korean — 155 questions (full)
├── nl-NL/
│   └── README.md                      # Dutch — 144 questions
├── pl-PL/
│   └── README.md                      # Polish — 75 questions
├── pt-BR/
│   └── README_pt_BR.md                # Portuguese (Brazil) — 80 questions
├── ro-RO/
│   └── README.ro.md                   # Romanian — 155 questions (full)
├── ru-RU/
│   └── README.md                      # Russian — 155 questions (full)
├── sq-KS/
│   └── README_sq_KS.md                # Albanian (Kosovo) — 155 questions (full)
├── th-TH/
│   └── README.md                      # Thai — 107 questions
├── tr-TR/
│   └── README-tr_TR.md                # Turkish — 95 questions
├── uk-UA/
│   └── README.md                      # Ukrainian — 46 questions
├── vi-VI/
│   └── README-vi.md                   # Vietnamese — 152 questions
├── zh-CN/
│   └── README-zh_CN.md                # Chinese (Simplified) — 150 questions
└── zh-TW/
    └── README_zh-TW.md                # Chinese (Traditional) — 155 questions (full)
```

Total: **24 tracked files** (23 README markdowns + the LICENSE).

### 9.2 What's NOT in the repository

To save fork operators time investigating, here is what you will **not** find:

- **No** `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lockb` — there are no JavaScript dependencies because there is no JavaScript code to run.
- **No** `.github/` directory — no Actions workflows, no issue templates, no PR templates, no CODEOWNERS, no dependabot config, no funding.yml.
- **No** `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `SUPPORT.md`.
- **No** `tests/`, `__tests__/`, or any test runner config.
- **No** `Dockerfile`, `docker-compose.yml`, `.devcontainer/`.
- **No** `Makefile`, `justfile`, `Taskfile`.
- **No** `.eslintrc*`, `.prettierrc*`, `.editorconfig`, `tsconfig.json`.
- **No** `docs/`, `site/`, `website/`, or generated documentation directories.
- **No** image assets — every locale README links the JavaScript icon directly from `img.icons8.com`.
- **No** `.gitignore` — all tracked files are markdown or LICENSE; nothing is generated.

> [!NOTE]
> The absence of `.gitignore` is unusual for a top-1000 GitHub repository and reflects the genuinely empty nature of the build surface. Forks that introduce a build step (e.g. converting markdown into a custom format) should add a `.gitignore` for their generated outputs.

### 9.3 Untracked / ignored files

Because no `.gitignore` exists, contributors should be cautious about:

- **Editor temp files** (`.swp`, `.DS_Store`, `Thumbs.db`) accidentally committed.
- **OS-specific noise** (`Icon\r`, `desktop.ini`).

These have appeared in PRs historically. Reviewers should reject any PR that introduces non-content files.

---

## 10. Code Patterns and Conventions

The "code" in this project is **prose plus embedded JavaScript snippets**. Both have conventions worth documenting.

### 10.1 Markdown conventions in use

| Convention | Pattern | Rationale |
|---|---|---|
| Question heading | `###### N. {text}?` (H6) | Visual subordination so 155 headings don't dominate the document outline. |
| Answer verdict | `#### Answer: {LETTER}` (H4) | Subordinate to the parent question heading. Visually distinct inside the disclosure. |
| Question separator | `---` (thematic break) | Renders as a horizontal rule in GitHub. |
| Code fence language | ` ```javascript ` (full word, not `js`) | GitHub's linguist resolves both, but full-word is the catalogue's chosen consistency. |
| Inline code | `` `…` `` (single backticks) | For variables, options labels (often), and short outputs. |
| Emphasis | `*italic*` and `**bold**` | Standard GFM. |
| Lists | `- A: ...` (hyphen, not asterisk) | Hyphen is the dominant style; some translations drift to `*`. |

### 10.2 Code-snippet style conventions

| Convention | Example | Rationale |
|---|---|---|
| 2-space indent | `function f() {\n  console.log(x);\n}` | Matches Lydia's broader code style. |
| Single quotes | `console.log('hello')` (mostly) | Some snippets use double quotes — drift the maintainer hasn't normalised. |
| Semicolons | Mixed; varies per question | Not strictly enforced; readers shouldn't infer style guidance. |
| No `'use strict'` directive | unless the question is **specifically** testing strict-mode behaviour | Matches the implicit "browser DevTools console" mental model. |
| `console.log` for output | `console.log(x)` | Never `print`, never `process.stdout.write` — the platform is browser-aligned. |
| Variable names | Short and contextual: `x`, `y`, `name`, `age`, `arr`, `obj`, `f`, `g`, `member`, `randomValue` | Consistent across questions; aids translation because translators don't have to mentally re-bind names. |

### 10.3 Explanation-prose conventions

- **Inline backticks for technical terms** at first use: `` `var` ``, `` `let` ``, `` `Promise` ``, etc.
- **Italic for emphasis on conceptual labels**: *"This is called the temporal dead zone"* — italics signal "term of art", not stress.
- **Numbered lists rare**; prose paragraphs preferred. Explanations are typically 1–3 paragraphs.
- **Cross-references between questions** are uncommon; each question stands alone. This is intentional — a reader should never need question N to understand question M.
- **No screenshots, no diagrams**. The runnable snippet plus prose is the entire mental model. A handful of questions reference a hypothetical browser console output; no visual rendering of it.

---

## 11. Quality Heuristics

When reviewing new content (or auditing an existing question for correctness), several heuristics distinguish a strong contribution from a weak one.

### 11.1 Strong-question signals

- The snippet is **short** (≤ 15 lines) and **self-contained**.
- The snippet **runs without modification** in a current browser console.
- At least one option is the **plausible-but-wrong** answer that catches readers who haven't internalised the relevant concept.
- The explanation reveals a **single, identifiable** language behaviour rather than a confluence of three quirks.
- The explanation **cites a specific runtime mechanism** (hoisting, scope chain, microtask queue) by name, anchoring the reader to a learnable concept.

### 11.2 Weak-question warning signs

- Snippet relies on **engine-specific** ordering that disagrees between V8, SpiderMonkey, and JavaScriptCore.
- Multiple correct answers exist depending on **environment** (browser vs Node, strict vs sloppy, module vs script).
- Explanation hand-waves with phrases like *"because that's just how JavaScript works"*.
- Snippet uses a feature **not yet in the catalogue's scope** (top-level await, decorators, private fields).
- The "correct" answer is the literal text on the page rather than the runtime behaviour (e.g. answer is `'undefined'` as a string vs the value `undefined`).
- Question depends on a Web API behaviour rather than a language behaviour.

### 11.3 Translation quality signals

- Translated explanation is a **paraphrase**, not a literal word-for-word translation. Literal translations of English idioms produce clumsy target-language prose.
- Technical terms use the **target language's accepted vocabulary** — *Hebezeit* vs *hoisting* in German, *подъем* vs *хойстинг* in Russian. Consult the existing translated questions for established terminology.
- RTL languages (Arabic) keep code blocks LTR with appropriate `<div>` wrappers around the prose.
- Number formatting in prose follows local conventions (**1.000** vs **1,000** for "one thousand"); inside code blocks, JavaScript syntax (always `1000`) is preserved.

> [!TIP]
> The fastest way to spot a low-effort translation is to check whether the original Lydia anecdote in the README intro paragraph (e.g. "yes I'm sad lol") was translated. If it's still in English, the translation is likely a copy-paste-and-replace job rather than an idiomatic rewrite.

---

## 12. Improvements Roadmap

This section catalogues outstanding issues and the maintainer-stance on each, so derivative platforms can decide which to absorb into their forks.

### 12.1 Open content issues

| Issue | Stance | Notes |
|---|---|---|
| #820 (RU translation of Q98) | Awaiting PR | Russian-speaking contributor needed. |
| #819 (Q25 explanation incomplete) | Will accept improved explanation | The integer-key-then-string-key insertion-order rule should be added. |
| #797 (Q14 about object prototypes) | Discussion | Whether `Object.create(null)` counts as having "no prototype" or "a null prototype" is contested. |
| #831 (Q7 == vs ===) | Will accept improved explanation | Current text doesn't explain coercion explicitly enough. |
| #827 (Russian translation Q71/Q119/Q126) | Awaiting PR | Translation maintenance. |
| #824 (static class member inheritance) | Discussion | The behaviour is correct as documented; the issue is whether *"inheritable"* is the right word. |
| #814 ("Changes required.") | Closing stale | Author hasn't elaborated. |
| #835, #826, #829 ("V", "Oh?", "Hello") | Closing stale | Empty issue bodies; not actionable. |

### 12.2 Closed feature requests worth knowing about

| Issue | Resolution |
|---|---|
| **#714** (rearrange topic-wise) | **Declined.** Renumbering breaks translation alignment. A topic index could be added without renumbering — see §12.3. |
| #647 (broken external link) | **Closed.** Author-personal site went private; the link in README has not been removed but is harmless. |
| #782 (Q61 wrong answer) | **Resolved** in earlier commit. |

### 12.3 Improvements appropriate for forks (not upstream)

These would not be merged upstream because they would expand scope, but a fork may want them:

- **A topic index file** (`TOPICS.md`) that groups questions 1–155 by subject (closures, prototypes, etc.) without renumbering. Could live in a fork as a curated reading order.
- **Per-question difficulty tags** (`Easy` / `Medium` / `Hard`). The maintainer has not introduced difficulty labels because it would require relabelling 22 translations. Forks can do it client-side based on a single canonical mapping.
- **A scoring/quiz mode** UI. The repository is content; building a quiz UI on top is a separate project.
- **Modern-JavaScript supplement** (Q156+) covering 2020–2025 features. If you fork to add this, you opt out of inheriting the upstream commitment to "frozen at 2019".
- **Anki / SRS export.** Question + answer + explanation map cleanly to flashcard front/back. A script can extract them — but you'll have to handle the `<details>` HTML and the H6 numbering quirk.
- **Sitemap of permalinks.** A `sitemap.xml` exposing each `#N-question-text` anchor would help search engines surface individual questions; not needed for the canonical README on github.com but useful for derivative sites.

### 12.4 Things not on the roadmap

- **Build pipeline.** Will not be added; the absence is intentional.
- **CI for content validation.** Could be added (a markdown linter that checks H6 numbering monotonicity, code-fence language tags, `<details>` balance) but historically hasn't been.
- **Web app.** Out of scope upstream. Forks have built quiz apps; the maintainer doesn't endorse any one of them.
- **Internationalisation tooling.** Tools like Crowdin or Weblate could replace the manual translation workflow but would impose process overhead the project hasn't needed at its current pace.

---

## 13. Troubleshooting

### 13.1 Common failure modes for fork operators

#### Error: `<details>` blocks render as plain text in my pipeline

**Cause:** Your markdown processor is sanitising HTML, or you're using a CommonMark parser without the GFM extensions.

**Solution:**
1. If using `markdown-it`: enable `html: true` in the constructor options.
2. If using `marked`: ensure `breaks` and `gfm` are enabled (they are by default in v4+).
3. If using pandoc: pass `-f gfm` (not `-f markdown`) and `--wrap=none`.
4. If using a CMS importer (Confluence, Notion, etc.): check for an HTML allowlist setting; add `details`, `summary`, `p`, `b`, `i`, `div` to the permitted tags.

**Prevention:** Test your pipeline against the canonical README before importing all 22 translations. If question 1's answer doesn't expand on click in your output, the disclosure is broken everywhere.

#### Error: Question count mismatch between English and translation in my parser

**Cause:** Your parser is counting `^###### \d+\.` headings; the locale you're parsing uses a non-standard heading style (Modern Arabic `ar-AR` uses bold-numbered prose, no H6).

**Solution:** Build a locale-aware regex. For most locales, `^######\s+\d+\.` works. For `ar-AR`, the pattern is `^\d+\.\s+` (no heading hashes — questions use plain numbered list items).

**Prevention:** Run a count audit per locale before relying on parsed output. The expected counts are in §6.4.

#### Error: My TOC generator includes 155 question titles, making the TOC unusable

**Cause:** Default markdown-TOC tools include H1–H6 by default. The catalogue's H6-per-question pattern explodes the TOC.

**Solution:** Limit TOC depth. In `markdown-toc`, pass `--maxdepth 4`. In MkDocs, set `toc.permalink: false` and `toc.toc_depth: 4`. In `pandoc`, `--toc-depth=3`.

**Prevention:** Choose a TOC depth that matches the catalogue's structural intent (H2/H3 only, never H6).

#### Error: 404 when clicking the Thai translation link

**Cause:** The English README links to `./th-TH/README-th_TH.md`, but the actual file is `./th-TH/README.md`.

**Solution:** Patch your fork's English README to use the correct relative path. Optionally upstream the fix.

**Prevention:** Validate all relative links during fork ingestion. A simple `markdown-link-check` invocation catches this in CI.

#### Error: Egyptian Arabic option labels (أ, ب, ج, د) don't map to English A/B/C/D in my answer-letter audit

**Cause:** `ar-EG` is the only locale that translates the option labels. Other locales preserve A/B/C/D.

**Solution:** Build a locale-specific letter map. For `ar-EG`: `أ → A`, `ب → B`, `ج → C`, `د → D`.

**Prevention:** Document the locale-specific exceptions in your data layer. Don't assume label uniformity.

#### Error: Russian translation contradicts the English answer for Q98

**Cause:** Issue #820 (open at the time of writing) — the Russian translation is wrong.

**Solution:** Trust the English answer until #820 is resolved. If your fork is multilingual, consider adding a maintainer note flag so users see "this question's translation has a known issue" until upstream resolves it.

**Prevention:** Subscribe to the upstream issue tracker for the questions your derivative platform highlights.

#### Error: My pandoc-to-PDF conversion produces a 600-page document because `<details>` blocks are all expanded

**Cause:** Pandoc renders `<details>` content unconditionally; the "click to expand" is a runtime behaviour of HTML, not a markdown semantic.

**Solution:** This is expected. If you want a printable version with all answers visible, accept the page count. If you want a "questions only" version, pre-process the markdown to strip the `<details>` blocks before conversion.

**Prevention:** Decide upfront whether your derivative artefact is **interactive** (HTML, render-time disclosure preserved) or **printable** (PDF/EPUB, all content visible).

#### Error: Git blame on a translation file shows unhelpful "Merge pull request" commits

**Cause:** Squash-merge PRs collapse the per-line authorship.

**Solution:** Use `git log --follow {translation-file} | grep -A5 'Author:'` to find the most recent **non-merge** commit touching the file. That author is usually the translation's de facto current maintainer.

**Prevention:** When opening a translation-update PR, include `Co-authored-by:` lines in your commit message to preserve credit through the squash.

### 13.2 Common content-side failure modes

#### Error: A question's answer doesn't match what I observe in Node

**Cause:** Many questions assume browser semantics (especially around the global object, strict mode default, and `document.…` references). A handful exhibit different ordering in Node due to microtask scheduling differences.

**Solution:** Test in a browser DevTools console first. If browser and the answer agree but Node disagrees, the discrepancy is a runtime difference, not a question bug.

**Prevention:** When discussing answers, note your runtime environment.

#### Error: A question's answer depends on a JavaScript engine version

**Cause:** Some edge-case behaviours have evolved across spec revisions. The catalogue's snapshot is roughly 2019.

**Solution:** Test with an engine close to the catalogue's vintage (Node 12+, Chrome 75+) for canonical-era behaviour. Most answers are stable across engines and versions.

**Prevention:** When in doubt, the canonical English answer is the authority — engines may *behave* differently in some Marian corner case, but the catalogue documents what the spec said.

---

## 14. Quick Reference

### 14.1 File / locale lookup

| Locale | Path |
|---|---|
| English | `README.md` |
| Arabic (Modern) | `ar-AR/README_AR.md` |
| Arabic (Egyptian) | `ar-EG/README_ar-EG.md` |
| Bosnian | `bs-BS/README-bs_BS.md` |
| German | `de-DE/README.md` |
| Spanish | `es-ES/README-ES.md` |
| French | `fr-FR/README_fr-FR.md` |
| Indonesian | `id-ID/README.md` |
| Italian | `it-IT/README.md` |
| Japanese | `ja-JA/README-ja_JA.md` |
| Korean | `ko-KR/README-ko_KR.md` |
| Dutch | `nl-NL/README.md` |
| Polish | `pl-PL/README.md` |
| Portuguese (Brazil) | `pt-BR/README_pt_BR.md` |
| Romanian | `ro-RO/README.ro.md` |
| Russian | `ru-RU/README.md` |
| Albanian | `sq-KS/README_sq_KS.md` |
| Thai | `th-TH/README.md` |
| Turkish | `tr-TR/README-tr_TR.md` |
| Ukrainian | `uk-UA/README.md` |
| Vietnamese | `vi-VI/README-vi.md` |
| Chinese (Simplified) | `zh-CN/README-zh_CN.md` |
| Chinese (Traditional) | `zh-TW/README_zh-TW.md` |

### 14.2 Schema cheat sheet

```markdown
###### N. {QUESTION}?

```javascript
{SNIPPET}
```

- A: `{OPT_A}`
- B: `{OPT_B}`
- C: `{OPT_C}`
- D: `{OPT_D}`

<details><summary><b>Answer</b></summary>
<p>

#### Answer: {LETTER}

{EXPLANATION}

</p>
</details>

---
```

### 14.3 Useful audit commands

Count questions per locale (assumes you're in the repo root):

```bash
for f in $(find . -mindepth 2 -maxdepth 2 -name 'README*.md'); do
  printf "%-40s %d\n" "$f" "$(grep -cE '^###### [0-9]+\.' "$f")"
done | sort -k2 -n -r
```

```text
./README.md                              155
./it-IT/README.md                        155
./ko-KR/README-ko_KR.md                  155
./ro-RO/README.ro.md                     155
./ru-RU/README.md                        155
./sq-KS/README_sq_KS.md                  155
./zh-TW/README_zh-TW.md                  155
./id-ID/README.md                        153
./vi-VI/README-vi.md                     152
./zh-CN/README-zh_CN.md                  150
…
```

Find every commit that changed a question's correctness (modifies a `#### Answer:` line):

```bash
git log -p --all -- 'README.md' | grep -E '^[+-]#### Answer:' | head -20
```

```text
+#### Answer: A
-#### Answer: B
+#### Answer: C
…
```

(A `+/-` pair on the same question is the smoking gun for an answer correction.)

Verify that every question heading in the canonical README is monotonically numbered:

```bash
grep -E '^###### [0-9]+\.' README.md | grep -oE '[0-9]+' | awk '
  NR==1 { prev=$1; next }
  $1 != prev+1 { print "GAP at " prev " -> " $1; exit 1 }
  { prev=$1 }
  END { print "OK: " prev " questions, monotonic" }'
```

```text
OK: 155 questions, monotonic
```

### 14.4 Maintainer contacts

- **Maintainer:** Lydia Hallie (`@lydiahallie` on GitHub).
- **Issue tracker:** <https://github.com/lydiahallie/javascript-questions/issues>
- **Pull-request queue:** <https://github.com/lydiahallie/javascript-questions/pulls>
- **License:** MIT, copyright © 2019 Lydia Hallie. See `LICENSE` in the repo root.

### 14.5 Glossary

`Canonical edition`
: The English `README.md` at the repository root. The source of truth for question content, numbering, and answer correctness.

`Locale`
: A `{language}-{REGION}` directory containing one translation file. There are 22 locales plus the canonical English at the root.

`Translation drift`
: The state where a translation file documents an older version of the canonical edition because errata or new questions have not yet been propagated.

`Answer letter`
: The single uppercase character (A/B/C/D, occasionally E/F) inside `#### Answer:` that names the correct option for a question.

`Disclosure widget`
: The HTML `<details>`/`<summary>` mechanism that hides the answer until clicked.

`Schema`
: The implicit per-question structural template documented in §5.

`Stale link`
: A relative link in the canonical README that points to a path that no longer exists (e.g. the Thai filename mismatch noted in §6 and §13.1).

`Errata`
: A correction to an existing question's answer or explanation, as opposed to the addition of a new question.

`Renumbering`
: Changing question numbers for any reason. **Forbidden.**

---

_Generated April 2026 from lydiahallie/javascript-questions at a8b427b. 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._
