The problem
Language teachers spend a big part of their week producing practice material: twenty gap-fill sentences on the dative, a short reading text about a supermarket with five questions, a listening clip. Then they mark all of it, and then they try to remember which student keeps failing which topic.
ChatGPT in a browser tab can already write the exercises. But it doesn't know who a teacher's students are, so it can't say which topic a class is weak at, and everything it writes still has to be handed out and marked by hand.
What I built
LangDrill is a web app that closes that loop. The teacher generates exercises, bundles them into a template, assigns the template to a room of students, the model grades each answer, and the grades roll up into class statistics. Sebastian and I built it over the summer of 2025: I wrote the backend, prompts and database schema, and he joined on the frontend in July (the repo is split almost exactly in half, 144 commits from me and 137 from him).
What it does
- Generate exercises. Writing, reading and listening drills. The teacher picks a language, a CEFR level, the number of items, a variation (fill in the blanks, sentence reordering, conjugation drills) and a topic, then checks the result before saving it.
- Bundle and assign. Exercises go into templates, and templates are assigned to rooms of students.
- Grade answers. Every answer is marked, with one or two sentences of feedback on each mistake and a grammar tip.
- Show where a class struggles. Each room has a page with top students, completion rates, accuracy by exercise type and the best and worst grammar topics.

- Ask about your data. A chat screen for questions like "which grammar do my students not understand at all?".

Why these tools
OpenAI does the generating and the grading, and every endpoint returns one strict JSON shape, so the frontend can render any exercise without guessing. My first version was a chatbot that parsed the teacher's request with keyword matching. That was a form with extra steps, so within a week it became a form, and the chat moved to the side.
Supabase holds teachers, rooms, students and grades. Its row-level security (Postgres rules like "a teacher can only see rooms they own") is what is supposed to keep one teacher's data away from another's. FastAPI sits between the frontend and the model, so prompts and keys stay on the server. Brevo sends the class emails, Railway runs the backend and Vercel the React frontend.
What was hard
The dashboard depends on one field. Every graded exercise comes back with a grammar_topic, and the room page groups scores by it. That only works if every exercise about pronouns is labelled pronouns, every time. I gave the model a closed list of 67 grammar topics across six languages, and it still tagged exercises with whatever the student got wrong instead of what the exercise was about, and invented new topics when nothing fit. It took seven commits to the grading endpoint in one afternoon before the prompt said, in capitals, "DO NOT invent a new topic". A fixed list reads worse than free text, but it can be counted.
The other lesson was about the database. The backend first used one shared Supabase client, so the row-level rules couldn't tell who was asking. When real logins arrived, I switched to a client per request carrying the user's token. That fixed the bug but didn't make the app secure, and I only saw how far off we were a year later.
What it became
By the end of August 2025 LangDrill had a new logo, a Railway deploy, a landing page at langdrill.com, and Brevo sending the class emails. Then the commits stop. The next ones are a license in November and a README in February.
In July 2026 we picked it up again. I merged the separate frontend and backend repos into one deployable image, wrote the docs and a known-issues.md, and planned the next features: an interactive reader, turning scanned workbooks into exercises, and voice practice (OpenAI Realtime by default, ElevenLabs as fallback). Sebastian then built most of it in three days: Redis job queues, Docling for PDF parsing, a book reader with word lookup, vocabulary lists, a voice chat page. The debugging plan in the repo starts with a 120 KB PDF stuck in queued for 20 minutes, so that part is still being worked out.
The audit behind that file found nineteen database functions that bypass row-level security and trust a user ID sent by the caller, so a student could read exercises from assignments that aren't theirs. It's all written down, with file names.
I don't have usage numbers to put here. The landing page is live, the loop from generating to grading runs end to end, and the docs are honest about the holes.
