ANU Grades

ANU Grades is the results system I wish ANU had. It has two sides.

Staff convene courses. They set up the assessment items, enrol students by uni ID (one at a time or from a class-list CSV), and enter marks or upload them from a spreadsheet. Each item stays hidden until they release it, and they set final grades (with a “fill from marks” shortcut).

Students log in and every course they’ve been enrolled in is there, newest session first, with the released grade and every released mark behind it. Their GPA is worked out exactly the way ANU does it. For a course still running they can set a target and see what they need on what’s left, and run a what-if: type “72/100 on the final exam” and see the course mark, the grade and the new career GPA. Nothing typed into a what-if is saved. Students can’t change a mark, a grade or a course. Results are official, so only the convenor writes them.

Try both sides:

Both use the same login page; the account decides what you see. The demo accounts are shared, so either one can “Reset demo data”.

There’s no sign-up. Open sign-up would let anyone on the internet claim a uni ID and read that student’s results. Instead, accounts are provisioned: the demo accounts and classmates come from the seed, and more can be added with node scripts/add-user.ts u1234567 "Full Name" student. A real deployment would get accounts from ANU’s single sign-on. Login here is a mock, so don’t use your real ANU password.

Why this system

At ANU your results are spread across three places. Canvas has assignment marks per course, ANUHub has final grades and a GPA, and the maths to connect them lives in a spreadsheet you rebuild every semester. None of them answers questions about the future: what you need on the exam, or whether a 6.0 is still possible. This app puts the archive and the planning in one place.

What good looks like here

The numbers are ANU’s, not mine. Grade bands, grade points, which results count and the rounding all come from ANU’s grading scale and GPA pages:

The GPA page’s own worked example (300 ÷ 72 = 4.167) is a test.

Where ANU says nothing, I made a choice and the app says so:

It looks like part of the university. The design follows my A2 course site, using its exact colours, font weights and spacing: a plain header with a crest and “ANU / Grades” lockup, gold headings, square cards and gold-headed tables, in a centred column with little on each page. One login page serves students and staff. The crest is drawn for this prototype, not ANU’s.

It works properly on a phone. Results emails get opened on a phone, so every feature works at 360px wide:

Every form is a plain HTML form, so it still works on bad campus wifi or with JavaScript off.

It talks like a person. “You need 66 / 100 on the Final exam” and “Your career GPA would go from 5.333 to 5.368”, not “required remaining performance 0.66”. When a target is already locked in or out of reach, it says that directly. Needed marks are rounded up to the half mark, so hitting the number is enough.

Results are official, and private. Only a course’s convenor can write its marks and grades, and a student only sees marks once they’re released. Tests check that:

Enrolments are keyed by uni ID, the way the university does it, so staff can upload marks before a student has ever logged in. When staff release something, any open page of an affected student offers a refresh.

What’s enforced and what’s judgement

Enforced by tests in spec/ (run with pnpm check):

The rules the agent building this is held to live in CLAUDE.md and docs/harness/.

Left to judgement: whether the wording is kind and clear, whether the phone layout feels good in the hand (checked by eye at 390px), and whether “an average plus one example grade mix” is the right answer to “what GPA do I need”. Many grade mixes reach the same GPA, so there’s no single honest answer.

What I chose not to build

The demo student’s courses are real ANU course codes, but the marks are made up. This is a prototype of the experience, not a replacement for the official record.