@lernapps/app-templates 0.0.1 → 0.1.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 (231) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +195 -2
  3. package/dist/appname-Bh23cUuz.mjs +12 -0
  4. package/dist/assessment-By2GGTJC.mjs +1696 -0
  5. package/dist/block-BK_ohsH1.mjs +82 -0
  6. package/dist/blocks-BmRrD7UY.mjs +149 -0
  7. package/dist/blocks.mjs +4 -0
  8. package/dist/check-BkEl-m-F.mjs +254 -0
  9. package/dist/content-cYBPYg_J.mjs +140 -0
  10. package/dist/contract-PONpxJtd.mjs +52 -0
  11. package/dist/e2e-BiMI-pCL.mjs +89 -0
  12. package/dist/engine-BqF2Vffn.mjs +136 -0
  13. package/dist/explainer-e2e.mjs +1297 -0
  14. package/dist/explainer-islands.mjs +197 -0
  15. package/dist/explainer-plugin.mjs +2131 -0
  16. package/dist/explainer.mjs +1246 -0
  17. package/dist/html-mffkHGHh.mjs +89 -0
  18. package/dist/image-CspJVfyQ.mjs +21 -0
  19. package/dist/interactive-e2e.mjs +140 -0
  20. package/dist/interactive-plugin.mjs +242 -0
  21. package/dist/interactive.mjs +75 -0
  22. package/dist/load-C-0hUaSC.mjs +16947 -0
  23. package/dist/needs-BzEahJ6X.mjs +97 -0
  24. package/dist/pages-9RaaomoO.mjs +81 -0
  25. package/dist/questions-e2e.mjs +1 -0
  26. package/dist/questions-engine.mjs +3 -0
  27. package/dist/questions.mjs +6 -0
  28. package/dist/quiz-BKc8JYtC.mjs +70 -0
  29. package/dist/quiz-e2e.mjs +174 -0
  30. package/dist/quiz-plugin.mjs +266 -0
  31. package/dist/quiz.mjs +246 -0
  32. package/dist/render-BJey0bwl.mjs +540 -0
  33. package/dist/render-BL6fV_NI.mjs +507 -0
  34. package/dist/render-DpRO_RKm.mjs +146 -0
  35. package/dist/result-_eQcamoz.mjs +180 -0
  36. package/dist/tasks-DADUYy52.mjs +74 -0
  37. package/dist/validate-COaZso7u.mjs +1072 -0
  38. package/dist/validate-CxtdeQ5S.mjs +146 -0
  39. package/dist/vue-DO1m6q1R.mjs +40 -0
  40. package/dist/vue-code-BkJjW_I_.mjs +320 -0
  41. package/docs/arc42/01-introduction-and-goals.arc42.md +82 -0
  42. package/docs/arc42/02-constraints.arc42.md +228 -0
  43. package/docs/arc42/03-system-context.arc42.md +118 -0
  44. package/docs/arc42/04-solution-strategy.arc42.md +47 -0
  45. package/docs/arc42/05-building-blocks.arc42.md +307 -0
  46. package/docs/arc42/06-runtime-view.arc42.md +98 -0
  47. package/docs/arc42/07-deployment-view.arc42.md +160 -0
  48. package/docs/arc42/08-concepts.arc42.md +123 -0
  49. package/docs/arc42/09-decisions.arc42.md +246 -0
  50. package/docs/arc42/10-quality-requirements.arc42.md +155 -0
  51. package/docs/arc42/11-risks.arc42.md +113 -0
  52. package/docs/arc42/12-glossary.arc42.md +162 -0
  53. package/docs/arc42/architecture-evidence.md +395 -0
  54. package/explainer/.arc42ignore +3 -0
  55. package/explainer/README.md +54 -0
  56. package/explainer/_gitignore +5 -0
  57. package/explainer/docs/arc42/03-explainer-system-context.arc42.md +35 -0
  58. package/explainer/docs/arc42/05-explainer-building-blocks.arc42.md +659 -0
  59. package/explainer/docs/arc42/06-explainer-runtime-view.arc42.md +105 -0
  60. package/explainer/docs/arc42/07-explainer-deployment-view.arc42.md +34 -0
  61. package/explainer/docs/arc42/08-explainer-concepts.arc42.md +17 -0
  62. package/explainer/docs/arc42/09-explainer-decisions.arc42.md +443 -0
  63. package/explainer/docs/arc42/10-explainer-quality-requirements.arc42.md +54 -0
  64. package/explainer/docs/arc42/11-explainer-risks.arc42.md +17 -0
  65. package/explainer/docs/arc42/12-explainer-glossary.arc42.md +185 -0
  66. package/explainer/e2e/explainer.e2e.ts +3 -0
  67. package/explainer/index.html +11 -0
  68. package/explainer/package.json +18 -0
  69. package/explainer/playwright.config.ts +1 -0
  70. package/explainer/src/app.yaml +20 -0
  71. package/explainer/src/components/ProzentFeld.test.ts +30 -0
  72. package/explainer/src/components/ProzentFeld.ts +121 -0
  73. package/explainer/src/components/ProzentFeld.vue +84 -0
  74. package/explainer/src/images/hunderterfeld-klammern.svg +105 -0
  75. package/explainer/src/main.ts +4 -0
  76. package/explainer/src/prozent/chapter.yaml +18 -0
  77. package/explainer/src/prozent/grundwert.yaml +115 -0
  78. package/explainer/src/prozent/prozentsatz.yaml +99 -0
  79. package/explainer/src/prozent/prozentwert.yaml +119 -0
  80. package/explainer/tsconfig.json +1 -0
  81. package/explainer/vite.config.ts +4 -0
  82. package/interactive/.arc42ignore +5 -0
  83. package/interactive/README.md +28 -0
  84. package/interactive/_gitignore +4 -0
  85. package/interactive/docs/arc42/05-interactive-building-blocks.arc42.md +518 -0
  86. package/interactive/docs/arc42/06-interactive-runtime-view.arc42.md +58 -0
  87. package/interactive/docs/arc42/07-interactive-deployment-view.arc42.md +35 -0
  88. package/interactive/docs/arc42/08-interactive-concepts.arc42.md +52 -0
  89. package/interactive/docs/arc42/09-interactive-decisions.arc42.md +130 -0
  90. package/interactive/docs/arc42/10-interactive-quality-requirements.arc42.md +45 -0
  91. package/interactive/docs/arc42/11-interactive-risks.arc42.md +20 -0
  92. package/interactive/docs/arc42/12-interactive-glossary.arc42.md +80 -0
  93. package/interactive/e2e/interactive.e2e.ts +3 -0
  94. package/interactive/index.html +11 -0
  95. package/interactive/package.json +18 -0
  96. package/interactive/playwright.config.ts +1 -0
  97. package/interactive/src/app.yaml +28 -0
  98. package/interactive/src/core/index.ts +101 -0
  99. package/interactive/src/data/lessons.json +4 -0
  100. package/interactive/src/env.d.ts +6 -0
  101. package/interactive/src/main.ts +6 -0
  102. package/interactive/src/messages/de.json +12 -0
  103. package/interactive/src/playthroughs/grundreihe.yaml +33 -0
  104. package/interactive/src/playthroughs/obere-reihe.yaml +14 -0
  105. package/interactive/src/ui/App.vue +85 -0
  106. package/interactive/tsconfig.json +1 -0
  107. package/interactive/vite.config.ts +4 -0
  108. package/package.json +142 -4
  109. package/quiz/README.md +31 -0
  110. package/quiz/_gitignore +5 -0
  111. package/quiz/docs/arc42/05-quiz-building-blocks.arc42.md +283 -0
  112. package/quiz/docs/arc42/06-quiz-runtime-view.arc42.md +21 -0
  113. package/quiz/docs/arc42/07-quiz-deployment-view.arc42.md +33 -0
  114. package/quiz/docs/arc42/09-quiz-decisions.arc42.md +36 -0
  115. package/quiz/docs/arc42/10-quiz-quality-requirements.arc42.md +53 -0
  116. package/quiz/docs/arc42/11-quiz-risks.arc42.md +19 -0
  117. package/quiz/docs/arc42/12-quiz-glossary.arc42.md +27 -0
  118. package/quiz/e2e/quiz.e2e.ts +3 -0
  119. package/quiz/index.html +11 -0
  120. package/quiz/package.json +18 -0
  121. package/quiz/playwright.config.ts +1 -0
  122. package/quiz/src/images/berge-ordnen.jpg +0 -0
  123. package/quiz/src/images/everest-hoehe.jpg +0 -0
  124. package/quiz/src/images/galapagos.jpg +0 -0
  125. package/quiz/src/images/grand-canyon.jpg +0 -0
  126. package/quiz/src/images/totes-meer.jpg +0 -0
  127. package/quiz/src/images/uluru.jpg +0 -0
  128. package/quiz/src/images/wasserfaelle-laender.jpg +0 -0
  129. package/quiz/src/main.ts +4 -0
  130. package/quiz/src/quiz.json +312 -0
  131. package/quiz/tsconfig.json +1 -0
  132. package/quiz/vite.config.ts +4 -0
  133. package/runtime/explainer/assessment-client.ts +478 -0
  134. package/runtime/explainer/assessment-page.ts +446 -0
  135. package/runtime/explainer/assessment.ts +393 -0
  136. package/runtime/explainer/check-page.ts +520 -0
  137. package/runtime/explainer/components/exercise.ts +409 -0
  138. package/runtime/explainer/components/props.ts +230 -0
  139. package/runtime/explainer/components/read.ts +428 -0
  140. package/runtime/explainer/content.ts +277 -0
  141. package/runtime/explainer/e2e.ts +1474 -0
  142. package/runtime/explainer/exercises.ts +324 -0
  143. package/runtime/explainer/explainer.css +1283 -0
  144. package/runtime/explainer/explainer.ts +838 -0
  145. package/runtime/explainer/explainer.v1.schema.json +1165 -0
  146. package/runtime/explainer/expression.ts +407 -0
  147. package/runtime/explainer/fraction.ts +107 -0
  148. package/runtime/explainer/generated/comparator.ts +31 -0
  149. package/runtime/explainer/generated/question.ts +165 -0
  150. package/runtime/explainer/generated/soundness.ts +280 -0
  151. package/runtime/explainer/generated/texts.ts +257 -0
  152. package/runtime/explainer/generated/types.ts +103 -0
  153. package/runtime/explainer/generated/values.ts +136 -0
  154. package/runtime/explainer/islands.ts +281 -0
  155. package/runtime/explainer/load.ts +457 -0
  156. package/runtime/explainer/messages/de.json +200 -0
  157. package/runtime/explainer/messages/en.json +200 -0
  158. package/runtime/explainer/messages.ts +13 -0
  159. package/runtime/explainer/needs.ts +122 -0
  160. package/runtime/explainer/open-task.ts +235 -0
  161. package/runtime/explainer/outline.ts +299 -0
  162. package/runtime/explainer/plugin.ts +488 -0
  163. package/runtime/explainer/position.ts +62 -0
  164. package/runtime/explainer/prompt.ts +75 -0
  165. package/runtime/explainer/render.ts +686 -0
  166. package/runtime/explainer/result.ts +238 -0
  167. package/runtime/explainer/routes.ts +119 -0
  168. package/runtime/explainer/schema.ts +140 -0
  169. package/runtime/explainer/scope.ts +87 -0
  170. package/runtime/explainer/stuck.ts +57 -0
  171. package/runtime/explainer/tasks.ts +109 -0
  172. package/runtime/explainer/tutor.ts +469 -0
  173. package/runtime/explainer/tutorpage.ts +669 -0
  174. package/runtime/explainer/video.ts +123 -0
  175. package/runtime/interactive/contract.ts +121 -0
  176. package/runtime/interactive/e2e.ts +190 -0
  177. package/runtime/interactive/interactive.css +82 -0
  178. package/runtime/interactive/interactive.ts +115 -0
  179. package/runtime/interactive/interactive.v1.schema.json +146 -0
  180. package/runtime/interactive/load.ts +188 -0
  181. package/runtime/interactive/messages/de.json +14 -0
  182. package/runtime/interactive/messages/en.json +14 -0
  183. package/runtime/interactive/messages.ts +11 -0
  184. package/runtime/interactive/playthrough.v1.schema.json +143 -0
  185. package/runtime/interactive/plugin.ts +266 -0
  186. package/runtime/interactive/render.ts +126 -0
  187. package/runtime/quiz/e2e.ts +233 -0
  188. package/runtime/quiz/engine.ts +242 -0
  189. package/runtime/quiz/messages/de.json +23 -0
  190. package/runtime/quiz/messages/en.json +23 -0
  191. package/runtime/quiz/plugin.ts +150 -0
  192. package/runtime/quiz/quiz.css +154 -0
  193. package/runtime/quiz/quiz.ts +56 -0
  194. package/runtime/quiz/quiz.v1.schema.json +72 -0
  195. package/runtime/quiz/render.ts +173 -0
  196. package/runtime/quiz/validate.ts +108 -0
  197. package/runtime/shared/appname.ts +16 -0
  198. package/runtime/shared/blocks/block.ts +162 -0
  199. package/runtime/shared/blocks/blocks.css +190 -0
  200. package/runtime/shared/blocks/blocks.v1.schema.json +432 -0
  201. package/runtime/shared/blocks/code.ts +26 -0
  202. package/runtime/shared/blocks/figures.ts +49 -0
  203. package/runtime/shared/blocks/image.ts +25 -0
  204. package/runtime/shared/blocks/index.ts +13 -0
  205. package/runtime/shared/blocks/messages/de.json +4 -0
  206. package/runtime/shared/blocks/messages/en.json +4 -0
  207. package/runtime/shared/blocks/render.ts +134 -0
  208. package/runtime/shared/blocks/validate.ts +165 -0
  209. package/runtime/shared/content.ts +197 -0
  210. package/runtime/shared/examples.ts +20 -0
  211. package/runtime/shared/html.ts +10 -0
  212. package/runtime/shared/languages.ts +94 -0
  213. package/runtime/shared/page.css +101 -0
  214. package/runtime/shared/pages.ts +114 -0
  215. package/runtime/shared/questions/e2e.ts +115 -0
  216. package/runtime/shared/questions/engine.ts +209 -0
  217. package/runtime/shared/questions/index.ts +39 -0
  218. package/runtime/shared/questions/messages/de.json +26 -0
  219. package/runtime/shared/questions/messages/en.json +26 -0
  220. package/runtime/shared/questions/question.ts +430 -0
  221. package/runtime/shared/questions/question.v1.schema.json +342 -0
  222. package/runtime/shared/questions/questions.css +192 -0
  223. package/runtime/shared/questions/render.ts +247 -0
  224. package/runtime/shared/questions/validate.ts +518 -0
  225. package/runtime/shared/schema.ts +44 -0
  226. package/runtime/shared/text/check.ts +68 -0
  227. package/runtime/shared/text/formula.ts +69 -0
  228. package/runtime/shared/text/markdown.ts +185 -0
  229. package/runtime/shared/text/text.v1.schema.json +34 -0
  230. package/runtime/shared/vue-code.ts +395 -0
  231. package/runtime/shared/vue.ts +38 -0
package/package.json CHANGED
@@ -1,8 +1,146 @@
1
1
  {
2
2
  "name": "@lernapps/app-templates",
3
- "version": "0.0.1",
4
- "description": "Placeholder that reserves the name. The first release (0.1.0) follows from CI with provenance; see https://github.com/lernapps/app-templates",
3
+ "version": "0.1.0",
4
+ "description": "The templates of the archetypes of lernapps.net apps, and the runtime of each archetype that apps depend on (the quiz: engine, build step, styles, end-to-end tests, the schema of the question bank, the questions it shares with the explainer are in ./questions; the explainer: build step, client module with its exercises, the islands of its Vue components, styles, end-to-end tests, the schema of its content; the interactive archetype: build step, the start page and the app page around the app's own Vue components and core, its playthroughs, styles, end-to-end tests, the schemas of its start page and its playthroughs)",
5
5
  "license": "MIT",
6
- "repository": { "type": "git", "url": "git+https://github.com/lernapps/app-templates.git" },
7
- "publishConfig": { "access": "public" }
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/lernapps/app-templates.git"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "runtime",
13
+ "docs/arc42",
14
+ "explainer",
15
+ "interactive",
16
+ "quiz",
17
+ "!**/package-lock.json",
18
+ "!**/node_modules"
19
+ ],
20
+ "type": "module",
21
+ "exports": {
22
+ "./package.json": "./package.json",
23
+ "./blocks": {
24
+ "types": "./runtime/shared/blocks/index.ts",
25
+ "default": "./dist/blocks.mjs"
26
+ },
27
+ "./blocks/blocks.v1.schema.json": "./runtime/shared/blocks/blocks.v1.schema.json",
28
+ "./text/text.v1.schema.json": "./runtime/shared/text/text.v1.schema.json",
29
+ "./questions": {
30
+ "types": "./runtime/shared/questions/index.ts",
31
+ "default": "./dist/questions.mjs"
32
+ },
33
+ "./questions/engine": {
34
+ "types": "./runtime/shared/questions/engine.ts",
35
+ "default": "./dist/questions-engine.mjs"
36
+ },
37
+ "./questions/e2e": {
38
+ "types": "./runtime/shared/questions/e2e.ts",
39
+ "default": "./dist/questions-e2e.mjs"
40
+ },
41
+ "./questions/question.v1.schema.json": "./runtime/shared/questions/question.v1.schema.json",
42
+ "./quiz": {
43
+ "types": "./runtime/quiz/engine.ts",
44
+ "default": "./dist/quiz.mjs"
45
+ },
46
+ "./quiz/plugin": {
47
+ "types": "./runtime/quiz/plugin.ts",
48
+ "default": "./dist/quiz-plugin.mjs"
49
+ },
50
+ "./quiz/e2e": {
51
+ "types": "./runtime/quiz/e2e.ts",
52
+ "default": "./dist/quiz-e2e.mjs"
53
+ },
54
+ "./quiz/style.css": "./runtime/quiz/quiz.css",
55
+ "./quiz/quiz.v1.schema.json": "./runtime/quiz/quiz.v1.schema.json",
56
+ "./explainer": {
57
+ "types": "./runtime/explainer/explainer.ts",
58
+ "default": "./dist/explainer.mjs"
59
+ },
60
+ "./explainer/plugin": {
61
+ "types": "./runtime/explainer/plugin.ts",
62
+ "default": "./dist/explainer-plugin.mjs"
63
+ },
64
+ "./explainer/e2e": {
65
+ "types": "./runtime/explainer/e2e.ts",
66
+ "default": "./dist/explainer-e2e.mjs"
67
+ },
68
+ "./explainer/style.css": "./runtime/explainer/explainer.css",
69
+ "./explainer/explainer.v1.schema.json": "./runtime/explainer/explainer.v1.schema.json",
70
+ "./interactive": {
71
+ "types": "./runtime/interactive/interactive.ts",
72
+ "default": "./dist/interactive.mjs"
73
+ },
74
+ "./interactive/plugin": {
75
+ "types": "./runtime/interactive/plugin.ts",
76
+ "default": "./dist/interactive-plugin.mjs"
77
+ },
78
+ "./interactive/e2e": {
79
+ "types": "./runtime/interactive/e2e.ts",
80
+ "default": "./dist/interactive-e2e.mjs"
81
+ },
82
+ "./interactive/style.css": "./runtime/interactive/interactive.css",
83
+ "./interactive/interactive.v1.schema.json": "./runtime/interactive/interactive.v1.schema.json",
84
+ "./interactive/playthrough.v1.schema.json": "./runtime/interactive/playthrough.v1.schema.json"
85
+ },
86
+ "publishConfig": {
87
+ "access": "public",
88
+ "provenance": true
89
+ },
90
+ "scripts": {
91
+ "prepare": "vp pack && vp config --no-agent",
92
+ "test": "vp test",
93
+ "check:vue": "vue-tsc --noEmit -p tsconfig.vue.json",
94
+ "prepack": "node scripts/pack-dotfiles.ts stage",
95
+ "postpack": "node scripts/pack-dotfiles.ts clean"
96
+ },
97
+ "dependencies": {
98
+ "@vitejs/plugin-vue": "6.0.10",
99
+ "ajv": "8.20.0",
100
+ "highlight.js": "11.12.0",
101
+ "marked": "18.1.2",
102
+ "source-map-js": "1.2.2",
103
+ "temml": "0.14.0",
104
+ "vue": "3.5.44",
105
+ "yaml": "2.9.1"
106
+ },
107
+ "devDependencies": {
108
+ "@doctc/arc42": "0.38.0",
109
+ "@types/node": "26.6.5",
110
+ "typescript": "6.0.3",
111
+ "vite-plus": "1.4.0",
112
+ "vue-tsc": "3.3.13"
113
+ },
114
+ "peerDependencies": {
115
+ "@lernapps/tooling": "*",
116
+ "playwright": "*",
117
+ "vite-plus": "1.4.0"
118
+ },
119
+ "peerDependenciesMeta": {
120
+ "@lernapps/tooling": {
121
+ "optional": true
122
+ },
123
+ "playwright": {
124
+ "optional": true
125
+ },
126
+ "vite-plus": {
127
+ "optional": true
128
+ }
129
+ },
130
+ "overrides": {
131
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.4.0"
132
+ },
133
+ "engines": {
134
+ "node": "^22.18.0 || ^24.11.0 || >=26.0.0"
135
+ },
136
+ "lernapps": {
137
+ "changes": {
138
+ "kind": "app"
139
+ },
140
+ "archetypes": [
141
+ "explainer",
142
+ "interactive",
143
+ "quiz"
144
+ ]
145
+ }
8
146
  }
package/quiz/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Archetype quiz
2
+
3
+ A quiz about things to know: one page of questions with options, feedback on every option, score and solutions.
4
+
5
+ ## What it can do
6
+
7
+ - Six question types: single choice, multiple choice, true or false, a number within a tolerance, putting items in
8
+ order, matching pairs.
9
+ - Background on every option, an explanation for every question, links to further reading, an optional hint, typical
10
+ wrong numbers with their message.
11
+ - One question at a time with feedback; at the end the score and all solutions. Without JavaScript: a worksheet with
12
+ the solutions.
13
+ - Questions in a shuffled order; a link with a seed gives every learner the same order. A link to each question.
14
+ - The learner chooses at the start how many questions to answer (at most all of them): the seed picks them, and the address (`?seed=…&n=…`) keeps the choice, so a link gives every learner the same questions.
15
+ - German, plus English: a page per language.
16
+ - Optionally keeps the last score on the learner's device.
17
+ - Content in a question, between its text and its answers (`material`): prose, a formula, a figure (your own image in
18
+ `src/images/` with its source and licence, or drawn from numbers), a labelled figure, a table, a quotation, code.
19
+ Every figure has an alternative text and a caption; the build checks the blocks and carries the images.
20
+
21
+ ## What it cannot do
22
+
23
+ - No other media than images: no audio, no video. Content does not move.
24
+ - No own colours or layout: the look is the runtime's, calm like a worksheet. Dark mode follows the device.
25
+ - No timer, no new tasks drawn each time, no count the learner chooses.
26
+
27
+ ## What the app supplies
28
+
29
+ - The question bank `src/quiz.json` ([schema](../runtime/quiz/quiz.v1.schema.json)) and, for the figures of its
30
+ questions, the image files in `src/images/` (`<name>.svg`, `.png`, `.jpg` or `.webp`, referred to as
31
+ `images/<name>.…`). No code: the runtime `@lernapps/app-templates` does the rest.
@@ -0,0 +1,5 @@
1
+ node_modules/
2
+ dist/
3
+ _site/
4
+ test-results/
5
+ playwright-report/
@@ -0,0 +1,283 @@
1
+ # Building Blocks
2
+
3
+ The quiz's extension of the generic architecture (`docs/arc42/` at the root of `lernapps/app-templates`): a quiz
4
+ about things to know, whose build step, rendering, validation, engine and tests the runtime `runtime/quiz/` ships, and
5
+ whose creator writes only the question bank `src/quiz.json` (`quiz-only-data`) and keeps `src/main.ts` as generated.
6
+ The quiz has no components, no tutor handoff, no task numbers and no exercise contract; its question types are the shared
7
+ runtime's (`bb-questions`), which the explainer builds on alike, and what a question shows besides its text (`material`: figures, tables, quotations, code, ...) is the shared runtime's content blocks (`bb-blocks`). The creator's assistant follows the skill `lernapps-quiz` (`if-skills`). A quiz app writes no
8
+ architecture of its own: the bank's schema fixes its structure.
9
+
10
+ ## Level 1 (quiz)
11
+
12
+ ```arc42
13
+ :::diagram
14
+ id: building-blocks-quiz-level-1
15
+ view: building-block
16
+ notation: mermaid
17
+ :::
18
+ ```
19
+
20
+ ```mermaid
21
+ flowchart TB
22
+ subgraph bb-runtime["Shared runtime"]
23
+ bb-blocks["Content blocks"]
24
+ bb-questions["Questions"]
25
+ end
26
+ bb-tooling["Tooling helpers"]
27
+ bb-archetype-runtime["Quiz runtime"]
28
+ bb-quiz-bank["Question bank"]
29
+ bb-archetype-runtime -->|"if-shared-runtime"| bb-runtime
30
+ bb-archetype-runtime -->|"if-questions"| bb-questions
31
+ bb-archetype-runtime -->|"if-blocks"| bb-blocks
32
+ bb-archetype-runtime -->|"if-preset"| bb-tooling
33
+ ```
34
+
35
+ ## Level 2: the quiz runtime
36
+
37
+ ```arc42
38
+ :::diagram
39
+ id: building-blocks-quiz-runtime
40
+ view: building-block
41
+ notation: mermaid
42
+ :::
43
+ ```
44
+
45
+ ```mermaid
46
+ flowchart TB
47
+ subgraph bb-archetype-runtime["Quiz runtime"]
48
+ bb-build["Build step"]
49
+ bb-validation["Bank validation"]
50
+ bb-render["Quiz rendering"]
51
+ bb-shell["Quiz engine"]
52
+ bb-e2e["End-to-end tests"]
53
+ bb-runtime-texts["Runtime texts"]
54
+ end
55
+ bb-quiz-bank["Question bank"]
56
+ bb-tooling["Tooling helpers"]
57
+ bb-build -->|"if-archetype-content"| bb-quiz-bank
58
+ bb-validation -->|"if-archetype-content"| bb-quiz-bank
59
+ bb-render -->|"if-archetype-content"| bb-quiz-bank
60
+ bb-render -->|"if-runtime-texts"| bb-runtime-texts
61
+ bb-render -->|"if-translator"| bb-tooling
62
+ bb-shell -->|"if-runtime-texts"| bb-runtime-texts
63
+ bb-shell -->|"if-device-storage"| bb-tooling
64
+ bb-shell -->|"if-a11y"| bb-tooling
65
+ bb-shell -->|"if-translator"| bb-tooling
66
+ bb-e2e -->|"if-archetype-content"| bb-quiz-bank
67
+ bb-e2e -->|"if-runtime-texts"| bb-runtime-texts
68
+ ```
69
+
70
+ ## Quiz runtime
71
+
72
+ Built. The runtime of every quiz, which the app does not change: it renders the bank into the page, validates it,
73
+ turns the page into a quiz in the browser and brings the end-to-end tests.
74
+
75
+ ```arc42
76
+ :::building-block
77
+ id: bb-archetype-runtime
78
+ title: Quiz runtime
79
+ path: runtime/quiz
80
+ technology: TypeScript, Vite plugin, DOM
81
+ requires: if-shared-runtime, if-preset, if-questions, if-blocks
82
+ implements: concept-archetype-extension
83
+ :::
84
+ ```
85
+
86
+ ### Build step
87
+
88
+ Built. The plugin `quiz()` reads and validates the bank and writes the quiz page in every language and the 404 page;
89
+ `vp dev` serves the same pages.
90
+
91
+ ```arc42
92
+ :::building-block
93
+ id: bb-build
94
+ title: Build step
95
+ parent: bb-archetype-runtime
96
+ path: runtime/quiz/plugin.ts
97
+ technology: Vite plugin
98
+ requires: if-archetype-content
99
+ :::
100
+ ```
101
+
102
+ #### Build plugin interface
103
+
104
+ The app's vite.config.ts adds `quiz()` to the tooling preset.
105
+
106
+ ```arc42
107
+ :::interface
108
+ id: if-build-plugin
109
+ title: quiz() Vite plugin
110
+ provider: bb-build
111
+ protocol: TypeScript import, @lernapps/app-templates/quiz/plugin
112
+ path: runtime/quiz/plugin.ts
113
+ :::
114
+ ```
115
+
116
+ ### Bank validation
117
+
118
+ Built. Validates the bank against its schema, then what a schema cannot say (one correct option in a single choice,
119
+ unique ids, complete languages, the examples through the checker), one line per problem naming the question.
120
+
121
+ ```arc42
122
+ :::building-block
123
+ id: bb-validation
124
+ title: Bank validation
125
+ parent: bb-archetype-runtime
126
+ path: runtime/quiz/validate.ts
127
+ technology: Ajv, JSON Schema
128
+ requires: if-archetype-content
129
+ :::
130
+ ```
131
+
132
+ ### Quiz rendering
133
+
134
+ Built. Renders every question into the page with its controls, the hidden background, explanation and further
135
+ reading, the solutions and the sources, a page per language. Without JavaScript the page reads as a worksheet with its
136
+ answer key; the quiz's own tests check it, not `lernapps check`.
137
+
138
+ ```arc42
139
+ :::building-block
140
+ id: bb-render
141
+ title: Quiz rendering
142
+ parent: bb-archetype-runtime
143
+ path: runtime/quiz/render.ts
144
+ technology: TypeScript, HTML
145
+ requires: if-archetype-content, if-runtime-texts, if-translator
146
+ implements: concept-readable-without-js
147
+ :::
148
+ ```
149
+
150
+ #### Pages interface
151
+
152
+ Learners, teachers and parents read the quiz at `lernapps.net/<repo>/` (and `/<language>/`), with `?seed=<n>` and the
153
+ deep link `#frage-<id>`; the catalog entry links there.
154
+
155
+ ```arc42
156
+ :::interface
157
+ id: if-pages
158
+ title: Quiz page at lernapps.net/<repo>/
159
+ provider: bb-render
160
+ protocol: HTML pages over HTTPS
161
+ path: runtime/quiz/render.ts
162
+ :::
163
+ ```
164
+
165
+ ### Quiz engine
166
+
167
+ Built. Turns the rendered page into a quiz: one question at a time in the order of the seed in the address, each
168
+ answer checked with the question types' checker, the feedback after each answer, the score and the solutions at the
169
+ end. It stores nothing but the last result, and only when the bank asks for it (`rememberLastResult`).
170
+
171
+ ```arc42
172
+ :::building-block
173
+ id: bb-shell
174
+ title: Quiz engine
175
+ parent: bb-archetype-runtime
176
+ path: runtime/quiz/engine.ts
177
+ technology: TypeScript, DOM
178
+ requires: if-runtime-texts, if-device-storage, if-a11y, if-translator
179
+ implements: concept-determinism, concept-accessibility
180
+ :::
181
+ ```
182
+
183
+ #### Start interface
184
+
185
+ The app's `src/main.ts` imports the quiz's style and calls `startQuiz()`.
186
+
187
+ ```arc42
188
+ :::interface
189
+ id: if-start
190
+ title: startQuiz()
191
+ provider: bb-shell
192
+ protocol: TypeScript import, @lernapps/app-templates/quiz
193
+ path: runtime/quiz/engine.ts
194
+ :::
195
+ ```
196
+
197
+ ### End-to-end tests
198
+
199
+ Built. `quizTests()` checks every question of the bank in the browser (deep link, right and wrong answer, feedback in
200
+ view with the focus), the full score, the page without JavaScript, and each further language.
201
+
202
+ ```arc42
203
+ :::building-block
204
+ id: bb-e2e
205
+ title: End-to-end tests
206
+ parent: bb-archetype-runtime
207
+ path: runtime/quiz/e2e.ts
208
+ technology: Playwright
209
+ requires: if-archetype-content, if-runtime-texts
210
+ :::
211
+ ```
212
+
213
+ #### Tests interface
214
+
215
+ The app's `e2e/quiz.e2e.ts` only calls `quizTests()`.
216
+
217
+ ```arc42
218
+ :::interface
219
+ id: if-e2e-tests
220
+ title: quizTests()
221
+ provider: bb-e2e
222
+ protocol: TypeScript import, @lernapps/app-templates/quiz/e2e
223
+ path: runtime/quiz/e2e.ts
224
+ :::
225
+ ```
226
+
227
+ ### Runtime texts
228
+
229
+ Built. The quiz's own learner texts in German and English; a bank may declare only these languages.
230
+
231
+ ```arc42
232
+ :::building-block
233
+ id: bb-runtime-texts
234
+ title: Runtime texts
235
+ parent: bb-archetype-runtime
236
+ path: runtime/quiz/messages
237
+ technology: JSON per language
238
+ implements: concept-languages
239
+ :::
240
+ ```
241
+
242
+ #### Runtime texts interface
243
+
244
+ The rendering, the engine and the tests take the quiz's texts by language.
245
+
246
+ ```arc42
247
+ :::interface
248
+ id: if-runtime-texts
249
+ title: Quiz texts by language
250
+ provider: bb-runtime-texts
251
+ protocol: JSON module import
252
+ path: runtime/quiz/messages
253
+ :::
254
+ ```
255
+
256
+ ## Question bank
257
+
258
+ Built in the template, written by the creator: title, intro, languages, sources, `rememberLastResult` and the
259
+ questions; the only file of a quiz the creator changes.
260
+
261
+ ```arc42
262
+ :::building-block
263
+ id: bb-quiz-bank
264
+ title: Question bank
265
+ technology: JSON
266
+ implements: concept-languages
267
+ path: quiz/src/quiz.json
268
+ :::
269
+ ```
270
+
271
+ ### Question bank interface
272
+
273
+ The quiz's content: rendering, validation, build and tests read the bank only through its schema.
274
+
275
+ ```arc42
276
+ :::interface
277
+ id: if-archetype-content
278
+ title: src/quiz.json (quiz.v1 schema)
279
+ provider: bb-quiz-bank
280
+ protocol: JSON, JSON Schema
281
+ path: runtime/quiz/quiz.v1.schema.json
282
+ :::
283
+ ```
@@ -0,0 +1,21 @@
1
+ # Runtime View
2
+
3
+ The quiz's own scenario, besides the generic ones.
4
+
5
+ ## Answering a question
6
+
7
+ The learner opens the quiz, possibly with `?seed=<n>` or `#frage-<id>`. Without JavaScript the page is a worksheet:
8
+ every question, then the solutions with the same background and links. With JavaScript `startQuiz()` turns it into a
9
+ quiz: the questions in the order of the seed (the address gets one when it has none), one at a time. Before the first question the learner chooses how many to answer (`?n=<n>` in the address, all by default; a link with `n` or to a question skips the choice), the first of them in the order of the seed; an answer is
10
+ checked by the question types' checker, and right or wrong, the background of every option, the explanation and the
11
+ further reading show, the feedback in view with the focus and announced. At the end come the score and the solutions;
12
+ when the bank asks for it, the last result is kept on the device.
13
+
14
+ ```arc42
15
+ :::runtime-scenario
16
+ id: scenario-quiz-answer
17
+ title: Answering a question of the quiz
18
+ trigger: The learner opens the quiz or answers a question
19
+ involves: bb-archetype-runtime, bb-render, bb-shell, bb-questions, bb-blocks, bb-quiz-bank, bb-runtime-texts, bb-tooling
20
+ :::
21
+ ```
@@ -0,0 +1,33 @@
1
+ # Deployment View
2
+
3
+ Where the quiz's blocks run, below the generic nodes.
4
+
5
+ ## Quiz build
6
+
7
+ The quiz's build, validation and end-to-end tests run in CI and, through the same hooks, on the creator's machine;
8
+ the bank is built into the page and the bundle there.
9
+
10
+ ```arc42
11
+ :::deployment-node
12
+ id: dn-quiz-build
13
+ title: Quiz build
14
+ type: container
15
+ parent: dn-ci-runner
16
+ hosts: bb-quiz-bank
17
+ :::
18
+ ```
19
+
20
+ ## Quiz page
21
+
22
+ The quiz engine with the question types' checker and the quiz's texts runs in the learner's browser on the page the
23
+ build rendered.
24
+
25
+ ```arc42
26
+ :::deployment-node
27
+ id: dn-quiz-page
28
+ title: Quiz page
29
+ type: container
30
+ parent: dn-learner-browser
31
+ hosts: bb-shell, bb-runtime-texts
32
+ :::
33
+ ```
@@ -0,0 +1,36 @@
1
+ # Architecture Decisions
2
+
3
+ The quiz's decisions, besides the generic ones.
4
+
5
+ ## The Creator Writes Only the Question Bank
6
+
7
+ The quiz is a deep scaffold: engine, six question types, feedback, scoring, order, accessibility and the page
8
+ without JavaScript come from the runtime, and the creator writes only `src/quiz.json`, no code. What the bank cannot
9
+ say goes into the retrospective instead of code around the runtime. So the schema fixes the quiz's structure, and a
10
+ quiz app writes no architecture of its own. Rejected: quiz-specific code in the app.
11
+
12
+ ```arc42
13
+ :::decision
14
+ id: dec-quiz-only-bank
15
+ title: A quiz is only its question bank
16
+ status: accepted
17
+ date: 2026-10-16
18
+ addresses: qg-checkable, qg-understandable, con-runtime-unchanged
19
+ :::
20
+ ```
21
+
22
+ ## A Worksheet Without JavaScript
23
+
24
+ The build renders every question with its solution into the page, so that without JavaScript the quiz reads as a
25
+ worksheet with its answer key and the engine only adds the one-question-at-a-time quiz. Rejected: a page that needs
26
+ JavaScript to show its questions.
27
+
28
+ ```arc42
29
+ :::decision
30
+ id: dec-quiz-worksheet
31
+ title: The quiz page is a worksheet without JavaScript
32
+ status: accepted
33
+ date: 2026-10-16
34
+ addresses: qg-quiz-readable-without-js, qg-accessibility
35
+ :::
36
+ ```
@@ -0,0 +1,53 @@
1
+ # Quality Requirements
2
+
3
+ The quiz's goal and scenarios, besides the generic ones.
4
+
5
+ ## Readable without JavaScript (quiz)
6
+
7
+ A quiz is text-heavy, so its questions, solutions, background and links read without JavaScript, as far as a quiz
8
+ can: as a worksheet with its answer key, not as a quiz answered one question at a time. Realised by the quiz
9
+ rendering and checked by the quiz's end-to-end tests (`dec-quiz-worksheet`).
10
+
11
+ High priority, because the archetype is text-heavy (owner, 2026-10-16).
12
+
13
+ ```arc42
14
+ :::ignore W014 the extension's goal follows the generic goals in the combined chapter; the generic part cannot hold it
15
+ :::
16
+ :::ignore H010 the generic solution strategy cannot name an archetype's goal; the quiz's rendering realises it, see the decisions that address it
17
+ :::
18
+ :::quality-goal
19
+ id: qg-quiz-readable-without-js
20
+ title: Readable without JavaScript (quiz)
21
+ priority: high
22
+ :::
23
+ ```
24
+
25
+ ## Every question readable without JavaScript
26
+
27
+ `quizTests()` opens the page with JavaScript off, in every language of the bank.
28
+
29
+ ```arc42
30
+ :::quality-scenario
31
+ id: qs-quiz-without-js
32
+ title: Every question and its solution read without JavaScript
33
+ quality: qg-quiz-readable-without-js
34
+ stimulus: The quiz's end-to-end tests open the built quiz with JavaScript off
35
+ response: Every question and its solution, with the same background and links, are visible; in each further language too
36
+ metric: All questions of the bank and their solutions visible, in every declared language
37
+ :::
38
+ ```
39
+
40
+ ## A broken bank fails the build
41
+
42
+ The bank validation runs before the page is written.
43
+
44
+ ```arc42
45
+ :::quality-scenario
46
+ id: qs-quiz-bank-valid
47
+ title: A broken question bank fails the build
48
+ quality: qg-checkable
49
+ stimulus: The bank has two correct options in a single choice, a duplicate id or a missing translation
50
+ response: The build fails with one line per problem, naming the question by its position and id
51
+ metric: 0 pages written from an invalid bank
52
+ :::
53
+ ```
@@ -0,0 +1,19 @@
1
+ # Risks and Technical Debt
2
+
3
+ The quiz's risks, besides the generic ones.
4
+
5
+ ## Readability Without JavaScript Checked Only by Its Own Tests
6
+
7
+ `lernapps check` checks pages without JavaScript only for the explainer (`explainer-readable-without-js`); the quiz's
8
+ worksheet is checked by the quiz's end-to-end tests alone, so a deployed quiz is not checked for it again.
9
+
10
+ ```arc42
11
+ :::ignore H007 accepted without a decision of its own: the quiz's own end-to-end tests check the worksheet before every push and in CI
12
+ :::
13
+ :::risk
14
+ id: risk-quiz-no-js-not-in-check
15
+ title: The quiz's page without JavaScript is not checked by lernapps check
16
+ severity: low
17
+ mitigation: Accepted for now; the quiz's end-to-end tests run before every push and in CI.
18
+ :::
19
+ ```
@@ -0,0 +1,27 @@
1
+ # Glossary
2
+
3
+ The quiz's terms, besides the generic ones.
4
+
5
+ ## Question Bank
6
+
7
+ `src/quiz.json`, checked against `quiz.v1.schema.json`.
8
+
9
+ ```arc42
10
+ :::glossary-term
11
+ id: term-question-bank
12
+ title: Question bank
13
+ definition: The quiz's title, intro, languages, sources and questions, the only file a quiz's creator writes.
14
+ :::
15
+ ```
16
+
17
+ ## Worksheet
18
+
19
+ What the quiz page shows without JavaScript.
20
+
21
+ ```arc42
22
+ :::glossary-term
23
+ id: term-worksheet
24
+ title: Worksheet
25
+ definition: The quiz page without JavaScript, all questions followed by their solutions with background and links.
26
+ :::
27
+ ```
@@ -0,0 +1,3 @@
1
+ import { quizTests } from "@lernapps/app-templates/quiz/e2e";
2
+
3
+ quizTests();
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="de">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <script type="module" src="/src/main.ts"></script>
7
+ </head>
8
+ <body>
9
+ <!-- quiz -->
10
+ </body>
11
+ </html>