Rules
Each rule is one requirement on a learning app. It lives where it acts: as a section of a skill for AI assistants, as a check, as a lint rule or as an item of the review rubric. The same rule can live in several of them, always under the same id. This page reads them from there.
- Scope:
listingapplies to every app in the app overview, however it is built and wherever it is hosted;toolingto apps built with this tooling (theirpackage.jsonlists@lernapps/tooling), because the rule presupposes its plan workflow or its checks;archetype:…to apps of that archetype. - Severity:
errormust not be broken;warningonly with a reason recorded in place;hintis a recommendation. Atoolingrule never blocks a listing: in the listing validation and the review its findings are warnings at most, advice for the creator; in the app's repo its severity holds.
Every message of a check links to its rule here, by its id: https://lernapps.net/tooling/rules/#<id>.
| Rule | Scope | Severity |
|---|---|---|
accessible | listing | error |
app-checkable | listing | error |
correct-content-support | listing | hint |
dependency-licence | listing | error |
entry-fitness-matches | listing | error |
entry-from-schema | listing | error |
entry-links-resolve | listing | error |
free-of-charge | listing | error |
learner-text-german | listing | error |
learners-act | listing | error |
links-resolve | listing | error |
no-account | listing | error |
no-ads | listing | error |
no-learner-data-in-texts | listing | error |
no-request-before-click | listing | error |
no-tracking | listing | error |
own-data-only | listing | error |
pages-reachable | listing | error |
runs-in-browser | listing | error |
third-party-licence | listing | error |
usable-at-360px | listing | error |
app-content-guide | tooling | error, warning at listing |
app-content-matches | tooling | error, warning at listing |
checks-pass | tooling | error, warning at listing |
early-preview | tooling | hint |
explore-before-code | tooling | error, warning at listing |
few-turns-after-plan | tooling | hint |
fix-from-message | tooling | error, warning at listing |
lockfile-matches | tooling | error, warning at listing |
plan-file | tooling | error, warning at listing |
retrospective-filled | tooling | error, warning at listing |
stop-at-checkpoints | tooling | error, warning at listing |
suppression-reason | tooling | error, warning at listing |
explainer-content-valid | archetype:explainer | error |
explainer-figure-explains | archetype:explainer | hint |
explainer-figure-hides-answer | archetype:explainer | error |
explainer-formulas-static | archetype:explainer | error |
explainer-generated-sound | archetype:explainer | error |
explainer-languages | archetype:explainer | error |
explainer-mistakes-diagnosed | archetype:explainer | hint |
explainer-navigation | archetype:explainer | error |
explainer-only-content | archetype:explainer | error |
explainer-open-points | archetype:explainer | warning |
explainer-plausible-numbers | archetype:explainer | warning |
explainer-quote-sourced | archetype:explainer | warning |
explainer-readable-without-js | archetype:explainer | error |
explainer-scope-matches | archetype:explainer | warning |
explainer-stable-ids | archetype:explainer | warning |
explainer-structure-by-sections | archetype:explainer | error |
explainer-structure-complete | archetype:explainer | error |
explainer-structure-depth | archetype:explainer | error |
interactive-app-valid | archetype:interactive | error |
interactive-architecture-current | archetype:interactive | error |
interactive-core-contract | archetype:interactive | error |
interactive-playthroughs-pass | archetype:interactive | error |
keep-the-preset | archetype:explainer, archetype:interactive, archetype:quiz | error |
pages-from-gh-pages | archetype:explainer, archetype:interactive, archetype:quiz | error |
prefer-built-in-block | archetype:explainer | hint |
quiz-answers-checked | archetype:quiz | hint |
quiz-bank-valid | archetype:quiz, archetype:explainer | error |
quiz-clear-question | archetype:quiz, archetype:explainer | warning |
quiz-feedback-explains | archetype:quiz, archetype:explainer | hint |
quiz-fitting-type | archetype:quiz, archetype:explainer | hint |
quiz-further-reading | archetype:quiz | warning |
quiz-number-precision | archetype:quiz, archetype:explainer | warning |
quiz-only-data | archetype:quiz | error |
quiz-own-words | archetype:quiz | warning |
quiz-plausible-options | archetype:quiz, archetype:explainer | warning |
quiz-stable-ids | archetype:quiz | warning |
start-page-explains | archetype:interactive | hint |
storage-through-wrapper | archetype:explainer, archetype:interactive, archetype:quiz | error |
strict-typescript | archetype:explainer, archetype:interactive, archetype:quiz | error |
topic-has-exercises | archetype:explainer | error |
vue-component-browser-globals | archetype:explainer, archetype:interactive | error |
vue-component-exercise-contract | archetype:explainer | error |
vue-component-imports | archetype:explainer, archetype:interactive | error |
vue-component-no-html-injection | archetype:explainer, archetype:interactive | error |
vue-component-no-network | archetype:explainer, archetype:interactive | error |
vue-component-nojs | archetype:explainer | error |
vue-component-props-valid | archetype:explainer | error |
vue-component-size | archetype:explainer | error |
vue-component-tested | archetype:explainer | error |
vue-component-tutor-table | archetype:explainer | hint |
Accessible to WCAG 2.1 AA
accessible · listing · error
- WCAG 2.1 AA: labels, contrast, keyboard, text alternatives.
- Deviate only where the idea needs it (typing game against the clock); then say what is missing, in plain German, in the entry's
limits. - With
limits:lernapps check --entryreports warnings; without: errors.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/accessible.ts.
The published app can be opened and checked
app-checkable · listing · error
- Opens at the entry's
url; a built app from its bundle (index.html). - Page does not load, build fails, no browser, check stops → only this rule is reported. Fix, check again.
- Opens in a browser but the check fails → issue at https://github.com/lernapps/tooling/issues with the message.
Told in skills/tooling/lernapps-cli/references/platform-rules.md.
Help keep the content correct
correct-content-support · listing · hint
- Computable answers: generate exercises, test answers with a checker.
- Name a source for facts. Where it fits; never a listing condition.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
Only dependencies with an open licence
dependency-licence · listing · error
dependenciesonly with these licences, transitively: MIT, MIT-0, ISC, 0BSD, BSD-2-Clause, BSD-3-Clause, Apache-2.0, MPL-2.0, BlueOak-1.0.0, Zlib, Unlicense, CC0-1.0, CC-BY-4.0, Python-2.0.- Build tools:
devDependencies.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/dependency-licence.ts.
Fitness values as measured
entry-fitness-matches · listing · error
fitness.storage,fitness.thirdPartyfrom what the app does;lernapps check --report <file>measures it.- Anything in
localStorageorsessionStorage, also what the app only reads on loading and keeps after an input (an assistant chosen for the tutor, an answer being written) →storage: device; loads from another server after a click →thirdParty: on-click.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/entry-fitness-matches.ts.
Fill the entry from the published schema
entry-from-schema · listing · error
- Fetch the entry schema each time; never from memory or another app.
- Every value from the creator's answers, the plan or the app; never invented.
Told in skills/tooling/lernapps-cli/references/platform-rules.md.
Every link of the entry resolves
entry-links-resolve · listing · error
- Each topic: path of an existing page, relative to the app's
url;<page>#<section>names an element id there. - Check against the deployed app:
lernapps check --entry <file>.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/entry-links-resolve.ts.
Free of charge
free-of-charge · listing · error
- Every part free: no payment, paid upgrade or ending trial.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
German always, every declared language complete
learner-text-german · listing · error
- Texts for learners, teachers, parents: German, plain (short sentences, active voice, no jargon).
- More languages only where the archetype supports them (explainer, quiz:
languages, German first); each declared language complete, no other. - Texts out of code: in the content (explainer YAML, quiz bank) or message files (
src/messages/de.json, shown withtranslatorfrom@lernapps/tooling/i18n).
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the lint rule lint/rules/learner-text-german.ts; judged by the rubric item in review/rubric.md.
Learners do something themselves
learners-act · listing · error
- Every page or screen asks learners to try, practise or decide. Reading alone is not enough.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
Every link resolves
links-resolve · listing · error
- Every link and resource points to a page or file the build writes. Relative links inside the app.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/links-resolve.ts.
No account
no-account · listing · error
- Whole app usable without sign-up or login.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
No ads
no-ads · listing · error
- No advertising, sponsored content or product placement.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
Nothing about a particular learner in public texts
no-learner-data-in-texts · listing · error
- No name, class, school, grade, picture or other detail of a real learner in app, entry, README, plan or commit message, even if the creator mentions one. Made-up names in exercises.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
No request to another server before a click
no-request-before-click · listing · error
- Bundle fonts, scripts, pictures at build time.
- Other servers (video, map) only after the learner's click.
- No other servers' URLs in code; at a click-to-load line suppress the lint message with this reason.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/no-request-before-click.ts; checked by the lint rule lint/rules/no-request-before-click.ts.
Collect nothing, set no cookies
no-tracking · listing · error
- No cookies, analytics, tracking pixels, server storing data.
- Stored data stays on the device (
localStorage, orsessionStoragewhile the tab is open) and serves only the app.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/no-tracking.ts; judged by the rubric item in review/rubric.md.
Touch only the app's own data in the browser
own-data-only · listing · error
- Every app on lernapps.net shares one origin with the other apps and the platform.
- Own data: keys of
localStorageandsessionStorage, IndexedDB databases and caches namedlernapps:<id>:…,<id>the app's id in the catalog (entries/<id>.yaml). - Also every app's: the learner's settings for every app (
lernapps:settings:<key>, a key without a colon) and for every app of the page's archetype (lernapps:settings:<archetype>:…, the archetype of<meta name="lernapps-archetype">); never another archetype's.settingsis never an app's id. - Never read, write or remove other keys; never
clear(); nevercaches.match()withoutcacheName. - Built with this tooling:
createStorage("<id>")from@lernapps/tooling/storage; settings withcreateSettings("<id>", "<archetype>"). lernapps checkputs another app's data into the browser and reports every access to it, before a click.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/own-data-only.ts; judged by the rubric item in review/rubric.md.
Every page is reachable from the start page
pages-reachable · listing · error
- Every built page linked from the start page or a page it leads to; the listing checks only those.
- Pages nobody should reach: out of the build. Reached otherwise on purpose:
<meta name="robots" content="noindex">. 404.htmlat the root needs no link.- On a URL the checks visit at most 100 pages (hint); check the bundle for all.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/pages-reachable.ts.
Runs in the browser, without installation
runs-in-browser · listing · error
- Opens and works at its URL in a current browser. No app store, download or extension.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
Name source and licence of others' content
third-party-licence · listing · error
- Others' content (texts, pictures, quotes) only with a licence that allows it; source and licence next to it.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; judged by the rubric item in review/rubric.md.
Usable at 360 px
usable-at-360px · listing · error
- Every page at 360 px width: no horizontal scrolling, every control reachable.
- Deviate only where the idea needs it (keyboard required), in
limitsas underaccessible.
Told in skills/tooling/lernapps-cli/references/platform-rules.md; checked by the check check/rules/usable-at-360px.ts.
Keep the app's content guide
app-content-guide · tooling · error · warning at listing
- Keep
.agents/skills/app-content/SKILL.mdwith its fixed headings. - After the plan is confirmed and before content: replace every placeholder ("FILL IN") with concrete instructions for writing new content: files, ids, data files, an example of this app. Not how the app works, no general advice.
- A content decision changes (pattern, figure type, source rule) → change the guide in the same commit.
lernapps checkchecks the file and its headings always, and that no placeholder is left once the plan is in Commit.- App older than the guide:
lernapps updateadds the skeleton (skilllernapps-cli).
Told in guidance/workflow-rules.md; checked by the check check/rules/app-content-guide.ts.
The content guide says what was built
app-content-matches · tooling · error · warning at listing
- Every pattern it names is used; no pattern is used that it does not name.
- Curriculum, competencies, chapters, pages or rounds match the content.
- Its procedure for a new chapter or round names the current files.
- An agent without your conversation can add the next chapter or round from it alone.
Told in guidance/workflow-rules.md; judged by the rubric item in review/rubric.md.
Run the checks before you push
checks-pass · tooling · error · warning at listing
lernapps checkpasses before every push. The hooks run it too; CI runs the same command and keeps its report as the artifactvalidation-report.
Told in skills/tooling/lernapps-cli/SKILL.md.
Show a first look early
early-preview · tooling · hint
- In Code, as soon as the first screen or page shows real content: send the creator a short "Zwischenstand".
- Show screenshots, desktop and 360 px. On the creator's machine also the address of
npm run dev, started in the background. - No checkpoint, no question: go on in the same message. The creator may stop you or ask for a change.
- Example: "Zwischenstand: So sieht die erste Seite aus. Ich baue weiter; sag Bescheid, wenn etwas nicht passt."
Told in guidance/workflow-rules.md.
No code before the plan is confirmed
explore-before-code · tooling · error · warning at listing
- No code and no
lernapps createuntil the creator has confirmed the plan with a yes.
Told in guidance/workflow-rules.md.
Work on your own after the plan
few-turns-after-plan · tooling · hint
- After the confirmation, ask only what you cannot decide.
- Else choose, mark "(guess)" under "Key decisions" and list it in the retrospective.
Told in guidance/workflow-rules.md.
Fix failed checks, never bypass them
fix-from-message · tooling · error · warning at listing
- Fix the cause the message names.
- Never bypass a hook: no
--no-verify, no acceptance such asARC42_CONSISTENTwithout a finding shown. - Never delete a test to make it pass.
Told in skills/tooling/lernapps-cli/SKILL.md.
Commit the lock file with every dependency change
lockfile-matches · tooling · error · warning at listing
- Change dependencies with
npm install, never inpackage.jsonalone; commitpackage-lock.jsonwith it. - A git pin (
github:…#<commit>) moves in both files together.
Told in skills/tooling/lernapps-cli/SKILL.md; checked by the check check/rules/lockfile-matches.ts.
Keep the plan file
plan-file · tooling · error · warning at listing
- Each plan in
.vibe/plans/, with every section and front matter key of its template. - Never change the plan of an earlier piece of work.
- Set
phasewhen you enter a phase. Tick each task box when it is done. - Never edit
prePushFailuresorfailedChecks: the hook and the check write them.
Told in guidance/workflow-rules.md; judged by the rubric item in review/rubric.md.
Fill the retrospective
retrospective-filled · tooling · error · warning at listing
- At the end of Commit, fill every part with facts: phases reached, creator turns after the plan, where you guessed. No names.
- Failed checks need no entry: the check counts them in
failedChecks.
Told in guidance/workflow-rules.md; judged by the rubric item in review/rubric.md.
Stop at the creator's checkpoints
stop-at-checkpoints · tooling · error · warning at listing
- Checkpoints: research, confirm the plan and the content method, publish. Stop at each and wait for the answer.
- Checkpoint list: open the listing pull request first (it publishes nothing), then show it and its result and wait.
- A message sent before the checkpoint's question is no yes.
- Example: "Die App ist fertig und geprüft. Soll ich sie jetzt veröffentlichen?"
Told in guidance/workflow-rules.md.
Suppress only in place, with the reason
suppression-reason · tooling · error · warning at listing
- Lint: only on the line, with the rule named and the reason after
--:// oxlint-disable-next-line lernapps/no-request-before-click -- the video loads after a click. - Types: only
// @ts-expect-error -- <reason>; never@ts-ignoreor@ts-nocheck. - The review reads every suppression.
Told in skills/tooling/lernapps-cli/SKILL.md; checked by the lint rule lint/rules/suppression-reason.ts.
The content validates
explainer-content-valid · archetype:explainer · error
- Schema-valid; ids unique per level; references exist (data file, image, component, page or section link); placeholders declared; formulas only from the command list.
- Build names each problem with file, line, block path.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
The figure shows what the text says
explainer-figure-explains · archetype:explainer · hint
- Each figure shows what the text next to it explains. The caption says what to look at;
altsays what it shows.
Told in skills/archetypes/lernapps-explainer-design/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
The figure does not give the answer away
explainer-figure-hides-answer · archetype:explainer · error
- A task's figure shows the given values, never the answer.
Told in skills/archetypes/lernapps-explainer-design/references/rules.md.
Formulas as formulas
explainer-formulas-static · archetype:explainer · error
- Every formula in a
formulablock or$…$; never plain text (W = G * p / 100) or a picture. MathML for screen readers.
Told in skills/archetypes/lernapps-explainer/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
The property test passes
explainer-generated-sound · archetype:explainer · error
given,where:whereholds often; answer defined and in format for every draw; no mistake can equal it.- Failure names the seed: narrow
givenor change the mistake; never the comparator.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
German first, every language complete
explainer-languages · archetype:explainer · error
languages, German first.- Every learner text (content, data files, component props) in each, no other. Build fails otherwise.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
Typical mistakes with their message
explainer-mistakes-diagnosed · archetype:explainer · hint
- Computed tasks list real mistakes. Each message says what went wrong and how to fix it ("Du hast vergessen, durch 100 zu teilen", not "Falsch").
Told in skills/archetypes/lernapps-explainer-design/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Write only the content
explainer-only-content · archetype:explainer · error
- Write: YAML of app, chapters, pages, data; images in
src/images/; components with logic and tests insrc/components/. src/main.ts,index.html,e2e/explainer.e2e.ts, config as generated (keep-the-preset). Any other file insrc/fails the build.- Not expressible → "Where I had to guess", never code around the runtime.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
An open task checks what the material teaches
explainer-open-points · archetype:explainer · warning
- 2 to 5 points, each one sentence a learner can check with yes or no; together what a good answer needs.
- A point of the content names its section (
source), and its content is there; a point of form haskind: form. - The model answer has every point, in the words of the class.
Told in skills/archetypes/lernapps-explainer/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Numbers that fit the story
explainer-plausible-numbers · archetype:explainer · warning
- Ranges fit the thing: prices in whole cents, people whole, a bicycle 150–1500 €.
- Preconditions rule out misfits (90.91 people).
Told in skills/archetypes/lernapps-explainer-design/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Quotes exact, with their origin
explainer-quote-sourced · archetype:explainer · warning
- Quote exactly. Name its origin (author, work, year), source and licence.
Told in skills/archetypes/lernapps-explainer-design/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Every page readable without JavaScript
explainer-readable-without-js · archetype:explainer · error
- Every fact in a block, visible without JS. No meaning only inside an exercise or component.
- Every component a
nojstext: what it shows, its content. lernapps checkopens every explainer page again with JS off, bundle and deployed (listing and review too): headings, formulas, figures visible, figures named; every "Lösung" andnojstext not empty.
Told in skills/archetypes/lernapps-explainer/references/rules.md; checked by the check check/rules/explainer-readable-without-js.ts; judged by the rubric item in review/archetypes/explainer.md.
The scope says what the pages teach
explainer-scope-matches · archetype:explainer · warning
scopeof each page in your own words, never copied from the material;scopeinsrc/app.yamlwith what does not belong to it.- Each page's scope says what the page teaches, no more and no less; "Gehört nicht dazu" names what a learner or tutor might expect but the material does not teach.
Told in skills/archetypes/lernapps-explainer/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Keep the ids
explainer-stable-ids · archetype:explainer · warning
- Short, telling ids ("prozentwert", "regel") for chapters, pages, sections, exercises; keep them when texts change (entry topics, teachers' links).
- New content, new ids; never reuse a removed one.
Told in skills/archetypes/lernapps-explainer/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Structure only by sections
explainer-structure-by-sections · archetype:explainer · error
- Every heading = a
sectionblock withid,title. - A Markdown heading (
#,##, underlined) in a text fails the build.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
Every chapter and page listed once
explainer-structure-complete · archetype:explainer · error
- At least one chapter.
- Every chapter folder in
chaptersofsrc/app.yaml, every page file inpagesof itschapter.yaml, exactly once, in reading order.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
Chapter, page, two section levels
explainer-structure-depth · archetype:explainer · error
- Sections at most two deep. No heading levels set: they follow from nesting. More levels = two apps.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
The description and the playthroughs validate
interactive-app-valid · archetype:interactive · error
src/app.yamland every playthrough valid against their schemas; German first, every language complete.- Unique ids; at least one playthrough; each step expects a state or an announcement; playthrough routes exist.
- Build names each problem with file and line.
The architecture is valid and current
interactive-architecture-current · archetype:interactive · error
docs/arc42/: generic part and extension ascreate/updatewrote them, unchanged outside the app sections.- App part describes the code: every part of
src/has its block, every block its code. arc42 validate --strictandarc42 diff --stagedpass; the review checks it says what the code does.
Told in skills/archetypes/lernapps-interactive/SKILL.md; judged by the rubric item in review/archetypes/interactive.md.
The core keeps its contract
interactive-core-contract · archetype:interactive · error
src/core/index.tsexportsstart(seed, route),step(state, input);tick(state, dt)as a function if it moves on its own.- Every route starts; nothing throws; same seed, route, inputs, ticks → same states.
Every playthrough plays as written
interactive-playthroughs-pass · archetype:interactive · error
- After each step the state has the expected fields; the browser shows the expected announcement.
- Failure → fix core or playthrough, whichever is wrong; never delete a playthrough.
Extend the preset, change nothing of it
keep-the-preset · archetype:explainer, archetype:interactive, archetype:quiz · error
vite.config.tsisexport default lernapps(), with only the app's own settings as generated (lernapps({ plugins: [quiz()] })).tsconfig.jsonextends@lernapps/tooling/tsconfig.jsonas generated.- The hooks come from the package (
prepareinpackage.json); never replace one. - Never turn a lint rule off or lower its severity.
Told in skills/tooling/lernapps-cli/SKILL.md.
Publish from gh-pages, served from its root
pages-from-gh-pages · archetype:explainer, archetype:interactive, archetype:quiz · error
- GitHub Pages serves the branch
gh-pagesfrom/: usuallyhttps://<owner>.github.io/<repo>/; only repos of the lernapps organisation athttps://lernapps.net/<repo>/. - Previews of pull requests go below
pr-preview/on that branch: leave the setting. - Hosted elsewhere → the entry's
urlpoints there.
A component only where no block fits
prefer-built-in-block · archetype:explainer · hint
- Built-in blocks and exercises first. A component only for what none can express; say why in the plan.
Told in skills/archetypes/lernapps-explainer-design/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Check every fact
quiz-answers-checked · archetype:quiz · hint
- Check every marked option, number and
infoagainst the linked article before you commit. - A source does not open → say so in the plan, mark it "not checked"; never fill it from memory.
- Learners report errors through
.github/ISSUE_TEMPLATE/inhaltsfehler.yml.
The question bank validates
quiz-bank-valid · archetype:quiz, archetype:explainer · error
- Valid against the schema. Build also checks: exactly one correct in single choice, at least one in multiple choice; unique ids and options.
- Broken bank: one line per problem (position, id); fix in
src/quiz.json. Explainer exercise: named by file and block path.
One clear question at a time
quiz-clear-question · archetype:quiz, archetype:explainer · warning
- One thing per question, answerable before reading the options.
- Positive; avoid "nicht", never two negations. No trick questions.
- Plain, short sentences in every language (
learner-text-german).
Background and explanation say why
quiz-feedback-explains · archetype:quiz, archetype:explainer · hint
- Every option has an
infoof 1–3 sentences about the option, true either way ("Der Nil fließt durch mehrere Länder Afrikas und mündet in Ägypten ins Mittelmeer."). A wrong option'sinfoalso says why it does not fit. explanation: 1–3 sentences why the answer is right; for true-false, number, ordering and matching also the background.number: typical wrong numbers asmistakes(answer,message). Any question: an optionalhint, not the answer.- A wrong answer's
message(and an exercise component'sreason) says what does not fit and where to look, never the solution itself: the solution comes after the answer, with "Lösung" or the tutor.
Told in skills/content/lernapps-content-questions/SKILL.md; judged by the rubric item in review/archetypes/quiz.md.
The type that fits the question
quiz-fitting-type · archetype:quiz, archetype:explainer · hint
- One fact among things of a kind:
single-choice; several facts:multiple-choice; estimate a size:number; compare sizes or dates:ordering; connect:matching; judge a statement:true-false. - Mix the types. The type must accept every answer the text allows (
orderingonly for a fixed order).
Every question links to further reading
quiz-further-reading · archetype:quiz · warning
- At least one link per question, best the German Wikipedia (
https://de.wikipedia.org/wiki/...). titlenames the page ("Uluru (Wikipedia)").- HTTP 429 → tell the creator which; mark the facts "not checked" in the plan; go on.
Numbers with unit and rounding
quiz-number-precision · archetype:quiz, archetype:explainer · warning
- The text says how exact the answer must be ("Bis zu 100 m daneben zählt noch als richtig");
tolerancematches it. - The unit goes into
unit, not into the answer. - Sources differ → the tolerance covers them.
Write only the question bank and its images
quiz-only-data · archetype:quiz · error
- Change only
src/quiz.jsonand add image files tosrc/images/.index.html,src/main.ts,e2e/quiz.e2e.ts, config as generated (keep-the-preset). - Bank cannot say it → "Where I had to guess", never code around the runtime.
Write in your own words
quiz-own-words · archetype:quiz · warning
- Take facts, never sentences: Wikipedia is CC BY-SA (copying needs attribution and relicenses).
infoandexplanation: new, shorter, plainer, for the app's school year. Sources insources(third-party-licence).
Options a learner could believe
quiz-plausible-options · archetype:quiz, archetype:explainer · warning
- Wrong options are real things of the same kind (a river for a river), with true background.
- Options alike in length and form. No "Alle genannten", "Keine davon" or jokes. Three or four options.
Keep the ids
quiz-stable-ids · archetype:quiz · warning
- Short, telling
id("grand-canyon"); keep it when the text changes (shared links#frage-<id>). - New question, new id; never reuse a removed one.
The start page explains the app
start-page-explains · archetype:interactive · hint
- The static start page says what learners train, for whom, and how to begin.
Told in skills/archetypes/lernapps-interactive-design/SKILL.md; judged by the rubric item in review/archetypes/interactive.md.
Store only through the preset's storage
storage-through-wrapper · archetype:explainer, archetype:interactive, archetype:quiz · error
- Only
createStoragefrom@lernapps/tooling/storage, named after the app's id in the catalog (own prefixlernapps:<id>:, ruleown-data-only; works when storage is blocked). - At most 100 kB under the prefix (keys and values, 2 bytes per UTF-16 unit). Beyond,
savereturns false and the app keeps working. - A setting of the learner that holds for every app or every app of the archetype:
createSettings("<id>", "<archetype>"), saved only where the learner chose it ("app","archetype"or"all"); the app's own goes first. - Keep the learning state, not growing histories.
- What only a reload must not lose, such as an answer being written, lasts while the tab is open:
createStorage("<id>", { type: "sessionStorage" })(sessionStorage, same prefix and limit). - Never
localStorage,sessionStorage, IndexedDB or cookies directly.
Told in skills/tooling/lernapps-cli/SKILL.md; checked by the lint rule lint/rules/storage-through-wrapper.ts.
TypeScript only, strict
strict-typescript · archetype:explainer, archetype:interactive, archetype:quiz · error
- Every source file is TypeScript; no JavaScript files.
- Never
any: useunknownand narrow it, or write the type. - Type the creator's data; validate it at build time.
Told in skills/tooling/lernapps-cli/SKILL.md.
Every page has exercises
topic-has-exercises · archetype:explainer · error
- Every page has at least one exercise that practises what the page explains, with solution or feedback; best in a last section "Übung".
- The schema requires it; start, chapter and glossary pages are generated. The review judges the fit.
Told in skills/archetypes/lernapps-explainer-design/references/rules.md; judged by the rubric item in review/archetypes/explainer.md.
Browser globals only once mounted
vue-component-browser-globals · archetype:explainer, archetype:interactive · error
window,document,localStorageetc. only inonMountedor later unmount hooks (server render has none).
Told in skills/archetypes/lernapps-explainer/references/rules.md; checked by the lint rule lint/rules/vue-component-browser-globals.ts.
An exercise component has its logic module
vue-component-exercise-contract · archetype:explainer · error
- Emits
answer→src/components/<Name>.tswith pure, deterministicgenerate(seed, props),check(task, answer),solution(task),wrong(task),reason(task, answer, props, lang); property test passes. - Emits no
answered(the old contract): the explainer draws "Prüfen" and checks; a component draws none. - Block lists
exampleswith at least oneacceptedand onerejected,{ answer, seed? }in the shape ofcheck(no seed: seeds 1–50), incl. another correct answer where the text allows. - Declares prop
seed: number, showsgenerate(seed, props). The explainer gives the seed, shows "Aufgabe Nr.", "Neue Aufgabe", keeps?<id>=<n>: never draw a seed or offer "next" inside. - Also exports
describe(task, props, lang)→{ task, solution }(restricted Markdown, task exactly as shown) andabout = { task, answer, correct, mistakes }(texts by language). The tutor reads only these (the tutor page, no-JS text). - Any exercise may carry
examples: { accepted, rejected };generated: expressions ofgivenandanswer, per seed (e.g.reverse(answer)). - With
template,params,mistakesandshow(all four or none, rulevue-component-tutor-table):checkaccepts the solution and rejects each mistake's answer,paramsgives the same names for every task, each placeholder oftemplateis one of them.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
Imports only from the allowed packages
vue-component-imports · archetype:explainer, archetype:interactive · error
- Only
vue,@lernapps/app-templates,@lernapps/tooling/storage,i18n,a11y, own folder. Types from anywhere. - Interactive: also the app's
src/files and itsdependencies.
Told in skills/archetypes/lernapps-explainer/references/rules.md; checked by the lint rule lint/rules/vue-component-imports.ts.
No code or HTML from strings
vue-component-no-html-injection · archetype:explainer, archetype:interactive · error
- No
eval,new Function,innerHTML,v-html: the template renders.
Told in skills/archetypes/lernapps-explainer/references/rules.md; checked by the lint rule lint/rules/vue-component-no-html-injection.ts.
No network
vue-component-no-network · archetype:explainer, archetype:interactive · error
- No request, no URL import: props or bundle.
Told in skills/archetypes/lernapps-explainer/references/rules.md; checked by the lint rule lint/rules/vue-component-no-network.ts.
Every component block has its nojs text
vue-component-nojs · archetype:explainer · error
- Every non-exercise
vue-componentblock:nojsin every language (exercise: fromdescribe): what it shows and does, with content; same meaning without JS. - Schema requires it;
lernapps checkfinds empty or hidden ones (explainer-readable-without-js).
Told in skills/archetypes/lernapps-explainer/references/rules.md.
Props as the component declares them
vue-component-props-valid · archetype:explainer · error
defineProps<{ … }>()with types; each block passes exactly the declared props, of their types.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
Within 20 kB
vue-component-size · archetype:explainer · error
- Own code max 20 kB gzip. More → split, or a new block: write it into the retrospective.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
A test per component
vue-component-tested · archetype:explainer · error
src/components/<Name>.test.tsper component, testing its logic: other right answers the text allows, typical wrong ones with reasons, edge cases. Run bylernapps check.
Told in skills/archetypes/lernapps-explainer/references/rules.md.
An exercise component declares its exercise for the tutor
vue-component-tutor-table · archetype:explainer · hint
- The logic module also exports
template(props, lang): the task once,{name}for each input;params(task, props, lang): the inputs by name ({ G: 1260, p: 15 }), numbers or texts, the same names for every task;mistakes(task, props): perabout.mistakes, in order, the answer it gives,undefinedwhere none;show(answer, task, props, lang): an answer as text, short ("C", "3 Kästchen"). - The tutor page then has the task once, the mistakes as F1, F2 … and a table of every number (inputs, solution, each mistake), like
generated. Without them: each number'sdescribeas far as 64 kB allow, and the build's hint names the block. - Example:
src/components/ProzentFeld.tsof the template.
Told in skills/archetypes/lernapps-explainer/references/rules.md.