Project description
The problem
A student in Tashkent opens a page on the present perfect, reads it, understands it, and closes the book. Nothing has been practised.
Practice is the scarce resource. Coursebooks carry a handful of exercises per unit. Teachers manage forty students. Online generators produce questions written for nobody in particular.
That last point is the one that matters, and it is the one nobody builds for:
Language learners do not make random errors. They make errors shaped by the language they already speak.
- An Uzbek speaker writes "I am student" — Uzbek has no articles
- and "five book" — Uzbek does not pluralise after a numeral
- A Russian speaker writes "depend from" — from зависеть от
- A German speaker writes "I have seen him yesterday" — the German perfect covers both English past forms
- A French speaker writes "I have 20 years" — age uses avoir
- Half the region buys shirts at a magazine, because магазин means shop
A generic quiz generator knows none of this. It spends its questions on things the learner already gets right, and misses the handful of structures that account for most of their mistakes.
The solution
Lingua takes whatever material the learner already has — a photographed coursebook page, a pasted passage, or just a typed question like "when do we use should?" — and builds a full lesson from it in the learner's own language. Then it generates practice aimed at the collision between that material and their first language.
Get something wrong and Lingua does not just show the answer. It names the interference: "Uzbek has no articles, which is why this blank feels optional."
Key features
Three ways in. Photograph a page, paste text or a PDF, or simply ask a question the way you would ask a teacher. No account, no login, no app to install.
An interference model per language. Seven first languages carry a documented error profile — Uzbek, Russian, German, French, Spanish, Turkish, Arabic — each listing the specific collisions with English. About half of every generated set targets these points. Any other language falls back to a general contrastive prompt. The claim is not "we support many languages"; it is we know what goes wrong in each one.
Level budgets enforced in code. "Write A2 questions" means nothing to a model on its own. Each CEFR level carries an explicit budget — grammar allowed, grammar forbidden, sentence length, vocabulary range — and a question that exceeds its budget is rejected by the server, not merely discouraged in the prompt.
Every question is anchored. Generated questions must cite an anchor: a form or word the source material actually teaches. The server verifies each anchor against the lesson text before the learner sees anything. A question the model invented cannot reach the page. This is what stops exercises drifting away from the uploaded material.
A three-stage quality pipeline. Generate more questions than needed → deterministic structural checks → a second model pass that keeps, revises or drops each one. The app shows the learner exactly what it threw away and why.
Grading that knows grammar from typing. Writing docter for doctor is a slip, accepted with a note. Writing book for books is the mistake the question exists to catch, and is never forgiven — even though those strings are closer together.
It follows the learner. Every answer updates a skill profile. Miss enough prepositions and the next set is told to aim there. Missed questions return on a spaced ladder — 1, 3, 7, 16, 35 days — retiring only after surviving all five steps.
A vocabulary game, follow-up chat about the lesson, pronunciation on every English example, a daily streak, an accuracy chart by grammar area, and a printable worksheet with answer key for teachers.
Built With
- async-httpx
- backend
- claude-sonnet-as-automatic-failover
- from
- frontend
- no-build-step-**speech:**-the-browser's-own-web-speech-api
- no-database
- no-personal-data-held-anywhere-**deployment:**-render
- one
- pydantic-**ai:**-gemini-3.5-flash-as-primary
- serving
- so-pronunciation-costs-nothing-**storage:**-browser-localstorage-?-no-accounts
- the
- with
- with-a-model-name-fallback-chain-and-exponential-backoff-between-retries-**frontend:**-vanilla-javascript-modules-?-no-framework
Log in or sign up for Devpost to join the conversation.