🎓 Native GitHub Classroom

How it works


The shape in one line: one org per course, one teacher control repo holding the engine, one workspace repo per student, and grading and publishing kept as two deliberate steps. This page walks the parts that make that safe to run. It is the architecture, not the course content: no student data and no private course internals live here, and the canonical grader tests and the gradebook stay in the private control repo.

The four repos
The orgone per course, owned by the org so the engine can reach in and grade, and locked down so a student sees only their own repos.
The teacher control repothe engine: the scripts, the workflows, the private grader tests, and the gradebook. The gradebook is the single source of truth. If it is not in the gradebook, it did not happen.
The student workspace repoone per student, both their graded coursework and their personal scratch space.
Canvasthe only outside system, and only at the end, to receive final grades as one CSV.
The parts that were the real work

The interesting engineering was never the grading. It was the plumbing around who can touch what. Every real bug was a boundary bug.

Access control is the whole ballgame

The org owns every repo so the engine can grade it, but each student has to be the admin of their own repo and no one else's. That is a narrow beam to thread, and getting it wrong is not cosmetic. I stopped trusting my memory of who could reach what and wrote an audit that checks it directly, by actual collaborators on each repo.

Tokens, not titles

Being an org admin does not let a workflow reach into other repos. The workflow needs its own scoped token. Obvious in hindsight, a lost afternoon at the time.

Names are data

The course code in a repo's name is what the engine filters on, so a misnamed or unconfigured repo matches to nobody. Half my "the grader is broken" panics were really "a repo is misnamed." Now an audit catches the bad names before I ever run a grade.

Safe by default, or not at all

Anything that writes to a student repo or the gradebook dry-runs first and shows me the plan. I read what is about to happen before it happens. That one rule is why I can let automation this close to real grades sleep at night.

Booting a term

The operating loop I open every term with, each step something I can point at and say that works: lock down the org, stand up the control repo, get every student a correctly named workspace, push a unit of content and confirm it landed everywhere, then have them do the hello-world activity and watch it show up as a graded row in the gradebook. When that first green row appears, the platform is confirmed end to end.

Read more
The full build storythe maker's account of the reframe, the design, and everything that broke on the way.
Native GitHub Classroomback to the project page.
Part of tjakoen.github.io.

🤖 Built with Claude. I don't prompt and pray, I prompt and prove. Every commit here is co-authored with an AI, on purpose. How I actually work with AI, receipts and all →