WORK INDEX
BOOK A CALLEMAIL ME
OWN PRODUCT  ·  IN PRODUCTION  ·  2026

The hard part wasnever the calendar.

PRODUCT
ClassPortal
ROLE
Everything
API
GraphQL
STACK
NestJS · Next.js
DATA
Postgres · TypeORM
ClassPortal tutor dashboard
01  THE PROBLEM

Private tutors run a business out of a spreadsheet and a chat thread.

Students in one sheet, this week's schedule in another, assignments in a chat thread, and invoicing done by hand at the end of the month from whichever of the three is least out of date. Every tool that promises to fix this is built for a school with an administrator, not for one person teaching twelve students.

But scheduling was never the difficult part. The difficult part is that a tutor is not a fixed thing: they start alone, they get busy, they take on a second tutor or join someone else's agency, and the records have to keep working across that change rather than being exported and re-entered.

The constraint I set: growing from one tutor to an agency must never mean starting a new account.
02  ARCHITECTURE

Two deployables, one database.

A NestJS API exposing a single GraphQL surface, and a Next.js client that consumes it. One Postgres behind the API through TypeORM. The split is deliberate: the domain is wide enough that module boundaries are worth having, and the web client was never meant to be the only thing that talks to it.

FIG. 02.1 / SYSTEM
CLIENT
next.js
GRAPHQL
apollo
TYPEORM
entities
POSTGRES
source of truth
ONE SCHEMA, TYPES GENERATED FOR BOTH SIDES OF THE WIRE
EVERY RESOLVER ANSWERS THE TENANT QUESTION FIRST
03  DATA MODEL

Built around the operation most likely to go wrong.

Reassigning a student between tutors, and deleting an organisation without deleting the people in it, are the two operations that touch everything else. The shape of the schema is mostly a consequence of making those two safe.

organizations
Membership is its own row rather than a column on the user, so a tutor can join or leave an agency without their students and invoices being rewritten or lost.
sessions
A four-state machine, scheduled through confirmed to completed or cancelled, plus the recurrence group it was born in.
students
Owned by a tutor and reassignable to another. That single operation is the one everything else in the schema has to survive.
invoices
Unpaid, paid or overdue. Rendered to PDF and emailed on demand; the renderer never writes the status it is printing.
04  STACK MANIFEST
CLIENT
Next.js · React · Apollo Client · Tailwind
API
NestJS · GraphQL · Passport · argon2
DATA
Postgres · TypeORM · Supabase Storage
SERVICES
Resend · PDFKit · Gemini
Have a business running on a spreadsheet?