@lernapps/tooling 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/check/rules/competencies-on-map.mjs +85 -0
  2. package/dist/check/rules/one-competency-per-page.mjs +18 -0
  3. package/dist/check/rules/prerequisites-linked.mjs +38 -0
  4. package/dist/cli.mjs +191 -52
  5. package/dist/explainer-map-DW4XCcY0.mjs +124 -0
  6. package/dist/skills/lernapps-app/SKILL.md +2 -1
  7. package/dist/skills/lernapps-cli/SKILL.md +13 -4
  8. package/dist/skills/lernapps-content-questions/SKILL.md +2 -0
  9. package/dist/skills/lernapps-content-questions/references/question-types.md +2 -1
  10. package/dist/skills/lernapps-content-research/SKILL.md +41 -5
  11. package/dist/skills/lernapps-exercise-patterns/references/mathematics.md +25 -1
  12. package/dist/skills/lernapps-exercise-patterns/references/physics.md +1 -0
  13. package/dist/skills/lernapps-explainer/SKILL.md +10 -4
  14. package/dist/skills/lernapps-explainer/references/blocks.md +7 -3
  15. package/dist/skills/lernapps-explainer/references/exercises.md +6 -0
  16. package/dist/skills/lernapps-explainer/references/rules.md +29 -0
  17. package/dist/skills/lernapps-explainer/references/structure.md +62 -0
  18. package/dist/skills/lernapps-explainer-design/SKILL.md +46 -2
  19. package/dist/skills/lernapps-explainer-design/references/rules.md +1 -0
  20. package/dist/skills/lernapps-explainer-self-assessment/SKILL.md +1 -0
  21. package/dist/skills/lernapps-listing/SKILL.md +9 -0
  22. package/generator/create.ts +39 -10
  23. package/generator/init.ts +89 -19
  24. package/generator/update.ts +53 -8
  25. package/guidance/increment-template.md +13 -5
  26. package/guidance/plan-template.md +25 -11
  27. package/guidance/workflow-rules.md +3 -1
  28. package/package.json +2 -2
  29. package/skills/archetypes/lernapps-explainer/SKILL.md +10 -4
  30. package/skills/archetypes/lernapps-explainer/references/blocks.md +7 -3
  31. package/skills/archetypes/lernapps-explainer/references/exercises.md +6 -0
  32. package/skills/archetypes/lernapps-explainer/references/rules.md +29 -0
  33. package/skills/archetypes/lernapps-explainer/references/structure.md +62 -0
  34. package/skills/archetypes/lernapps-explainer-design/SKILL.md +46 -2
  35. package/skills/archetypes/lernapps-explainer-design/references/rules.md +1 -0
  36. package/skills/archetypes/lernapps-explainer-self-assessment/SKILL.md +1 -0
  37. package/skills/content/lernapps-content-questions/SKILL.md +2 -0
  38. package/skills/content/lernapps-content-questions/references/question-types.md +2 -1
  39. package/skills/content/lernapps-content-research/SKILL.md +41 -5
  40. package/skills/content/lernapps-exercise-patterns/references/mathematics.md +25 -1
  41. package/skills/content/lernapps-exercise-patterns/references/physics.md +1 -0
  42. package/skills/process/lernapps-app/SKILL.md +2 -1
  43. package/skills/process/lernapps-listing/SKILL.md +9 -0
  44. package/skills/tooling/lernapps-cli/SKILL.md +13 -4
@@ -17,8 +17,70 @@
17
17
  - Navigation generated: contents on start and chapter pages, breadcrumbs, previous/next across chapters, page
18
18
  contents from three sections, glossary from `definition` blocks.
19
19
 
20
+ ### When `scope` is needed
21
+
22
+ - All or nothing: `scope` in `src/app.yaml` → every page needs its own `scope`, else the build stops; none in
23
+ `src/app.yaml` → no page has one.
24
+ - Needed when the app has an `open-task` (the tutor judges open answers by the scope, never from general knowledge),
25
+ or follows the creator's material (the scope keeps the tutor to it). Else optional; the plan says which.
26
+ - Each page's `scope`: what the page teaches, in your own words; `src/app.yaml`: `scope: { text, out: [...] }` with
27
+ what does not belong (`explainer-scope-matches`, form in `runtime.md`).
28
+
29
+ ## Format 2: strand and competencies
30
+
31
+ An explainer on the learning map is in format 2. `src/app.yaml` starts with:
32
+
33
+ ```yaml
34
+ # yaml-language-server: $schema=../node_modules/@lernapps/app-templates/runtime/explainer/explainer.v2.schema.json
35
+ format: 2
36
+ strand: mathematik/stochastik # "<subject>/<strand>" of the map, or none
37
+ title: Stochastik
38
+ ```
39
+
40
+ | Field | Where | Rule |
41
+ |---|---|---|
42
+ | `format` | `src/app.yaml` | `2`; absent means format 1 (an app that has not moved) |
43
+ | `strand` | `src/app.yaml` | required in format 2: `<subject>/<strand>` (two ids of the map) or `none` |
44
+ | `competencies` | every page | strand set: required, ids of the app's strand; as a rule one. `none`: not allowed |
45
+
46
+ - A page: `competencies: [laplace]` beside `title` and `blocks`. One page per competency; a large one may take
47
+ several pages; several on one page are not recommended (`one-competency-per-page`).
48
+ - Chapters group competencies that build on each other; pages follow the map's `requires`.
49
+ - One app, one strand. The ids are those of `https://lernapps.net/apps/map/<subject>.json`; the build cannot know
50
+ them. `lernapps check` compares them with the map before the push (`competencies-on-map`); the listing checks
51
+ them again.
52
+ - The build writes `lernapps-pages.json` (path, title, competencies or recap per page, in the app's order) beside
53
+ `index.html`; the catalog lists the pages from it.
54
+
55
+ ### A recap page
56
+
57
+ A competency of the app may require one the app does not practise: of another strand, or of the app's strand outside
58
+ the app's scope. The app may repeat it on a recap page, placed before the page that needs it:
59
+
60
+ ```yaml
61
+ title: Brüche – kurz wiederholt
62
+ recap: mathematik/brueche-anteile # "<subject>/<competency>", one the app does not practise
63
+ blocks: [...] # descriptive blocks only: no exercise
64
+ ```
65
+
66
+ | Rule | Checked by |
67
+ |---|---|
68
+ | A page has either `competencies` or `recap`, never both | schema v2 |
69
+ | A recap page has no exercise; `topic-has-exercises` does not apply to it | schema v2, build |
70
+ | The link to the competency's page on the map is written by the runtime, so it cannot be missing | runtime |
71
+ | The recapped competency exists, and the app does not practise it on a page of its own | `lernapps check` (`competencies-on-map`, warning), listing (error) |
72
+
73
+ - A recap page counts as nothing on the map and is left out of the self-assessment.
74
+ - A prerequisite the app does not practise (of any strand) with neither a recap page nor a link in the page's text to
75
+ `https://lernapps.net/apps/map/<subject>/c/<id>/`: a hint of `lernapps check` (`prerequisites-linked`).
76
+ - Format 1 stays valid. `lernapps update` adds `format: 2` and `strand: none` to a format-1 app when its runtime
77
+ knows format 2.
78
+
20
79
  ## Entry topics
21
80
 
81
+ - An explainer in format 2 has no hand-written topics: the catalog takes its pages from `lernapps-pages.json`. The
82
+ rest of this section holds for the other apps.
83
+
22
84
  - Path of a page or section relative to the app's `url`: `prozent/prozentwert/`, `prozent/prozentwert/#regel`
23
85
  (`entry-links-resolve`; `lernapps check --entry` checks the section).
24
86
  - From the stable ids (`explainer-stable-ids`).
@@ -20,7 +20,20 @@ license: MIT
20
20
 
21
21
  ## Map the content
22
22
 
23
- - A chapter of competencies → an app chapter. A competency → a page or a section.
23
+ - A competency (one teachable thing, one or two lessons) → a page. A large competency may take several pages.
24
+ - A chapter → competencies that build on each other. Order chapters and pages along the map's `requires`: what
25
+ learners need first comes first.
26
+ - Prerequisites: for each page's competency, read its `requires` in the map.
27
+ - The app practises it (a page of its own) → it orders the pages; the text may link the page that teaches it.
28
+ - The app does not practise it → of another strand (one app, one strand), or of the app's strand outside the
29
+ app's scope. The page names it. The app may repeat it on a recap page (`recap: <subject>/<competency>`):
30
+ descriptive blocks only, no exercise; the runtime writes the link to its page on the map. Place the recap page
31
+ before the page that needs it ([structure](../lernapps-explainer/references/structure.md)). Never both: a
32
+ competency the app practises gets no recap page.
33
+ - The app has one strand of the subject's learning map (recommended, skill `lernapps-content-research`), or `none`.
34
+ Every page names the competency of the map it practises (`competencies`, ids of the app's strand). A competency
35
+ the map lacks is proposed to the catalog, not invented here. With `strand: none` pages name none.
36
+ - Show the creator this structure in Explore: which competency on which page, which pages in which chapter.
24
37
  - Depth: chapter, page, section, subsection. Need more levels → two apps.
25
38
  - The content structure → the same sections on every page, with fixed ids and titles (e.g. "Regel", "Beispiel",
26
39
  "Übung").
@@ -33,7 +46,7 @@ license: MIT
33
46
  - Text: prose (restricted Markdown), `definition` (also in the glossary), `example` and `note` boxes, `quote`,
34
47
  `code`.
35
48
  - Formulas: `formula` and inline `$…$`, LaTeX subset incl. chemistry (`\ce`), rendered as MathML.
36
- - Figures: drawn (`hundred-grid`, `bar`), an image (`images/<name>.svg`, with source and licence), a
49
+ - Figures: drawn (`hundred-grid`, `bar`: both a part of a whole), an image (`images/<name>.svg`, with source and licence), a
37
50
  `labelled-figure` with numbered markers, a `table`, a `timeline`.
38
51
  - Exercises: the six question types of the quiz; `generated` (a new task per seed, with drawn values, typical
39
52
  mistakes, hint and steps); a component.
@@ -44,10 +57,41 @@ license: MIT
44
57
 
45
58
  ## Decide
46
59
 
60
+ - Strand: `<subject>/<strand>` from the map where one fits, or `none`. The plan records it, the competency ids of
61
+ each page, each page's prerequisites the app does not practise and which of them get a recap page (format 2,
62
+ [structure](../lernapps-explainer/references/structure.md)).
47
63
  - Languages: German; English as a second language is supported. Each declared language complete. Never English
48
64
  only: without `languages` the page and the runtime's texts are German. English wanted → `[de, en]`.
49
65
  - The tutor: the build writes it from the content. Plan only app-specific tutor rules, if any.
50
66
 
67
+ ## `one-competency-per-page`: One page per competency
68
+
69
+ ```rule
70
+ id: one-competency-per-page
71
+ scope: tooling
72
+ severity: hint
73
+ ```
74
+
75
+ - Each page teaches one competency of the map: `competencies` with one id. Several pages for one large competency
76
+ are fine.
77
+ - Several competencies on one page: allowed by the schema, not recommended. Split the page, one per competency.
78
+ - `lernapps check` gives a hint for every page of a format-2 explainer with more than one competency.
79
+
80
+ ## `prerequisites-linked`: Prerequisites the app does not practise are recapped or linked
81
+
82
+ ```rule
83
+ id: prerequisites-linked
84
+ scope: tooling
85
+ severity: hint
86
+ ```
87
+
88
+ - A competency of a page requires one the app does not practise (`requires` in the map), of another strand or of
89
+ the app's own: learners find it from the app.
90
+ - Either a recap page of the app repeats it (`recap: <subject>/<competency>`), or the page's text names it with a link
91
+ to its page on the map: `https://lernapps.net/apps/map/<subject>/c/<id>/`.
92
+ - `lernapps check` gives a hint for each such prerequisite with neither, naming the page and the prerequisite. Without
93
+ the map it finds nothing (`competencies-on-map` says it could not check).
94
+
51
95
  ## Gotchas
52
96
 
53
97
  - Each component costs a module, a test and a no-JS text: plan one only where it teaches what no block can.
@@ -11,6 +11,7 @@ severity: error
11
11
  - Every page has at least one exercise that practises what the page explains, with solution or feedback; best in a
12
12
  last section "Übung".
13
13
  - The schema requires it; start, chapter and glossary pages are generated. The review judges the fit.
14
+ - Except a recap page (`recap`, format 2): it repeats a prerequisite the app does not practise and has no exercise.
14
15
 
15
16
  ## `prefer-built-in-block`: A component only where no block fits
16
17
 
@@ -89,5 +89,6 @@ selfAssessment:
89
89
 
90
90
  - An exercise renamed or moved → change its reference in the same commit.
91
91
  - `einschaetzung` is reserved: no chapter or page may have that id.
92
+ - A recap page (`recap`) has no exercise: it is never part of a self-assessment.
92
93
  - Never `selfAssessment` in `src/app.yaml` (build problem): the app's comes from the chapters.
93
94
  - Nothing about a real learner in any file (`no-learner-data-in-texts`).
@@ -81,6 +81,8 @@ severity: warning
81
81
 
82
82
  - At least one link per question, best the German Wikipedia (`https://de.wikipedia.org/wiki/...`).
83
83
  - `title` names the page ("Uluru (Wikipedia)").
84
+ - No page of its own (a term like "Wortgleichung"): the page that fits best, preferably the one the question's facts
85
+ came from. Never no link (the schema needs one).
84
86
  - HTTP 429 → tell the creator which; mark the facts "not checked" in the plan; go on.
85
87
 
86
88
  ## `quiz-own-words`: Write in your own words
@@ -9,7 +9,8 @@
9
9
  | `ordering` | `items` in the right order; the page mixes them |
10
10
  | `matching` | `pairs` as they belong, each pair an object `{ left, right }`; the page mixes the right side. `distractors` (1 to 4): wrong right entries that match no left one. `pairsFrom: material` instead of `pairs` takes them from the `labelled-figure` in `material` (marker left, text right; the figure needs `legend: false`) |
11
11
 
12
- - Every question: `id`, `text`, `explanation`, at least one link in `links`. Optional quiz `sources`.
12
+ - Every question: `id`, `text`, `explanation`, at least one link in `links` (no fitting page: `quiz-further-reading`).
13
+ Optional quiz `sources`.
13
14
  - Types without options carry their background in `explanation`.
14
15
  - Optional `material`: what the question shows between its text and its answers, a list of blocks: `text` (restricted
15
16
  Markdown), `formula`, `figure`, `labelled-figure`, `table`, `quote`, `code`. A `figure` is `image: images/<name>.svg`
@@ -20,22 +20,58 @@ license: MIT
20
20
  - Cite it under "Notes": title, issuer, year, address; page and unit (Inhaltsfeld, Lernbereich, Kompetenz).
21
21
  - The creator's material differs → follow the material; say so in one sentence.
22
22
 
23
- ## 2. Competencies
23
+ ## 2. The learning map
24
24
 
25
- - One per line: "Ich kann …" with one observable verb (berechnen, zuordnen, erklären, unterscheiden, ablesen,
25
+ Before you write competencies, look at the learning map of the subject. A strand is recommended, not required.
26
+
27
+ - Open `https://lernapps.net/apps/map/<subject>.json` (for you); people see it at `https://lernapps.net/apps/map/<subject>/`.
28
+ `<subject>` is the file name in the catalog, e.g. `mathematik`. Read it from the file or the page, in full.
29
+ - A strand fits the app → recommend it to the creator: one app, one strand. A strand runs over several school years;
30
+ a topic that spans two strands is two apps. Show the strand and its competencies (Bausteine), with the ones still
31
+ no app practises.
32
+ - The creator takes the strand → the app practises only competencies of that strand. Write each with its id from the
33
+ map. The app's "Ich kann …" competencies are those of the map, in its words: do not reword or invent them. The
34
+ map's `requires` shows what learners need first; a prerequisite the app does not practise, of any strand, gets a
35
+ recap page or a link to the map (skill `lernapps-explainer-design`).
36
+ - The map lacks a competency the creator wants → do not invent it in the app. Propose it to the catalog: an issue or a
37
+ pull request in `lernapps/apps` (`map/<subject>.yaml`, the strand's list). Say so to the creator; go on with the
38
+ ones the map has, or wait for the answer.
39
+ - No strand fits, the creator wants none, or the subject has no map (the address answers "not found") →
40
+ `strand: none`. The app is listed as usual, only not on the map; write its competencies as in the next section.
41
+ - Write the strand (`<subject>/<strand>`, or `none`) and the competency ids under "Notes".
42
+ - Tell the creator now how the content will be structured: a competency is one teachable thing (one or two lessons);
43
+ in an explainer as a rule one page per competency, chapters of competencies that build on each other (skill
44
+ `lernapps-explainer-design`).
45
+
46
+ ### `strand-from-map`: Recommend a strand of the learning map
47
+
48
+ ```rule
49
+ id: strand-from-map
50
+ scope: tooling
51
+ severity: hint
52
+ ```
53
+
54
+ - The subject has a learning map → check its strands and recommend the one that fits the app.
55
+ - `strand: none` only when no strand fits or the creator wants none; say why under "Notes".
56
+ - With a strand: only that strand's competencies, by their ids; a missing one is proposed to `lernapps/apps`.
57
+
58
+ ## 3. Competencies
59
+
60
+ - With a strand: those of the map, see above. Without: one per line: "Ich kann …" with one observable verb (berechnen, zuordnen, erklären, unterscheiden, ablesen,
26
61
  zeichnen). Never "verstehen" or "kennen".
27
62
  - Yes: "Ich kann die Stromstärke in einem Reihenstromkreis berechnen."
28
63
  - No: "Ich verstehe den elektrischen Strom."
29
- - Group them into chapters, in the order of the Lehrplan or the material. Many chapters are still one app.
64
+ - Group them into chapters of competencies that build on each other, in the order of the Lehrplan, the material
65
+ or the map's `requires`. Many chapters are still one app.
30
66
  - Write them under "Notes". Show them at the checkpoint "research".
31
67
 
32
- ## 3. Second sources
68
+ ## 4. Second sources
33
69
 
34
70
  - Per competency one article or video (serlo.org, a channel the creator trusts, Wikipedia).
35
71
  - Read [references/sources.md](references/sources.md) before you choose, cite or rely on a source.
36
72
  - A text source (Wikipedia, a schoolbook site): take facts, never sentences. Copying a sentence needs the licence the page states; if you cannot read it, do not copy.
37
73
 
38
- ## 4. The creator's material and privacy
74
+ ## 5. The creator's material and privacy
39
75
 
40
76
  - The creator's material stays local: never commit or quote it. Only the competencies derived from it go into the
41
77
  repo.
@@ -10,10 +10,34 @@
10
10
  | Idea | Learners see and do | Expressed with |
11
11
  |---|---|---|
12
12
  | Part of a whole (percent, fractions) | a 10×10 grid with the part filled; compute the part, the whole or the rate | `figure` `hundred-grid` on the page; `generated` with `compare: { number: { format: percent } }`; a figure that changes with the task: an exercise component |
13
- | Before and after a change | two bars, old and new value; compute the change or the new value | `figure` `bar` (`part`, `whole`) on the page; `generated` with the typical mistake "added the rate instead of the amount" |
13
+ | Before and after a change | old and new value; compute the change or the new value | a decrease: `figure` `bar` (`part` the new value, `whole` the old; it draws only a part of a whole); an increase: a `table` or an `image` of two bars; `generated` with the typical mistake "added the rate instead of the amount" |
14
14
  | Product of brackets (binomial formulas) | a rectangle split into a², ab, ab, b², lengths from the task | `image` (SVG) for the rule; `generated` for the task; a component only for lengths that follow the task |
15
15
  | Difference of squares | a² − b² as an L-shape, rearranged into (a + b)(a − b) | two `image`s side by side with captions; `ordering` of the steps |
16
16
  | Outcome set (Laplace) | die faces, wheel sectors or balls, the favourable ones marked | `table` or `image`; `generated` drawing from a data file of experiments, answer as a fraction |
17
17
  | Multi-stage experiment | a tree from top to bottom with branch probabilities; multiply along a path | `image` (SVG) of the tree; `generated` with the path rule; a clickable tree as a component |
18
18
  | Drawing without replacement | an urn before and after one ball is taken | two `image`s; `generated` with `pick: 2, distinct: true` from a data file of balls |
19
19
  | Unit conversion | a value with one unit; give it in another | `generated` with `compare: { number: { unit } }` and the mistake "factor in the wrong direction" |
20
+ | Sides and angles in a right triangle (trigonometry) | a right triangle, the angle α marked, its sides named from α (Gegenkathete, Ankathete, Hypotenuse); compute a side from an angle and a side, or an angle from two sides | `image` (SVG) of the triangle with the right angle and α marked, the sides labelled; `formula` with `\sin`, `\cos`, `\tan`, `\arcsin`, Greek letters and `^\circ`; `generated` with `sin`/`cos`/`tan`, `asin`/`acos`/`atan` (degrees) and `sqrt`, answer rounded (`round`, `decimals`, `tolerance`); mistakes: opposite and adjacent side swapped (`cos` instead of `sin`), calculator in radians (the value of `sin` of α taken as radians), sin⁻¹ confused with 1/sin; a triangle that changes with the task: an exercise component |
21
+
22
+ ## Example: a side in a right triangle
23
+
24
+ ```yaml
25
+ - type: generated
26
+ id: gegenkathete-berechnen
27
+ given:
28
+ c: { int: [5, 20] }
29
+ alpha: { int: [20, 70], step: 5 }
30
+ task:
31
+ text: "In einem rechtwinkligen Dreieck ist die Hypotenuse c = {{c}} cm lang, der Winkel α = {{alpha}}°. Wie lang ist die Gegenkathete a von α? Runde auf eine Stelle nach dem Komma."
32
+ answer:
33
+ value: "round(c * sin(alpha), 1)"
34
+ compare: { number: { format: decimal, decimals: 1, tolerance: 0.1, unit: cm } }
35
+ mistakes:
36
+ - { value: "round(c * cos(alpha), 1)", message: "Das ist die Ankathete: die Gegenkathete liegt α gegenüber, also Sinus." }
37
+ - { value: "round(c * sin(alpha * 57.29578), 1)", message: "Dein Taschenrechner rechnet im Bogenmaß (RAD): stelle ihn auf Grad (DEG)." }
38
+ - { value: "round(c / sin(alpha), 1)", message: "sin α = a : c, also a = c · sin α: mal, nicht geteilt." }
39
+ ```
40
+
41
+ An angle from two sides: `answer: { value: "round(asin(a / c), 1)" }`, in degrees. Mistakes: opposite and adjacent
42
+ swapped (`round(acos(a / c), 1)`, the other angle); sin⁻¹ taken as 1 : sin (`round(c / a, 1)`: "sin⁻¹ ist die
43
+ Umkehrfunktion, nicht 1 : sin"). A mistake value must have a value: `asin(c / a)` with c > a has none.
@@ -16,3 +16,4 @@
16
16
  | Lever and moment | a beam with weights at distances; does it balance | `image` of the beam; `generated` for F₁ · a₁ = F₂ · a₂; a component with draggable weights |
17
17
  | Optics | a ray diagram of a convex lens; where the image forms | `labelled-figure` of the rays; `true-false` on image properties; a component with a draggable object |
18
18
  | Density | blocks of equal mass and different volumes; float or sink | `table` from a data file of materials; `generated` with `compare: { choice: [schwimmt, sinkt] }` |
19
+ | Energy and efficiency | forms of energy before and after; how much is useful | `figure` `bar` only for a part of a whole (useful energy of the energy put in, the efficiency); energies side by side or a transfer chain → `table` or an `image` (SVG); `generated` with the values from a data file (`from: { data: … }`, records with numbers never inline) |
@@ -39,7 +39,8 @@ The READMEs are files of the package `@lernapps/app-templates`, which `init` ins
39
39
 
40
40
  - Choose after the interview topics "Goal" and "Learners", from what learners do. Read the patterns of the subject
41
41
  first (skill `lernapps-exercise-patterns`): how learners practise points to the archetype.
42
- - Before you choose, read the README of each archetype in question, in full. Tell the creator in plain words what the
42
+ - Before you choose, read the README of every archetype you consider, in full. One you rule out from the kind of
43
+ practice alone needs no README: say in one sentence why it does not fit. Tell the creator in plain words what the
43
44
  chosen one can and cannot do, before you ask about content, amount and look.
44
45
  - A few background sections on the start page keep an app `interactive`.
45
46
  - Explanation pages with one interactive exercise → `explainer` with a component.
@@ -19,6 +19,15 @@ At the checkpoint "list", without asking first: the pull request publishes nothi
19
19
  check it, how to open the pull request.
20
20
  2. Fill the entry from the plan's entry draft and <https://lernapps.net/apps/schemas/entry.v1.schema.json>, fetched
21
21
  now. The schema describes every field.
22
+ - An explainer in format 2: its pages come from `lernapps-pages.json` of the build, not from a hand-written list. The
23
+ listing checks the competency ids against the map and that they belong to the app's `strand`. A `strand` in
24
+ the entry, if given, equals the one in that file.
25
+ - Any other app may give `strand` (`<subject>/<strand>`) and `competencies` (ids of that subject) in the entry;
26
+ `competencies` needs a `strand`. An app without a strand is not on the map; that is valid.
27
+ - An unknown id or one of another strand is an error of the listing (`entry-learning-map`, lernapps/apps).
28
+ The review adds two hints, never errors: a strand that could fit an app with `strand: none`
29
+ (`strand-from-map`), a page that teaches more or other than its competencies say
30
+ (`content-matches-competencies`). `lernapps check` warns about unknown ids before (`competencies-on-map`).
22
31
  3. Run the check the guide names. Fix its findings first: the pull request runs the same check.
23
32
  4. Open the pull request from the creator's fork as skill `lernapps-github` says.
24
33
 
@@ -15,11 +15,18 @@ license: MIT
15
15
 
16
16
  1. Only after the creator's yes to the plan (`explore-before-code`). In the plan's folder:
17
17
  `npx --no -- lernapps create --archetype <archetype>`.
18
- 2. No git repo yet: `git init --initial-branch=work`. Then `npm install` (dependencies, git hooks), and commit
19
- everything on `work`.
18
+ 2. `create` installs nothing and commits nothing; its last lines say what follows, in this order: no git repo yet
19
+ (`lernapps init` makes one): `git init --initial-branch=work`; then `npm install` (runtime, git hooks); then commit
20
+ everything on `work` (`git add -A`, `git commit`; the hooks check it).
20
21
  3. Needs git, Node ≥ 22.18, registry.npmjs.org. Blocked → ask the creator to allow it, run again. Never write the
21
22
  app by hand.
22
23
  4. It keeps the plan and the installed skills, and writes the content guide's skeleton.
24
+ 5. Maintainers only, to try a tooling that is not on the registry (a local build has version `0.0.0`): give it to
25
+ both, `lernapps init <short name> --tooling <spec>` and `create --tooling <spec>`, e.g.
26
+ `file:/path/to/lernapps-tooling-0.0.0.tgz` (from `npm pack`) or `github:lernapps/tooling#<commit>`. Run from a
27
+ checkout of the tooling, `init` packs it into a temporary folder and installs that tarball by itself; `create`
28
+ takes the same from `package.json`. A sandbox without a server for the map: `LERNAPPS_TEST_MAP_URL=<folder>` (or a
29
+ `file:` URL) makes `lernapps check` read `<folder>/<subject>.json`.
23
30
 
24
31
  ## Update
25
32
 
@@ -38,8 +45,10 @@ license: MIT
38
45
  A check says the rules hold; only a look says what a learner sees. Show the creator the pages before a push, and before
39
46
  a submission they declare something about.
40
47
 
41
- - Explainer or quiz: build (`npx vp build`), then `npx --no -- lernapps screenshots`. It writes one image of every page, one of
42
- every figure, and an `index.html` that shows them in order to `screenshots/` (not part of the app: do not commit it).
48
+ - Explainer or quiz: build (`npx vp build` writes `dist/`; `npm run build` writes `_site/`), then
49
+ `npx --no -- lernapps screenshots`: it takes the newer of `dist/` and `_site/`, or the folder you name. It writes
50
+ one image of every page, one of every figure, and an `index.html` that shows them in order to `screenshots/` (not
51
+ part of the app: do not commit it).
43
52
  Show the images, or the `index.html` where you can show HTML. Check every figure in its own image
44
53
  (`…-figure-<n>.png`): a page image is scaled down, its details are not readable. `--desktop` adds 1280 px images.
45
54
  Options: `npx --no -- lernapps screenshots --help`. The folder ignores itself in git, so a later check never sees it.