nine courses, two drills · all open · no account needed
Courses I write, and what is in each one. Nothing here asks for payment, and none of them asks for an account either — you open one and start. Signing in only keeps your progress.
Every figure below was counted from the thing it describes, with the commands printed at the bottom. Where a count disagrees with a project’s own README, the counted number is the one shown. Each entry also says what is broken in it today.
A dash means the course has no such thing, not that the number is missing: a vocabulary deck has cards and no lessons, and the citizenship test is one flat bank of questions.
Each one in detail
The platform — nine courses, one place
Live · no account
Nine courses in the Duolingo shape, open without an account: a path of units, a handful of questions at each step, XP for finishing a lesson. Be clear about what it is — a question bank, not a textbook. A lesson is a title, one line of context and one to three questions; there is no reading material, so bring your own source and use this to find out what you have not understood. Get one wrong and it tells you why. Node, Express and SQLite on the back, React and Vite on the front.
Kubernetes is the oldest and much the largest. Elasticsearch covers mappings, the analyzer that rewrites your query and the DSL; DevOps covers pipelines, rollbacks and incidents; TOGAF is aimed at the exam; AWS, Google Cloud and Azure link the vendor’s own documentation from each lesson; function points is IFPUG counting; and the architect course is about the job rather than a stack.
Most questions sat on the wrong lesson. They referenced lessons by array position against an intended 84-lesson layout; only 81 exist, so everything after the first short unit had drifted and six questions fell off the end unnoticed. Each question now names its unit and lesson explicitly, and the loader refuses to start rather than silently dropping a row. Checked against the live data: every question sits on the lesson it was written for.
Seven lessons had no question at all — a score of 0/0 fails the 70% mark, so they were dead ends you could never clear. They have questions now. 21 of the 143 questions were written to fill those gaps and are not from the original repository; the other 122 are. Worth knowing before you treat every answer as the author's own.
The answer key was sent to the browser with the question. It now arrives only in the reply to your answer, together with the explanation.
The production build failed on two type errors, and every page refresh signed you out because the route guard redirected while the profile request was still in flight. Both fixed.
Still rough
Command answers are compared as text. Case and stray spaces are forgiven, but two ways of writing the same command — --selector=app=nginx against -l app=nginx — are not known to be treated as equal.
Achievements are listed in the interface and never awarded.
Run it yourself
git clone git@github.com:alexff91/learn-kubernetes.git
cd learn-kubernetes/backend && npm install && npm run build && npm start
cd ../frontend && npm install && npm run build
The backend defaults to port 5000, which macOS holds for the AirPlay receiver; change it in backend/.env and in the proxy in frontend/vite.config.ts first.
Source: github.com/alexff91/learn-kubernetes — private, and not linked, because the URL 404s without access. Ask for access.
Vivre ensemble — Luxembourg citizenship test
Live · no account
Everyone sitting the Luxembourg citizenship test reads the same official booklet and then has nowhere to practise. This is the practice: every question carries the reasoning behind the right answer, not just a tick, and there is a mock paper in the real format.
Not official and not affiliated with anyone. The state runs the course and the exam itself, free, including online in English. This is practice alongside that, not a replacement for it.
The questions were written by hand from public material. If one has drifted from the current syllabus, the address in the footer is there for exactly that.
Progress is tied to this browser. Clear its data, or open the site on your phone instead, and you start from nothing.
LuxFlash — Luxembourgish vocabulary
Live · no account
Luxembourgish is required for the Sproochentest and there is very little to study from. A deck, graded by level: what you already know comes back less often, what you forget comes back sooner.
There is no audio, and the Sproochentest is spoken. A silent deck builds vocabulary and cannot prepare you for the oral part on its own.
The vocabulary is community-maintained. Spelling, gender and declensions are worth checking against lod.lu — every card links to it.
Not a course
learn-elastic
Not listed above
A third repository has an Elastic-flavoured name and is not a course: 3 study paths, 0 lessons, 0 questions. It is a study-hours tracker with a title, a hero line and a footer that mention Elastic; nothing in it teaches anything, so it is named here rather than dressed up as a third course.
How these numbers were counted
Run from a clone of each repository. Both scripts parse the seed files and evaluate the array literals, rather than trusting the README.
# KubeLearn
node count_content.js learn-kubernetes
UNITS : 14
LESSONS : 81
QUESTIONS (objects in seedQuestions.ts): 122
lessons with ZERO questions : 10
questions dropped at seed time (lesson_idx out of range): 6
node count_misplaced.js learn-kubernetes
actually seeded : 116
on the lesson they were written for : 41
on a DIFFERENT lesson : 75 (65% of seeded questions)
# Learn Luxembourgish
grep -c "LevelUnit(categoryId:" lib/data/level_data.dart # 32
grep "LevelUnit(categoryId:" lib/data/level_data.dart \
| grep -oE "lessonCount: [0-9]+" | awk -F': ' '{s+=$2} END {print s}' # 202
grep -o "WordModel(" lib/data/vocabulary_data.dart \
lib/data/vocabulary_extended.dart | wc -l # 602
grep -o "ipa: '" lib/data/vocabulary_*.dart | wc -l # 602
grep -o "WordModel(" lib/data/phrases_data.dart | wc -l # 38
grep -o "GrammarExercise(" lib/data/grammar_*.dart | wc -l # 25
# learn-elastic
grep -c "targetHours:" src/main.js # 3
grep -riE "lesson|quiz|question|answer|exercise" src index.html | wc -l # 0