Skip to content
How much to read

AppendixThe first version of EaseMySemester, kept because the measurement that replaced it is argued here. The current product is the page before this one.

EaseMySemester v1

The first version: ten years of scattered exam papers turned into a tagged, browsable question bank, with a ranking that guessed what would be asked next. Six students paid for that ranking. It is still running, and v2 replaced it.

Open v1(opens in a new tab)

Still hosted, still with students on it, with a demo account offered on the login screen. It is here because the distance between this and v2 is most of what both pages are about.

Role
Product, research and engineering
Year
2026
Stack
Next.js, TypeScript, PostgreSQL, Neon, Vercel

At this depth1 min2 min7 min of 7

7.67 vs 6.00plain counting beat my own tuned weights on an exam year it never saw, so counting shipped

In short

Problem
Ten years of past exam papers scattered across drives and group chats, with no way to see what had actually been asked repeatedly.
User
First-year MBBS students, roughly fifty in one batch, invite only and never marketed.
Decision
No model in the ranking. The question was countable, so it was counted, and the counting was graded against a held-out year before it shipped.
Refused
No LLM in the ranking, no public signup, and no ingestion pipeline: getting PDFs into the database stayed an offline job I ran myself.
Number
8 of 20 predicted questions turned up in the real paper. One cycle, one cohort, scored against a 2026 paper the ranking had never seen. A signal, not a validated model, and the question-level control against that same paper is still unrun.

What this one proves

  • A prediction feature built out of counting rules rather than a model, on purpose, then graded against an exam year it had never seen. Plain counting beat my own tuned weights, so the baseline shipped.
  • An importer that either accepts a file completely or rejects it with line numbers, because a half-imported question bank is the failure nobody reports.
  • Finding a leak in my own harness, a cutoff that let a year count as evidence from before itself, and treating the number it had been producing as worthless rather than as nearly right.
v1 today, asking how you want to prep: set a plan, or go straight to the questions.
Review: 146 questions across 30 topics, ranked by how often each is asked, with the most-asked named at the top.
Intelligence: exam, subject and paper picked at the top, and under them the important topics ranked by where next year's questions cluster.
EaseMySemester v1, as it runs. Scroll for more; tap any screen to open it full size.

That is the brief. Set the dial to 3 min for the argument, section by section, or Deep for all 7 minutes of it.

Where this is: superseded, and still running. Sixteen of the roughly fifty students are still on this version; the other 34 have moved to v2. Nothing here is being developed any more. The page exists because the measurement at the bottom of it is the reason v2 looks the way it does.

v1: counting, on purpose

The feature people paid for guessed which questions were coming next. Last cycle it flagged 20; 8 of them showed up in the actual paper.

The bank covers 2016 to 2025. It was scored against the 2026 paper, so nothing the ranking had ever seen could contain the answer it was being asked for. That separation is the whole reason the number means anything, and it is the first thing I would want to check if someone showed me this.

I nearly used an LLM here. It is the obvious move and I would have learned something building it. But someone was going to message me asking why a question was ranked first, and I did not want the answer to be "the model said so." So it is counting rules: how often a question has been asked, how long since, whether the topic is climbing, and every card shows its working: Asked 5×, 3 yr gap, Rising topic.

Two other things settled it. The question is arithmetic, not language: "how often has this come up, and when?" is something you count. And it has to give the same answer twice. A top 20 that reshuffles overnight would be worthless during exam week, and worse, it would be obviously untrustworthy the first time someone noticed.

Boring, and it hit 40%.

Where a model does help, I use one: the question banks are generated with LLM assistance and then forced through a strict validator before anything enters the system. The model produces material. It never produces truth.

Every question paper from 2015 to 2025, counted by topic and by year. The problem is countable, which is why it doesn’t need a language model.
Every question paper from 2015 to 2025, counted by topic and by year. The problem is countable, which is why it doesn’t need a language model.

I got the navigation wrong

The data model had paper as a level you click through: exam → subject → chapter → paper → topic → question. Six levels. Faithful to the data, and I was pleased with it.

Then it came back to me that the thing was painful to use the night before an exam. Five clicks before you see a single question, on a tool whose whole purpose is "I have one hour, show me what they ask about this."

I rebuilt it as two panes: the tree on the left, the chapter's questions on the right, and paper demoted to a filter. Coming back restores your last chapter at zero clicks. Switching chapters costs one to three.

Two panes: the tree on the left, the chapter’s questions on the right, paper reduced to a filter. Every question carries the tag saying exactly where it appeared, board and year and session and paper, with the empty month dropped.
Two panes: the tree on the left, the chapter’s questions on the right, paper reduced to a filter. Every question carries the tag saying exactly where it appeared, board and year and session and paper, with the empty month dropped.

The data model didn't change. Paper is still on every question. What changed was my assumption that a faithful structure is a usable one. Those are different things and I'd argued myself into conflating them.

This is the fix v2 later took much further, and the reason I trusted it enough to go further. The click count was the first hard evidence I had that the structure I found elegant and the structure a student needed at 1am were not the same structure.

The part nobody sees

The hard problem was never the interface. It was that ten years of hand-curated exam questions rot unless every file is checkable.

So the format came first. YAML at the top for subject, exam and paper, then a five-token tag on every single question, (AKU 2020 null Reg P1): board, year, month, session, paper. Repeat appearances get joined into one tag.

The importer either accepts a file completely or rejects it with line numbers. There's no partial import. The person loading these files is a medical student, not an engineer, and the thing to protect against isn't a rejected file. It's a half-imported one that nobody notices until the night before an exam.

Once real people were using it I did a hardening pass. Eight fixes, one commit each so any of them could be backed out alone. I ordered them by what actually breaks. The first three cause something you can see: an unhandled database pool error taking the whole process down, students hitting a raw exception screen, the import page going white when a session expired. The other five quietly corrupt the question bank, which is worse because nobody reports it. Cleanup deletes were sweeping the entire database, so publishing Anatomy was quietly garbage-collecting Biochemistry.

The speed fix went last on purpose. A 2,000-question file used to take about 6,000 separate database round trips and blow past every serverless timeout; it now publishes in about 1.7 seconds. It rewrites the same loops the earlier fixes touch, so doing it first would have undone them.

Everything downstream inherits that discipline, including all of v2. The browse view, the counting rules and the retrieval all work because the corpus underneath is clean and tagged the same way every time.

Study priorities, ranked by frequency with recent years weighted double. The same counting rules, applied to topics instead of questions.
Study priorities, ranked by frequency with recent years weighted double. The same counting rules, applied to topics instead of questions.

I ran the control and the dumb version won

Everything above says the ranking is worth having. What I had never checked was the ranking against the obvious alternative: counting, with none of the recency, gap or momentum logic sitting on top of it.

So I built a harness that grades a ranking against an exam year it has never seen. It tunes on every subject and cutoff with at least three prior years behind it, ten of those, and validates only on 2025, which the sweep never gets to look at.

Counting alone scored 7.67. My hand-tuned weights scored 6.00. The best set the sweep could find for itself scored 7.33. By the harness's own rule, a tuned result that cannot beat plain counting on the held-out year is not an improvement, so it ships as frequency-only. The other signals are still computed and named in the code, zeroed out, so a later sweep can switch them back on if one ever earns it.

Two things nearly let me believe otherwise. The first version left frequency as an unbounded count while every other signal was squeezed into a nought-to-one range, so frequency dominated by construction. On one subject the tuned engine was already handing back the baseline's answer and nothing on screen would have told me. The second was a leak in the cutoff itself: asking for 2024 let 2024's own sittings count as evidence from before 2024. Ninety-four occurrences, in every one of the ten cells I was tuning on. A harness with a leak in it is worse than no harness, because it still produces a number and the number has my name on it.

This is not the same measure the 40% came from, and the two should not be read as one trend. That was 20 questions against the 2026 paper, measuring v1. This is topics, scored on recall at ten against 2025. The question-level control on that same paper is still unrun.

But the reason v2 ranks topics rather than questions is itself the finding: holding out 2025, 14% of its questions had been asked before and 89% of its topics had. A question-level ranker has a ceiling too low to carry the product. So the feature six people had been paying for is the one the measurement told me to replace, which is an uncomfortable order to find things out in, and the plainest argument I have for building the measuring part first.

What replaced it

v2 is the same students and a much narrower moment: the hour before the paper, answered out of nine textbooks with the page number attached. It threw out the self-rating flow, the six-level browse tree as the front door, and question-level prediction, the feature six people were paying for, and it has no paid tier at all.

Read what v2 does instead.

That is every section's opening. Deep has the working under each one, 7 minutes in all.

What is still open

Whether the 40% survives the same control at the question level, against the 2026 paper it was scored on. Counting has already beaten my tuned weights at the topic level, on a different held-out year, and the question-level control is still unrun.

Written up separately

Next

EaseMySemester

Rebuilding a working product around the one hour that actually matters once I understood when it was being used, and shipping an answer feature that declines rather than guesses when the books do not cover the question.

Get in touch

contact@adwitiyarahman.in

Happy to walk through any of this, including the parts that did not work. Or see the other projects.