The register gets kept on foot, not at a laptop
A teacher marks attendance at the end of a lesson while standing between the desks: eight to twenty people, and nobody must be missed. The laptop is closed at that moment, and opening it, sitting down and finding the right group takes longer than running a finger down a list on a phone.
One screen justifies the app. The other two roles are here because the phone is already in hand. A parent wants a glance at attendance and results, not a working session. A student wants to know on the way home whether a task passed, and sometimes to fix one line. Writing a whole solution on a phone is unpleasant and the app does not pretend otherwise: the starter code comes from the task.
What is inside
Four states, not two
Being late is not the same as being absent, and neither is an excused day. The marks differ in shape as well as in colour: a tick, a cross, a clock, a shield. Roughly one man in twelve cannot tell red from green.
The language of iOS, not repainted Material
The difference is not colour: the large title collapses as you scroll, a swipe from the left edge goes back, lists overscroll with a bounce, pickers rise as a sheet. Each tab keeps its own navigation stack.
A tab set per role
A teacher opens on the register, a parent on their children, a student on lessons. Not a permission but an order: everyone has their own reason to open the app, and it comes first.
A parent's view without the child's code
The adult sees attendance, solved tasks, recent lessons and submitted work. Not the code, deliberately: the API does not return it and the app does not ask. Going through a solution is the teacher's job.
Three languages, keyed by the source string
Labels for statuses, roles and difficulty arrive from the server already translated: the app sends Accept-Language and keeps no second copy of those words. Its own strings live in one map, and anything untranslated stays readable text.
Grading on a queue, polled for a result
One build on the compiler service takes seconds and a Go build about twenty. The app submits, gets an id back and polls until the result is ready, instead of holding a request open for a minute.