# OnlineAcademy Handover

## Doel

Automatiseren van het opbouwen van elearningmodules in `create.onlineacademy.nl` met Markdown als bron, maar bewust via de zichtbare editor-UI met Playwright in plaats van via backend write-API's.

De gebruiker wil meekijken tijdens de browserrun en de oplossing moet veilig blijven in een productieomgeving.

## Onderzoeksuitkomst

### Platformstructuur

Live bevestigd:
- links: hoofdstukken/pagina's
- midden: paginacanvas met contentblokken
- rechts: blokbibliotheek en instellingen

Belangrijke UI-ankers die zijn aangetroffen:
- `data-testid="editor-main"`
- `data-testid="page-button"`
- blokken rechts zoals:
  - `drag-block-text`
  - `drag-block-heading`
  - `drag-block-quote`
  - `drag-block-table`
  - `drag-block-multiple-choice`
  - `drag-block-multiple-response`
  - `drag-block-open-question`
  - `drag-block-matching-pairs`

### Bloktypes

In UI gezien:
- `text`
- `heading`
- `quote`
- `table`
- `image`
- `video`
- `audio`
- `downloads`
- `links`
- `expert`
- `typeform`
- `multiple-choice`
- `multiple-response`
- `open-question`
- `matching-pairs`

### Backend read-only bevindingen

Er is bewust alleen read-only gekeken naar de data die de editor zelf ophaalt.

Belangrijke GET endpoints:
- `GET /authoring/v1.0/contents/course/{contentId}`
- `GET /authoring/v1.0/contents/version?externalId=...`

De echte cursusinhoud zit in `jsonContent` en heeft grofweg deze vorm:

```json
{
  "chapters": [
    {
      "id": "...",
      "title": "...",
      "pages": [
        {
          "id": "...",
          "pageType": "number",
          "title": "...",
          "blocks": [
            {
              "id": "...",
              "type": "text",
              "data": { "...": "..." }
            }
          ]
        }
      ]
    }
  ],
  "examPage": {
    "enabled": false,
    "blocks": [],
    "examSettings": {
      "showFeedbackAfterExam": false,
      "questionPool": false,
      "numberOfQuestions": 0,
      "minimumPassingScore": 60
    }
  }
}
```

Deze kennis is alleen gebruikt voor begrip en mapping, niet voor writes.

## Gekozen oplossingsrichting

Niet API-first.

Wel:
- Markdown parser
- intern trainingsmodel
- UI-plan
- zichtbare Playwright runner
- reviewstop vóór save

Reden:
- minder risico in productie
- platformvalidaties blijven actief
- gebruiker kan meekijken
- geen directe backend writes

## Huidige bestanden

### Input / referentie

- [create-md-format.md](/Users/nico/skillstown/create-md-format.md)
- [body.html](/Users/nico/skillstown/body.html)

### Scripts

- [inspect-onlineacademy.mjs](/Users/nico/skillstown/inspect-onlineacademy.mjs)
  Read-only inspectie van login, editor, requests en payloads.

- [markdown-to-onlineacademy-json.mjs](/Users/nico/skillstown/markdown-to-onlineacademy-json.mjs)
  Parser en dry-run converter van Markdown naar platform-compatibele `jsonContent`.

- [onlineacademy-playwright-runner.mjs](/Users/nico/skillstown/onlineacademy-playwright-runner.mjs)
  Zichtbare Playwright runner met:
  - reviewmodus
  - execute-modus
  - login
  - editorverificatie
  - pagina-aanmaak
  - blokinsertie/invulling
  - DOM-snapshot voor detectie van nieuw ingevoegde blokken
  - drop-targeting op de onderkant van het laatste bestaande blok
  - reviewstop vóór save

### Testdata

- [pilot-mvp.md](/Users/nico/skillstown/pilot-mvp.md)
- [pilot-multi-response.md](/Users/nico/skillstown/pilot-multi-response.md)
- [pilot-image.md](/Users/nico/skillstown/pilot-image.md)
- [pilot-table.md](/Users/nico/skillstown/pilot-table.md)
- [pilot-table-large.md](/Users/nico/skillstown/pilot-table-large.md)
- [pilot-open-question.md](/Users/nico/skillstown/pilot-open-question.md)
- [pilot-chapters.md](/Users/nico/skillstown/pilot-chapters.md)
- [pilot-chapters-large.md](/Users/nico/skillstown/pilot-chapters-large.md)
- [create-md-format.onlineacademy.json](/Users/nico/skillstown/create-md-format.onlineacademy.json)
- [pilot-mvp.onlineacademy.json](/Users/nico/skillstown/pilot-mvp.onlineacademy.json)

### Config

- [package.json](/Users/nico/skillstown/package.json)

## Wat werkt al

### Lokaal

- Markdown parsing werkt
- dry-run JSON generatie werkt
- plan/validatie-export werkt

### Live in de zichtbare browser

Bewezen:
- login werkt
- editorherkenning werkt
- reviewmodus zonder mutaties werkt
- nieuwe pagina `Intro` aanmaken werkt
- paginatitel invullen werkt
- drag/drop insertie van blokken werkt aantoonbaar stabieler wanneer op de onderkant van het laatste bestaande blok wordt gedropt
- execute-run in natuurlijke volgorde van boven naar beneden werkt nu voor:
  - `text`
  - `heading`
  - `quote`
- `multiple-choice` blokinsertie werkt en de vraag wordt ingevuld
- `multiple-choice` werkt nu end-to-end voor de pilot:
  - vraag invullen
  - aantal antwoorden afstemmen op Markdown
  - juiste antwoord selecteren
  - feedback invullen
- `multiple-response` werkt nu end-to-end voor de pilot:
  - vraag invullen
  - aantal antwoorden afstemmen op Markdown
  - alle checkboxen resetten
  - meerdere correcte antwoorden selecteren
  - feedback invullen
- `image` werkt nu voor de pilot:
  - upload via lokaal bestandspad
  - titel invullen
  - onderschrift invullen
  - alternatieve tekst invullen
- `table` werkt nu end-to-end voor de pilot:
  - titel invullen
  - `Top header` aan/uit zetten
  - `Left header` aan/uit zetten
  - aantal kolommen uitbreiden op basis van Markdown
  - aantal rijen uitbreiden op basis van Markdown
  - header- en bodycellen invullen
- `open-question` werkt nu end-to-end voor de pilot:
  - vraag invullen
  - toelichting invullen
- hoofdstukaanmaak werkt nu voor de pilot:
  - de execute-flow maakt nu altijd een nieuw hoofdstuk aan via `Nieuw hoofdstuk`
  - automatisch aangemaakte eerste pagina in nieuwe hoofdstukken hernoemen en hergebruiken
  - extra pagina's per hoofdstuk aanmaken wanneer Markdown meer pagina's bevat
- er is niet opgeslagen

## Artifacts / bewijs

Belangrijkste artifacts:

- [editor-ready.png](/Users/nico/skillstown/artifacts/oa-runner/editor-ready.png)
  Editor succesvol geladen.

- [page-1-structure.png](/Users/nico/skillstown/artifacts/oa-runner/page-1-structure.png)
  Nieuwe pagina `Intro` succesvol aangemaakt.

- [page-1-block-1-text.png](/Users/nico/skillstown/artifacts/oa-runner/page-1-block-1-text.png)
  Tekstblok zichtbaar ingevoegd en gevuld.

- [page-1-block-2-heading.png](/Users/nico/skillstown/artifacts/oa-runner/page-1-block-2-heading.png)
  Oud artifact uit een eerdere run waarin blokvolgorde/targeting nog niet stabiel was.

- [page-1-block-2-quote.png](/Users/nico/skillstown/artifacts/oa-runner/page-1-block-2-quote.png)
  Quoteblok succesvol ingevuld in een latere geharde run.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner/review-stop.png)
  Laat de huidige reviewstop zien vóór save, met de blokken in de goede volgorde bovenaan zichtbaar.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner/validation.json)

Pilot na drag/drop-hardening:

- [page-1-block-3-quote.png](/Users/nico/skillstown/artifacts/oa-runner-pilot/page-1-block-3-quote.png)
  Laat zien dat `text`, `heading` en `quote` in natuurlijke volgorde onder elkaar staan.

- [page-1-block-4-multiple-choice.png](/Users/nico/skillstown/artifacts/oa-runner-pilot/page-1-block-4-multiple-choice.png)
  Laat zien dat daarna ook `multiple-choice` onder het quote-blok is ingevoegd en dat de vraag is ingevuld.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-pilot/review-stop.png)
  Bevestigt de pagina-opbouw in volgorde `text` -> `heading` -> `quote` -> `multiple-choice`, zonder save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-pilot/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-pilot/validation.json)

Pilot voor `multiple-choice` afwerking:

- [page-1-block-4-multiple-choice.png](/Users/nico/skillstown/artifacts/oa-runner-mc/page-1-block-4-multiple-choice.png)
  Laat zien dat de meerkeuzevraag nu met exact 2 antwoorden uit Markdown is ingevuld, met het correcte antwoord geselecteerd.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-mc/review-stop.png)
  Laat zien dat ook de feedback/toelichting is ingevuld en dat de run weer stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-mc/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-mc/validation.json)

Pilot voor `multiple-response` afwerking:

- [page-1-block-1-multiple-response.png](/Users/nico/skillstown/artifacts/oa-runner-mr/page-1-block-1-multiple-response.png)
  Laat zien dat de multi-antwoordvraag nu exact 3 antwoorden uit Markdown overneemt, met 2 correcte checkboxen geselecteerd.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-mr/review-stop.png)
  Laat zien dat ook de toelichting is ingevuld en dat de run weer stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-mr/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-mr/validation.json)

Pilot voor `image` afwerking:

- [page-1-block-1-image.png](/Users/nico/skillstown/artifacts/oa-runner-image/page-1-block-1-image.png)
  Laat zien dat de afbeelding is geüpload en dat `Titel`, `Onderschrift` en `Alternatieve tekst` zijn ingevuld.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-image/review-stop.png)
  Laat zien dat de image-run ook weer stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-image/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-image/validation.json)

Pilot voor `table` verkenning:

- [page-1-block-1-table.png](/Users/nico/skillstown/artifacts/oa-runner-table/page-1-block-1-table.png)
  Laat zien dat `Titel`, `Top header`, kolomuitbreiding, rijuitbreiding en de volledige celvulling nu werken voor de tabelpilot.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-table/review-stop.png)
  Laat zien dat de tabel-run ook stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-table/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-table/validation.json)
- [failure-state.png](/Users/nico/skillstown/artifacts/oa-runner-table/failure-state.png)
  Artifact uit een tussenrun waarin de plusknoppen voor kolom/rij-uitbreiding nog niet betrouwbaar werden geraakt.

Pilot voor grotere `table` validatie:

- [page-1-block-1-table.png](/Users/nico/skillstown/artifacts/oa-runner-table-large/page-1-block-1-table.png)
  Laat zien dat de tabel ook opschaalt naar 4 kolommen en 10 regels totaal, inclusief volledige celvulling uit Markdown.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-table-large/review-stop.png)
  Laat zien dat ook de grotere tabel-run stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-table-large/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-table-large/validation.json)

Pilot voor `open-question` afwerking:

- [page-1-block-1-open-question.png](/Users/nico/skillstown/artifacts/oa-runner-open-question/page-1-block-1-open-question.png)
  Laat zien dat de open vraag en de toelichting correct uit Markdown zijn ingevuld.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-open-question/review-stop.png)
  Laat zien dat ook de open-vraag-run stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-open-question/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-open-question/validation.json)

Pilot voor hoofdstukaanmaak:

- [chapter-2-structure.png](/Users/nico/skillstown/artifacts/oa-runner-chapters/chapter-2-structure.png)
  Laat zien dat een tweede hoofdstuk wordt toegevoegd en dat de automatisch aangemaakte eerste pagina daarvan wordt hernoemd en gevuld.

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-chapters/review-stop.png)
  Laat zien dat de tweekoppige hoofdstukpilot stopt vóór save.

- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-chapters/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-chapters/validation.json)

Pilot voor grotere hoofdstukvalidatie:

- [review-stop.png](/Users/nico/skillstown/artifacts/oa-runner-chapters-large/review-stop.png)
  Laat zien dat 4 hoofdstukken met wisselende aantallen pagina's goed worden opgebouwd:
  - `Hoofdstuk Alfa`: 1 pagina
  - `Hoofdstuk Bravo`: 3 pagina's
  - `Hoofdstuk Charlie`: 2 pagina's
  - `Hoofdstuk Delta`: 4 pagina's

- [chapter-2-structure.png](/Users/nico/skillstown/artifacts/oa-runner-chapters-large/chapter-2-structure.png)
- [chapter-3-structure.png](/Users/nico/skillstown/artifacts/oa-runner-chapters-large/chapter-3-structure.png)
- [chapter-4-structure.png](/Users/nico/skillstown/artifacts/oa-runner-chapters-large/chapter-4-structure.png)
- [plan.json](/Users/nico/skillstown/artifacts/oa-runner-chapters-large/plan.json)
- [validation.json](/Users/nico/skillstown/artifacts/oa-runner-chapters-large/validation.json)

## Belangrijkste observatie over drag/drop

De eerdere generieke drop in het bovenste deel van `editor-main` gaf instabiele invoegposities.

Verbetering die live is gevalideerd:
- wanneer het nieuwe blok naar het onderste deel van het laatste bestaande blok wordt gedropt, wordt het in de pilot-run onder dat blok ingevoegd
- de runner vult niet meer "eerste" of "laatste" blok blind in, maar detecteert het nieuwe blok via een DOM-snapshot vóór en na insertie

Gevolg:
- omgekeerde insertievolgorde is niet meer nodig voor de huidige MVP-blokken
- de gebruiker ziet nu een natuurlijke opbouw van boven naar beneden tijdens de zichtbare run

## Belangrijke observatie over verwijderen

Tijdens de grotere hoofdstukpilot verscheen zichtbaar een bevestigingspopup bij het leegmaken van de bestaande eerste pagina.

Waarschijnlijk oorzaak:
- de runner hergebruikt voor hoofdstuk 1 de al bestaande geopende pagina
- daarvoor probeert `clearCurrentPageBlocks(...)` bestaande blokken via `Verwijderen` weg te halen
- de huidige implementatie klikt wel op `Verwijderen`, maar handelt de bevestigingspopup nog niet expliciet en stap-voor-stap af

Gevolg:
- de popup kan enkele seconden knipperen of opnieuw focus krijgen
- dit oogt voor de gebruiker onrustig
- het is een risicovoller stuk gedrag dan de overige blokinvullingen, omdat het om verwijderacties gaat

Pragmatische koerswijziging:
- de execute-flow verwijdert nu geen bestaande hoofdstukken, pagina's of blokken meer
- de runner hergebruikt hoofdstuk 1 niet meer
- voor elk Markdown-hoofdstuk wordt nu altijd een nieuw hoofdstuk aangemaakt
- daarmee verdwijnt de delete-confirmation popup uit het normale execute-pad

## Huidige tekortkomingen

Nog niet robuust:
- de nieuwe drop-strategie en execute-flow zijn live gevalideerd voor pilots met `text`, `heading`, `quote`, `multiple-choice`, `multiple-response`, `image`, `table`, `open-question` en hoofdstukken/pagina's
- scoped targeting per bloktype blijft verder hardening nodig hebben voor bredere bloksets en afwijkende editorstates
- de nieuwe "altijd nieuw hoofdstuk"-strategie moet nog live opnieuw gevalideerd worden

Nog niet opgepakt:
- matching-pairs UI-flow
- save-flow
- opschonen van oude, ongebruikte delete-helpers in de runner

## Veiligheidsafspraken

Tot nu toe gehanteerd:
- headed browser
- slow motion
- reviewmodus zonder mutaties
- execute stopt vóór save
- geen directe backend writes
- artifacts per stap
- execute-flow gebruikt nu geen delete-acties meer

Bewust nog niet gedaan:
- automatisch opslaan
- API writes
- bulkimport in productie

Aanbevolen aanvullende veiligheidsafspraak:
- als een run bestaande content zou moeten verwijderen, laat dat alleen gebeuren na expliciete gebruikersbevestiging
- voor het standaard execute-pad heeft een flow zonder delete-acties de voorkeur

## Run-instructies

In `/Users/nico/skillstown`:

Installeren:

```bash
npm install
```

Dry-run parser:

```bash
node markdown-to-onlineacademy-json.mjs pilot-mvp.md
```

Zichtbare review-run zonder mutaties:

```bash
# verwacht een lokaal `.env` bestand met ten minste:
# OA_EMAIL='...'
# OA_PASSWORD='...'
```

Credentials laden uit `.env`:

```bash
set -a
source .env
set +a
```

Zichtbare review-run zonder mutaties:

```bash
node onlineacademy-playwright-runner.mjs \
  --markdown pilot-mvp.md \
  --url 'https://create.onlineacademy.nl/8602e048-d7ee-4764-aafb-43412d0f65f3/edit?idsVersion=6'
```

Zichtbare execute-run tot reviewstop, zonder save:

```bash
set -a; source .env; set +a
node onlineacademy-playwright-runner.mjs \
  --markdown pilot-mvp.md \
  --url 'https://create.onlineacademy.nl/8602e048-d7ee-4764-aafb-43412d0f65f3/edit?idsVersion=6' \
  --execute \
  --output-dir artifacts/oa-runner-pilot
```

Zichtbare execute-run zonder save:

```bash
set -a
source .env
set +a
node onlineacademy-playwright-runner.mjs \
  --markdown pilot-mvp.md \
  --url 'https://create.onlineacademy.nl/8602e048-d7ee-4764-aafb-43412d0f65f3/edit?idsVersion=6' \
  --execute
```

## Directe volgende stap

Niet meer werken met "laatste blok = nieuw blok".

Hardeningvoorstel:

1. `multiple-choice` volledig afmaken:
   Status: afgerond voor de pilot-run.
2. `multiple-response`
   Status: afgerond voor de pilot-run.
3. `image`
   Status: afgerond voor de pilot-run.
4. `table`
   Status: afgerond voor de pilot-run.
5. `open-question`
   Status: afgerond voor de pilot-run.
6. hoofdstukaanmaak
   Status: afgerond voor de pilot-run, maar execute-flow is inmiddels vereenvoudigd naar "altijd nieuw hoofdstuk" en moet daarop opnieuw live gevalideerd worden.
7. verdere hardening voor andere bloktypes en editorvarianten
8. save-flow

## Eindconclusie

De drag/drop Playwright-route is technisch haalbaar en veiliger passend bij deze productiecontext dan direct backend writes.

De basis is gelegd en live gevalideerd. De veiligste huidige koers is om in execute-runs alleen nieuwe hoofdstukken op te bouwen en geen bestaande content te verwijderen. Verdere hardening blijft nodig op blokpositie, veldtargeting en uiteindelijk de save-flow voordat dit betrouwbaar genoeg is voor herhaalbaar gebruik.
