/turnmarks in five spreadsheets

Bhala

Primary schools, South Africa · Our own product

The problemA whole class's year living in one fragile spreadsheet.

A markbook platform for South African schools. Marks are append-only and the database enforces it, absences are never scored, and mark entry works offline. Live since October 2026.

Before and after

  • Before: A whole class's year living in one fragile spreadsheet.Now: Every mark kept, append-only, and never overwritten.
  • Before: An absence typed in as a zero.Now: Absences are never scored.
  • Before: Report comments written from scratch every term.Now: Drafts built from sentences the school wrote itself.

What we built

Bhala is a markbook for a primary school class. A teacher picks a class, a subject and a term, enters marks one assessment at a time, and the term mark is worked out from weights that sit on the screen rather than typed in by hand. The same marks then feed a read of the class, a report comment built from sentences the school wrote itself, and the groundwork for next year's classes.

We built it, and it is live: teachers have used it since October 2026. Marks are append-only and the database enforces it, absences are never scored, and mark entry works offline.

Keep every mark in one markbook

Pupils down the left, assessments across the top, each headed with its date, its kind and what it was out of. The weight on every assessment is editable in place and the total is shown beside them, and the term mark on the right is worked out from those weights rather than entered. Subject and term tabs sit above, and the sheet exports and prints.

Catch a slip while marking

Mark entry takes one assessment at a time. Each pupil gets a box, and beside it the mark as a percentage, that pupil's own previous result, and the difference between the two. A slip shows itself while the teacher is still marking rather than at the end of the term.

Read the class as people

My class reads the register rather than the grid. Every child carries their initials, their home group and table, any language they take, a flag column for anything the teacher has marked, and a strip of strand markers. It filters to everyone, to children on support, or to those who joined this year, and it groups by whatever the teacher needs to see.

Show patterns, not diagnoses

Room to improve reads the marks already entered and says two things: which strands the class as a whole is weakest in, lowest first, and which children have fallen by six points or more between their last two assessments, shown against the class average. The page surfaces patterns, does not diagnose a child and does not suggest a cause; what to do next is the teacher's own judgement.

Start next year's classes with people

Class builder collects the human constraints before anything is sorted. A card per child carries the band the school has them in, the languages they take, up to three friend choices and any pairs to keep apart, and one control sends a friend choice slip to parents, so the choices come from the children rather than from a guess.

Build reports from the school's own sentences

The report screen puts a pupil's term mark, their level, their strand marks with an achievement level each and an effort grade on one side, and the school's own phrase bank on the other. A draft comment is assembled from those saved sentences and nothing else, and the panel states in the interface what may never enter a draft: sensitive records, the ability bands the phrases are chosen with, and private staff notes.

The numbers

automated tests, all green
1,968

Stack used

  • Next.js
  • React
  • TypeScript
  • Postgres with row-level security
  • Drizzle ORM
  • Cloudflare R2
  • Stripe

Related services

Industries

See it live