MathWiz
A marketing site and a full exam-delivery LMS for one tutor
Two products for an A/L Combined Mathematics tutor — a marketing site at mathwiz.app, and an LMS at lms.mathwiz.app that runs timed papers and collects handwritten answers through a phone camera.
mathwiz.app
Chamoda Liyanage teaches A/L Combined Mathematics in Negombo and Wattala, across in-person and online classes, to several hundred students split by exam year. The teaching was working. The paperwork around it was not: papers printed and distributed, answer scripts collected by hand, marks tracked in spreadsheets.
We built two things — the public site at mathwiz.app, and the platform that does the actual work at lms.mathwiz.app.
The hard problem: handwritten maths
Combined Maths answers are pages of handwritten derivation. They cannot be typed into a form, and they cannot be auto-marked. So the platform's job is not to replace marking — it is to move paper around without anyone touching paper.
A student sits a timed paper on a laptop. When they finish, they need to get five or six handwritten sheets into the system. The flow we built:
- On Submit, the server issues an HMAC-signed magic-link token scoped to that attempt and renders it as a QR code.
- The student scans it with their phone. The magic link opens the capture page with no login — the token is the authorisation, and it dies when the attempt is submitted.
- The phone camera captures each page in order, with retake and drag-to-reorder before anything is sent.
pdf-libassembles the pages into a single PDF in the browser, prepends the student's generated cover sheet as page one, and uploads straight to Cloudflare R2 through a presigned URL.- The laptop, which has been polling the attempt, sees the submission land and moves the student to their results.
On mobile the QR handoff is skipped entirely — the session is already authenticated, so the same capture flow just opens.
Rules the platform enforces, not the tutor
- The timer is server-authoritative.
startedAtis set server-side; the client only renders the remaining time. Closing the tab, changing the system clock and reloading all do nothing. - One attempt per student per paper, enforced by a unique constraint rather than a check that can be forgotten.
- Submitted attempts are locked. Once
submittedAtis set, no resubmission is accepted. - Every cover sheet carries a QR code encoding its attempt ID, so a batch of corrected scripts can be bulk-uploaded and matched back to students automatically.
- Marks are visible the moment they are entered. There is no release step to forget.
Structure that matches how classes actually run
Batches (2027 A/L, 2028 A/L) contain classes (group, night, revision), which contain enrolled students. A re-sit student can sit in classes across multiple batches at once, which is common and which most off-the-shelf LMS products handle badly. Enrolment is approved per class, not per platform. Deleting a batch or class cascades cleanly through both PostgreSQL and R2, so nothing is orphaned in storage.
Homework and worksheets reuse the same capture pipeline with the timer and cover sheet removed.
The website
A separate Next.js and Sanity build, designed light-first around a graph-paper geometry drawn from the MathWiz logo — academic rather than playful. It carries the tutor's background, the class timetable across four locations, the Elite Paper Program, results, and an enrolment enquiry form.