@lernapps/app-templates 0.0.1 → 0.1.1

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 (232) 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-Dy359O1O.mjs +1696 -0
  5. package/dist/block-BK_ohsH1.mjs +82 -0
  6. package/dist/blocks-CxtCPAa5.mjs +149 -0
  7. package/dist/blocks.mjs +4 -0
  8. package/dist/check-CteIFN96.mjs +254 -0
  9. package/dist/content-DO6oEJxj.mjs +140 -0
  10. package/dist/contract-PONpxJtd.mjs +52 -0
  11. package/dist/e2e-CU0n_unV.mjs +89 -0
  12. package/dist/engine-CArxqizW.mjs +136 -0
  13. package/dist/explainer-e2e.mjs +1311 -0
  14. package/dist/explainer-islands.mjs +197 -0
  15. package/dist/explainer-plugin.mjs +2132 -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-RosvaPZf.mjs +16976 -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-DnW-xtCh.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-D5kwkNt1.mjs +507 -0
  33. package/dist/render-DqHOJyHK.mjs +146 -0
  34. package/dist/render-GS1Htlu8.mjs +545 -0
  35. package/dist/result-D_mmCVwN.mjs +180 -0
  36. package/dist/tasks-DADUYy52.mjs +74 -0
  37. package/dist/validate-BDwL7Su3.mjs +1076 -0
  38. package/dist/validate-Bxy9NfB8.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 +143 -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 +448 -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 +1488 -0
  142. package/runtime/explainer/exercises.ts +326 -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 +306 -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 +433 -0
  221. package/runtime/shared/questions/question.v1.schema.json +346 -0
  222. package/runtime/shared/questions/questions.css +192 -0
  223. package/runtime/shared/questions/render.ts +255 -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/speech.ts +39 -0
  230. package/runtime/shared/text/text.v1.schema.json +34 -0
  231. package/runtime/shared/vue-code.ts +395 -0
  232. package/runtime/shared/vue.ts +38 -0
@@ -0,0 +1,246 @@
1
+ # Architecture Decisions
2
+
3
+ <!--
4
+ Arc42 chapter 9. Document the significant architecture decisions as Architecture Decision
5
+ Records (ADRs). Capture any choice that was expensive, risky, or that future maintainers
6
+ will wonder about.
7
+
8
+ Avoid redundancy with section 4 (solution strategy) — refer to it for the highest-level
9
+ choices and use this chapter for detail and rationale.
10
+
11
+ For each decision, write a ## section with a prose paragraph explaining the context,
12
+ the alternatives considered, and the rationale for the chosen option, followed by a DSL block.
13
+ Document rejected alternatives so future readers understand what was considered.
14
+
15
+ Status values:
16
+ proposed — under discussion, not yet in force
17
+ accepted — in force
18
+ deprecated — no longer recommended but not yet replaced
19
+ superseded — replaced by another decision
20
+
21
+ When a new decision replaces an old one, set status: superseded on the old decision
22
+ and add supersedes: <old-id> on the new decision.
23
+
24
+ The `date` field should be ISO 8601 (YYYY-MM-DD).
25
+ The `addresses` field links to quality goals and constraints this decision responds to.
26
+
27
+ See https://docs.arc42.org/section-9/ for further guidance.
28
+
29
+ Example:
30
+
31
+ ## Stateless Token Authentication
32
+
33
+ The team evaluated session-based (server-side store) and token-based (stateless) authentication.
34
+ Stateless tokens were chosen to avoid a shared session store that would introduce a single point
35
+ of failure and complicate horizontal scaling.
36
+
37
+ ```arc42
38
+ :::decision
39
+ id: dec-auth-stateless
40
+ title: Stateless Token Authentication
41
+ status: accepted
42
+ date: 2025-07-01
43
+ addresses: qg-security, qg-performance
44
+ :::
45
+ ```
46
+
47
+ To supersede a decision, mark the old one and point to it from the new one:
48
+
49
+ ```arc42
50
+ :::decision
51
+ id: dec-auth-old
52
+ title: Session-based Authentication
53
+ status: superseded
54
+ date: 2024-01-15
55
+ :::
56
+ ```
57
+
58
+ ```arc42
59
+ :::decision
60
+ id: dec-auth-new
61
+ title: OAuth2 Token Authentication
62
+ status: accepted
63
+ date: 2025-09-01
64
+ supersedes: dec-auth-old
65
+ :::
66
+ ```
67
+ -->
68
+
69
+ The decisions every lernapps app shares. Owner decisions are accepted with their date; decisions the runtime made
70
+ when it was built are accepted because they are in force. Each extension adds its archetype's decisions, and an
71
+ interactive app adds its own below these.
72
+
73
+ ## Generic Architecture with One Extension per Archetype
74
+
75
+ Quiz, explainer and interactive app stay separate archetypes, but they share their quality goals, so they follow one
76
+ architecture: this generic part with the frame and an abstract archetype part, and one extension per archetype in its
77
+ template folder that adds only its own blocks and decisions and references the generic ids. An app's architecture is
78
+ both together. Rejected: one architecture per archetype, which would repeat the frame three times; one architecture
79
+ with every archetype's detail in it, which no app could take as its own.
80
+
81
+ ```arc42
82
+ :::decision
83
+ id: dec-generic-plus-extensions
84
+ title: A generic architecture plus one extension per archetype
85
+ status: accepted
86
+ date: 2026-10-16
87
+ addresses: qg-understandable, con-architecture-current
88
+ :::
89
+ ```
90
+
91
+ ## What Archetypes Share Lives in the Shared Runtime
92
+
93
+ Quiz, explainer and interactive app use some things alike, the questions first of all: the quiz asks them, the
94
+ explainer's exercises are the same six types; the explainer and the interactive archetype read YAML content, check
95
+ texts and formulas and check the code of Vue components alike. Such a thing lives in `runtime/shared` (the questions in
96
+ `runtime/shared/questions`), and the archetypes build on it: no archetype imports another, and the shared runtime
97
+ imports none. The public paths of the package (`quiz/question`, `quiz/e2e`, ...) stay as thin re-exports, so that an
98
+ app generated from a template keeps building when a module moves. A test (`test/architecture.test.ts`) fails on an
99
+ import against this direction and on a public path without a file or a build entry. Rejected: the explainer importing
100
+ the quiz and the quiz the explainer's figures, which makes two archetypes one; copying the questions into each.
101
+
102
+ ```arc42
103
+ :::decision
104
+ id: dec-shared-runtime-direction
105
+ title: Archetypes build on the shared runtime and never on each other
106
+ status: accepted
107
+ date: 2026-10-20
108
+ addresses: qg-understandable, con-runtime-unchanged
109
+ :::
110
+ ```
111
+
112
+ ## Vue Is Fixed for Components
113
+
114
+ Where an app has components of its own (an explainer's components, an interactive app's UI), they are Vue with
115
+ TypeScript, so that one set of component rules, their build checks on the SFC compiler's output, the lint rules and
116
+ `vue-tsc` hold for every app, with no rules per framework; what a component draws and how stays free. Rejected: a free
117
+ choice of framework.
118
+
119
+ ```arc42
120
+ :::decision
121
+ id: dec-vue-fixed
122
+ title: Vue with TypeScript is fixed for an app's components
123
+ status: accepted
124
+ date: 2026-10-16
125
+ addresses: con-vue-typescript, con-component-rules, qg-checkable
126
+ :::
127
+ ```
128
+
129
+ ## Small Storage with a Quota
130
+
131
+ All apps share the origin's 5 MiB of `localStorage`. The only storage is the tooling's `localStorage` wrapper under the
132
+ app's prefix with a quota of 100 kB per app, and `save` refuses beyond it; the shared origin is accepted as a risk. The
133
+ quota is decided, not built. A second storage (IndexedDB) is left out.
134
+
135
+ ```arc42
136
+ :::decision
137
+ id: dec-small-storage
138
+ title: localStorage through the wrapper with a 100 kB quota
139
+ status: accepted
140
+ date: 2026-10-16
141
+ addresses: con-state-on-device, con-storage-quota, con-frontend-only, qg-privacy, risk-shared-origin-storage, risk-storage-quota-not-built
142
+ :::
143
+ ```
144
+
145
+ ## No Size Limit, the Size in the Entry
146
+
147
+ The app's size is not limited by the frame; it is stated in the app's catalog entry (its fact sheet), and a page may
148
+ show an optional loading indicator while it loads (not built). An archetype may still fix the size of its own parts,
149
+ as the explainer does for each component. Rejected: a size budget for every app, which would keep large interactive
150
+ apps out.
151
+
152
+ ```arc42
153
+ :::decision
154
+ id: dec-no-size-limit
155
+ title: No size limit; the size in the entry, an optional loading indicator
156
+ status: accepted
157
+ date: 2026-10-16
158
+ addresses: qg-accessibility
159
+ :::
160
+ ```
161
+
162
+ ## Accessibility by Default, Limits Declared
163
+
164
+ WCAG 2.1 AA and 360 px are platform rules; an app follows them by default and may deviate where its idea needs it (a
165
+ game against the clock), saying in its entry what it does not offer; then `accessible` and `usable-at-360px`
166
+ become warnings for it. Pages the runtime renders from the creator's data meet both in any case. Low stimulation is
167
+ advice in a skill, not a check. Rejected: the rules as errors for every app, which would exclude real-time games.
168
+
169
+ ```arc42
170
+ :::decision
171
+ id: dec-accessibility-default
172
+ title: Accessibility as default with declared limits
173
+ status: accepted
174
+ date: 2026-10-16
175
+ addresses: con-accessibility-default, qg-accessibility, risk-accessibility-limits-not-built
176
+ :::
177
+ ```
178
+
179
+ ## No Settings Now
180
+
181
+ A settings dialog (time limit off, less motion, sound, pause) is not in scope now; an app that needs one later adds it
182
+ to the frame rather than on its own.
183
+
184
+ ```arc42
185
+ :::ignore H001 a scoping decision of the owner (2026-10-16): it leaves something out and serves no quality goal of its own
186
+ :::
187
+ :::decision
188
+ id: dec-no-settings
189
+ title: No settings dialog for now
190
+ status: accepted
191
+ date: 2026-10-16
192
+ :::
193
+ ```
194
+
195
+ ## arc42 in the App, Only for Interactive Apps
196
+
197
+ Every app gets the generic architecture and its archetype's extension. Only an interactive app, whose code is free,
198
+ writes an architecture part of its own, below its extension's blocks, English and minimal; a quiz or explainer app
199
+ writes none, because its archetype's notation (the question bank, the content schema) fixes its structure. Checked
200
+ is only what arc42 checks itself (`arc42 diff --staged --strict` before a commit, `arc42 validate` in
201
+ `lernapps check`); whether the code keeps to the responsibilities is not checked. Rejected: framework-specific
202
+ conformance checks. Both checks are not wired into an app yet; `lernapps/app-templates` validates each combination of
203
+ the generic part and one extension strictly in its pre-commit hook and in CI (`scripts/arc42.ts`).
204
+
205
+ ```arc42
206
+ :::decision
207
+ id: dec-arc42-in-app
208
+ title: arc42 in the app; only interactive apps add their own part
209
+ status: accepted
210
+ date: 2026-10-16
211
+ addresses: con-architecture-current, con-language, qg-understandable, risk-arc42-checks-not-wired
212
+ :::
213
+ ```
214
+
215
+ ## The Skill as the Interface to the Creator's Assistant
216
+
217
+ The guidance for the creator's assistant is a skill per archetype plus `lernapps-app` for every app: Markdown the
218
+ assistant loads and follows, modelled as the interface `if-skills` of the skills block `bb-skills`. Advice that no check can make (how to write
219
+ a good question, low stimulation) lives there, not in the runtime.
220
+
221
+ ```arc42
222
+ :::decision
223
+ id: dec-skill-interface
224
+ title: Skills as the interface used by the creator's assistant
225
+ status: accepted
226
+ date: 2026-10-16
227
+ addresses: qg-understandable
228
+ :::
229
+ ```
230
+
231
+ ## Tutor Variant
232
+
233
+ The optional tutor is a handoff to the learner's own assistant: after a click, a prompt (copied or passed to a chosen
234
+ provider) and a static tutor page per content page give it the task on the learner's screen. Rejected: a model
235
+ running in the browser. Built for the explainer (its extension models it); not built for the quiz and interactive
236
+ apps.
237
+
238
+ ```arc42
239
+ :::decision
240
+ id: dec-tutor-variant
241
+ title: Tutor as a handoff to the learner's own assistant
242
+ status: accepted
243
+ date: 2026-10-16
244
+ addresses: risk-tutor-not-built, con-no-request-before-click, qg-privacy
245
+ :::
246
+ ```
@@ -0,0 +1,155 @@
1
+ # Quality Requirements
2
+
3
+ The four quality goals every lernapps app shares, in the order of chapter 1, each made testable by scenarios. The
4
+ set and the priorities are the owner's (2026-10-16). Each extension adds its archetype's scenarios; the quiz and the
5
+ explainer add readability without JavaScript as a goal of their own. Scenarios marked "not built yet" describe a
6
+ decided check that does not exist today.
7
+
8
+ ## 10.1 Quality Goals
9
+
10
+ ## Privacy
11
+
12
+ The app sends nothing anywhere and requests nothing from another server before a click; what it remembers stays on the
13
+ learner's device. The privacy notice of lernapps.net promises this for every app.
14
+
15
+ ```arc42
16
+ :::quality-goal
17
+ id: qg-privacy
18
+ title: Privacy
19
+ priority: high
20
+ :::
21
+ ```
22
+
23
+ ## Checkable
24
+
25
+ The rules an app keeps are verified by machine, at build and in the browser, so that an assistant can change content
26
+ or code and still learn at once when it breaks the frame.
27
+
28
+ ```arc42
29
+ :::quality-goal
30
+ id: qg-checkable
31
+ title: Checkable by machine
32
+ priority: high
33
+ :::
34
+ ```
35
+
36
+ ## Accessibility
37
+
38
+ A default with declared limits: the pages meet WCAG 2.1 AA and work at 360 px, and an app that cannot declares its
39
+ limits in its entry.
40
+
41
+ ```arc42
42
+ :::quality-goal
43
+ id: qg-accessibility
44
+ title: Accessibility by default
45
+ priority: medium
46
+ :::
47
+ ```
48
+
49
+ ## Understandable
50
+
51
+ A reviewer or the creator's agent understands an app's structure from its architecture, the generic part plus its
52
+ archetype's extension, written in English and minimal and kept current with the code.
53
+
54
+ ```arc42
55
+ :::quality-goal
56
+ id: qg-understandable
57
+ title: Understandable from its architecture
58
+ priority: medium
59
+ :::
60
+ ```
61
+
62
+ ## 10.2 Quality Scenarios
63
+
64
+ ## No request before a click
65
+
66
+ `lernapps check` visits every page of the built app, blocks and records requests to other hosts while it loads.
67
+
68
+ ```arc42
69
+ :::quality-scenario
70
+ id: qs-no-request-before-click
71
+ title: No request to another host before a click
72
+ quality: qg-privacy
73
+ stimulus: lernapps check loads every page of the built app without clicking
74
+ response: Requests to other hosts are recorded; each one is an error of no-request-before-click
75
+ metric: 0 requests to another origin on every page before a click
76
+ :::
77
+ ```
78
+
79
+ ## State stays on the device
80
+
81
+ An app's code that uses the browser's storage directly, sets a cookie or calls a network API is reported by the lint
82
+ rules on commit and by the component rules at build.
83
+
84
+ ```arc42
85
+ :::quality-scenario
86
+ id: qs-state-on-device
87
+ title: Remembered state stays on the device
88
+ quality: qg-privacy
89
+ stimulus: A component stores progress with localStorage directly or sends it with fetch
90
+ response: storage-through-wrapper or vue-component-no-network reports it; the build's component rules fail on the network call
91
+ metric: 0 findings; all storage goes through createStorage under the prefix lernapps:<app>:
92
+ :::
93
+ ```
94
+
95
+ ## Broken content fails the build
96
+
97
+ What the creator wrote is validated against the archetype's schema or contract before any page is written.
98
+
99
+ ```arc42
100
+ :::quality-scenario
101
+ id: qs-build-fails-per-line
102
+ title: A broken question bank, content or description fails the build
103
+ quality: qg-checkable
104
+ stimulus: The creator's assistant writes data that breaks the archetype's schema or a rule the schema cannot say
105
+ response: The build fails with one line per problem naming the file, the place and what to change
106
+ metric: 0 pages written from invalid data; every problem named in one line
107
+ :::
108
+ ```
109
+
110
+ ## No WCAG violation found by axe
111
+
112
+ `lernapps check` runs axe-core for WCAG 2.1 A and AA on each page it visits. For an app whose entry declares its limits
113
+ the finding should become a warning; that is not built yet, so it is an error for every app today.
114
+
115
+ ```arc42
116
+ :::quality-scenario
117
+ id: qs-axe-clean
118
+ title: axe finds no WCAG 2.1 A or AA violation
119
+ quality: qg-accessibility
120
+ stimulus: lernapps check visits the pages of the built app
121
+ response: Each axe violation is reported as an error of accessible, naming the page and element
122
+ metric: 0 axe violations of WCAG 2.1 A or AA on every page
123
+ :::
124
+ ```
125
+
126
+ ## Usable at 360 px
127
+
128
+ `lernapps check` measures each page in a 360 px wide window.
129
+
130
+ ```arc42
131
+ :::quality-scenario
132
+ id: qs-usable-at-360px
133
+ title: No page wider than 360 px
134
+ quality: qg-accessibility
135
+ stimulus: lernapps check opens every page of the built app in a 360 px wide window
136
+ response: A wider page is an error of usable-at-360px, naming the elements that are too wide
137
+ metric: Page width at most 360 px on every page
138
+ :::
139
+ ```
140
+
141
+ ## Code no block claims
142
+
143
+ Not built yet (decided sketch, step 12, section 4): before a commit, `arc42 diff --staged --strict` compares the staged
144
+ code with the architecture; it matters for interactive apps, whose code is free.
145
+
146
+ ```arc42
147
+ :::quality-scenario
148
+ id: qs-architecture-current
149
+ title: New code without a building block fails the commit
150
+ quality: qg-understandable
151
+ stimulus: An assistant stages new code under src/ that no building block claims, or a block changed without its prose
152
+ response: arc42 diff --staged --strict fails the commit and names the unclaimed path or the block
153
+ metric: 0 unclaimed paths under src/ at every commit, in about 0.2 s
154
+ :::
155
+ ```
@@ -0,0 +1,113 @@
1
+ # Risks and Technical Debt
2
+
3
+ <!--
4
+ Arc42 chapter 11. Document known risks and areas of technical debt ordered by priority.
5
+ Risk management is about making technical risks visible to the people who need to act on them.
6
+
7
+ A risk is a known threat whose severity has not yet been fully mitigated.
8
+ Technical debt is a shortcut taken consciously or accidentally whose cost will have to be
9
+ paid later. Both belong here.
10
+
11
+ For each risk or debt item, write a ## section with a prose paragraph describing the risk,
12
+ its cause, its potential impact, and the current situation, followed by a DSL block.
13
+
14
+ The `mitigation` field describes the planned or accepted response. Even "accepted without
15
+ action until X" is a valid mitigation — it shows the team made a conscious choice.
16
+
17
+ Order entries by priority — highest risk first.
18
+
19
+ See https://docs.arc42.org/section-11/ for further guidance.
20
+
21
+ Example:
22
+
23
+ ## No Automated Performance Regression Tests
24
+
25
+ The performance quality goal has no automated gate in CI. Performance regressions can be
26
+ introduced without detection until a production incident occurs.
27
+
28
+ ```arc42
29
+ :::risk
30
+ id: risk-no-perf-tests
31
+ title: No Automated Performance Regression Tests
32
+ severity: high
33
+ mitigation: Add k6 load test suite as a nightly CI job with a p95 threshold gate.
34
+ :::
35
+ ```
36
+ -->
37
+
38
+ Risks and debt of the frame every lernapps app shares, highest first. Each extension adds its archetype's, and an
39
+ interactive app its own.
40
+
41
+ ## Declared Accessibility Limits Not Built
42
+
43
+ An app may declare its limits in its entry and then get warnings instead of errors from `accessible` and
44
+ `usable-at-360px`; neither the entry field nor the warnings exist yet, so an app that deviates (a game against the
45
+ clock) fails `lernapps check` today.
46
+
47
+ ```arc42
48
+ :::risk
49
+ id: risk-accessibility-limits-not-built
50
+ title: Declared accessibility limits not built
51
+ severity: medium
52
+ mitigation: Planned in the sketch (tooling step 2, lernapps/apps step 3); until then an app keeps both rules or cannot be listed.
53
+ :::
54
+ ```
55
+
56
+ ## Storage Quota Not Built
57
+
58
+ The quota of 100 kB per app is decided, but the storage wrapper has no limit: `save` succeeds until the browser
59
+ refuses, so one app can fill the origin's shared 5 MiB.
60
+
61
+ ```arc42
62
+ :::risk
63
+ id: risk-storage-quota-not-built
64
+ title: Storage quota of 100 kB not built
65
+ severity: medium
66
+ mitigation: Build the quota into the tooling's storage wrapper, so that save refuses beyond 100 kB per app; until then apps keep only small values (the quiz's last result, the explainer's chosen way to the tutor).
67
+ :::
68
+ ```
69
+
70
+ ## Shared Origin Storage
71
+
72
+ Every app on lernapps.net shares one origin and so one `localStorage`. A learner who clears the site's data, or a
73
+ browser that evicts it, loses what every app remembered, and an app that picks another app's storage name reads and
74
+ overwrites its values.
75
+
76
+ ```arc42
77
+ :::risk
78
+ id: risk-shared-origin-storage
79
+ title: Storage shared by every app of the origin
80
+ severity: medium
81
+ mitigation: Accepted (owner): apps keep only small data that may be lost, under their own prefix, and keep working with nothing remembered; the quota limits what one app takes.
82
+ :::
83
+ ```
84
+
85
+ ## Tutor Not Built for Quiz and Interactive Apps
86
+
87
+ The tutor is decided as a handoff to the learner's own assistant (`dec-tutor-variant`), but it is built only for the
88
+ explainer, so a quiz or an interactive app has no tutor yet.
89
+
90
+ ```arc42
91
+ :::risk
92
+ id: risk-tutor-not-built
93
+ title: Tutor handoff not built for quiz and interactive apps
94
+ severity: medium
95
+ mitigation: Build the handoff with the exercise contract and task numbers from the explainer's parts; until then apps add no tutor of their own.
96
+ :::
97
+ ```
98
+
99
+ ## arc42 Checks Not Wired
100
+
101
+ The architecture is meant to be kept current by `arc42 diff --staged --strict` before a commit and `arc42 validate` in
102
+ `lernapps check`; neither is wired into an app yet, so architecture and code can drift unnoticed. In
103
+ `lernapps/app-templates` the generic part and its extensions are validated in the pre-commit hook and in CI.
104
+
105
+ ```arc42
106
+ :::risk
107
+ id: risk-arc42-checks-not-wired
108
+ title: arc42 checks not wired into the app
109
+ severity: medium
110
+ mitigation: Planned in the sketch (tooling step 2); until then the review reads the architecture against the code.
111
+ :::
112
+ ```
113
+
@@ -0,0 +1,162 @@
1
+ # Glossary
2
+
3
+ <!--
4
+ Arc42 chapter 12. Define the domain and technical terms used in the architecture documentation.
5
+ A shared glossary reduces misunderstanding by ensuring all stakeholders use the same language.
6
+ If you work in multi-language teams, it also serves as a translation reference.
7
+
8
+ For each term, write a ## section with a prose paragraph providing context, etymology, or
9
+ extended explanation where useful, followed by a DSL block with a concise definition.
10
+
11
+ Keep the `definition` field to one or two sentences that unambiguously identify the concept.
12
+ Extended explanation belongs in the prose above the block.
13
+
14
+ If a short form is important, include it in the prose; the typed glossary block has no
15
+ `abbreviation` field.
16
+
17
+ Note synonyms the team has agreed NOT to use, and why, in the prose paragraph.
18
+
19
+ See https://docs.arc42.org/section-12/ for further guidance.
20
+
21
+ Example:
22
+
23
+ ## Bounded Context
24
+
25
+ A bounded context is a logical boundary within which a domain model is consistent and
26
+ unambiguous. Inside a bounded context, terms have precise, agreed meanings. The same word
27
+ may mean something different in another bounded context.
28
+
29
+ ```arc42
30
+ :::glossary-term
31
+ id: term-bounded-context
32
+ title: Bounded Context
33
+ definition: A logical boundary within which a domain model, its language, and its rules are internally consistent. Defined in Domain-Driven Design (Evans, 2003).
34
+ :::
35
+ ```
36
+ -->
37
+
38
+ Terms with a meaning specific to lernapps apps of every archetype. Learner-facing text is German; these terms are the
39
+ English names used in code, schemas and this architecture. Each extension adds its archetype's terms.
40
+
41
+ ## Archetype
42
+
43
+ One of the kinds of app the generator can make, each a template folder of `lernapps/app-templates` with its runtime:
44
+ `quiz`, `explainer`, `interactive`.
45
+
46
+ ```arc42
47
+ :::glossary-term
48
+ id: term-archetype
49
+ title: Archetype
50
+ definition: A kind of lernapps app (quiz, explainer, interactive) with its template and its runtime, which fixes what the creator writes.
51
+ :::
52
+ ```
53
+
54
+ ## Extension
55
+
56
+ Lives in the template folder's `docs/arc42/`; it references the generic ids and defines none of them again.
57
+
58
+ ```arc42
59
+ :::glossary-term
60
+ id: term-extension
61
+ title: Extension
62
+ definition: The part of the architecture one archetype adds to the generic architecture, its blocks placed below the generic ones.
63
+ :::
64
+ ```
65
+
66
+ ## Runtime
67
+
68
+ The runtime of `@lernapps/app-templates`; together with the tooling helpers it forms the frame an app does not change.
69
+
70
+ ```arc42
71
+ :::glossary-term
72
+ id: term-runtime
73
+ title: Runtime
74
+ definition: The shared code of every app of an archetype that builds its pages, checks it at build time and runs it in the browser; the app never edits it.
75
+ :::
76
+ ```
77
+
78
+ ## Shell
79
+
80
+ Started by the archetype's start function in `src/main.ts`: `startQuiz`, `startExplainer` or `startInteractive`.
81
+
82
+ ```arc42
83
+ :::glossary-term
84
+ id: term-shell
85
+ title: Shell
86
+ definition: The runtime's code in the browser that turns the static pages into the live app.
87
+ :::
88
+ ```
89
+
90
+ ## Creator
91
+
92
+ The person who makes and lists an app on lernapps.net, usually working through an AI assistant.
93
+
94
+ ```arc42
95
+ :::glossary-term
96
+ id: term-creator
97
+ title: Creator
98
+ definition: The person who builds an app and lists it in the app overview.
99
+ :::
100
+ ```
101
+
102
+ ## Start Page
103
+
104
+ `index.html` of each language. Not to be confused with the home page of lernapps.net.
105
+
106
+ ```arc42
107
+ :::glossary-term
108
+ id: term-start-page
109
+ title: Start page
110
+ definition: The page at the app's address, rendered at build from what the creator wrote, from which every other page of the app is reached.
111
+ :::
112
+ ```
113
+
114
+ ## Seed
115
+
116
+ Taken from the address where the archetype uses one, else drawn at random.
117
+
118
+ ```arc42
119
+ :::glossary-term
120
+ id: term-seed
121
+ title: Seed
122
+ definition: A positive integer from which the app draws everything random, so that the same address gives the same order, task or states.
123
+ :::
124
+ ```
125
+
126
+ ## Entry
127
+
128
+ The only way an app connects to the platform: its entry links to it. Its topics may point to the app's deep links, an
129
+ app that deviates from the accessibility default says so there, and its fact sheet states the app's size (not built
130
+ yet).
131
+
132
+ ```arc42
133
+ :::glossary-term
134
+ id: term-entry
135
+ title: Entry
136
+ definition: The one YAML file per app in lernapps/apps entries/, checked against the entry schema, that lists the app in the app overview.
137
+ :::
138
+ ```
139
+
140
+ ## Catalog
141
+
142
+ Shown at lernapps.net/apps/; the owner decides whether an app is listed.
143
+
144
+ ```arc42
145
+ :::glossary-term
146
+ id: term-catalog
147
+ title: Catalog
148
+ definition: The apps the app overview of lernapps.net provides, one entry per app.
149
+ :::
150
+ ```
151
+
152
+ ## Tutor
153
+
154
+ Optional; built for the explainer only; no model runs in the browser (see `dec-tutor-variant`).
155
+
156
+ ```arc42
157
+ :::glossary-term
158
+ id: term-tutor
159
+ title: Tutor
160
+ definition: The learner's own AI assistant, to which the app hands the current task after a click, through a prompt and static tutor pages.
161
+ :::
162
+ ```