This is the app behind most of the examples in the talk. It runs on one laptop, it holds real student data, and it is the reason I can say anything useful about where AI helps a teacher's week. This page is what I can honestly share of it: what it does, the rules that emerged while building it, why it is shaped the way it is — and enough of a recipe that you could build the version you need.
The problem it was built against
The goal was never "use AI in teaching". It was narrower and more selfish than that: spend the working day on explaining things to people, and not on remembering things.
Which students are behind. What each one got wrong last time, and whether it is the same thing they got wrong the time before. Whose homework is missing. Which topic the whole class fell over. None of that is teaching. All of it is load, and all of it is the kind of thing a database is better at than a person.
Six things, built in roughly this order
A daily page. Opens on today: the timetable with each lesson's plan, and for every class a "pulse" — who is missing work, who is trending down, who needs a word. Marking. Multiple-choice papers are photographed and scored; extended writing gets a drafted comment I then arbitrate. Gap analysis. Which topics the class actually failed, ranked, with the most common wrong answer as a clue to the misconception. Reports. A term's evidence turned into candidate strengths and targets in house style, which I pick from and edit. Nudges. Drafted messages about missing work, grounded only in the actual missing list. Department views. The same watch list logic, run across every class at once.
Shown with a class that does not exist
Every name and every number below is invented. Not anonymised, not initialised, not a real class with the names swapped — generated from scratch to look plausible.
That distinction matters, and it is the same one the talk makes about initials. If I had taken a real class and changed the names, the marks would still be real, the rank order would still be real, and any colleague who teaches that group could read it straight back. Fabricating the whole set costs nothing and removes the problem entirely.
| Student | Paper 1 | Paper 2 | Paper 3 | Predicted | Flags |
|---|---|---|---|---|---|
| Sun Wukong 悟空 | 88 | 79 | 82 | 7 | |
| Lisa Simpson | 84 | 81 | 76 | 7 | |
| Velma Dinkley | 76 | 72 | 74 | 6 | |
| Doraemon | 71 | 68 | 65 | 6 | |
| Nezha 哪吒 | 69 | 74 | 61 | 6 | |
| Daria Morgendorffer | 66 | 63 | 70 | 6 | |
| Astro Boy | 61 | 58 | 64 | 5 | |
| Charlie Brown | 57 | 61 | 52 | 5 | |
| Marge Simpson | 55 | 52 | 58 | 5 | |
| Fred Flintstone | 52 | 48 | 55 | 4 | 1 missing |
| Bugs Bunny | 49 | 55 | 44 | 4 | |
| Shaggy Rogers | 45 | 41 | 48 | 4 | 1 missing |
| Bart Simpson | 39 | 44 | 36 | 3 | 2 missing · trend ↓ |
| Scooby Doo | 34 | 31 | 38 | 3 | 3 missing · trend ↓ |
The flags on the right are the whole point of the page. Nobody needs a table of marks — that already exists in the gradebook. What a teacher needs at 8am is the three names that need something today, and the reason why.
| Syllabus unit | Class average | Most common wrong answer suggests |
|---|---|---|
| Market failure & externalities | 41% | Confusing external cost with total cost |
| Elasticity (PED, YED) | 48% | Sign of the coefficient ignored |
| Macro policy conflicts | 52% | Treating unemployment and inflation as independent |
| Exchange rates | 55% | Appreciation read as "stronger economy" |
| Demand & supply | 71% | — |
| Theory of the firm | 74% | — |
Two guards sit behind that table. A unit is not called reteach-worthy until there are at least three attempts at it, and a student is not told they have a personal gap unless they trail the class by fifteen points or more on it. Otherwise a topic that was hard for everyone gets read as one child's failing, which is both wrong and unkind.
None of these were decided in advance. All of them came from something going wrong
This came from a real failure. Last year I ran a multiple-choice analysis for a class through an AI chat and got back a confident, well-formatted report. It listed one student as wrong on four questions that the mark scheme — and that student's own transcribed answers — showed as correct. The model had simply counted wrong, and nothing about the output looked wrong.
Now every number in the app is produced by a database query. The model transcribes handwriting and it narrates findings. It never counts, scores, ranks or decides. If an answer is objectively checkable, checking it with a model turns a solved problem back into a probabilistic one.
Answer sheets are photographed and read by a vision model. The safety net is structural rather than clever: a paper has a fixed number of questions, answers can only be A to D, and numbering runs in sequence. Almost any misread therefore produces an impossible value, which gets caught and flagged for a human instead of quietly accepted.
Checked by hand against real scans, it read 59 of 60 letters correctly — and the one it missed came back flagged, not silently wrong. A blank I have to fill in costs me ten seconds. A plausible wrong mark costs a student their trust.
"Which students need attention" is defined once, in one function. The daily class page uses it. The department-wide view uses the same one. They cannot drift apart, because there is nothing to drift — the second feature calls the first.
The tempting alternative was to write a fresh, slightly better definition for the department view. Two definitions of "concern" in one system means two answers to the same question, and a conversation with a colleague where neither of you is wrong.
Every message the app drafts — parent emails, homework nudges, conversation notes — is paste-in and copy-out. There is no send button, deliberately, and the API keys that would make one possible are not in the app.
This is the automate/augment line drawn in code. The drafting is automated; the sending is a person deciding to send. It also means a bad draft is an inconvenience rather than an incident.
The nudge drafter will not write a message about missing homework for a student who has none. The report generator will not show a trend from three data points. A student's name that does not match the register is left unassigned rather than guessed at.
A tool that always produces something is a tool you have to check every time, which is most of the work you were trying to remove. A tool that refuses when it should is one you can trust when it doesn't.
And why the boring choice was the right one
A desktop application, running locally. A SQLite database file on the laptop — no cloud, no sync, no server. Where AI is genuinely needed — transcribing handwriting, drafting prose — it calls a domestic model API, so student data never leaves the mainland. Everything else is plain queries.
Local-first started as a compliance requirement: student data belonging to people in China has to stay in China, so the easy path — a cloud database, an account system, sync across devices — was closed from the start.
It made the app better. No hosting bill, no outage, no login, no data breach that is possible in principle. It opens instantly because there is no network in the loop. The constraint removed an entire category of problem I never had to solve.
An earlier version of the gradebook synced student first names, class IDs and initials to a database hosted outside China. Minimal data — but enough to identify specific students in context, which made it an unlawful cross-border transfer. I took it offline when I realised.
The cost of getting it wrong at the architecture stage is a weekend. The cost of getting it wrong after two years of use is everything in it. See the compliance guide for what the rules actually are.
And why that is the argument, not an excuse
People ask for a copy, and the honest answer is that the reason I can't hand it over is the reason it is safe.
It holds real student data in a file on one laptop with no sync — which is exactly what a compliant tool looks like. A version I could email you would be a version that had already broken that rule: either it carries the data with it, or it is an empty shell that needs a weekend of setup and a database schema you did not design and cannot maintain.
The version that is actually transferable
What transfers is not the code. It is the shape. If you are building anything that touches student data, this is the recipe I would give you:
Any of the tools on the Tools tab will do this. I use a local install of bolt.diy pointed at a domestic model, which means the building itself also stays inside China and costs API pennies rather than a subscription. The setup is on that page.
You do not need to be a programmer. You need to be able to say precisely what you want, notice when the answer is wrong, and refuse to accept an output you cannot check — which is a teacher's skillset, not an engineer's.