ModuleDrill

2026 · JavaScript, reverse engineering, web development

What it is

A free web app that runs timed digital SAT practice modules, built on College Board's public question bank. It reproduces the structure of the real test: 27 Reading and Writing questions in 32 minutes, 22 Math questions in 35, in the domain order the actual exam uses, with the interface and tools of Bluebook — countdown clock, mark for review, answer eliminator, question navigator.

I built it while preparing for the SAT myself. I was doing sets of ten questions and logging mistakes in a spreadsheet, which teaches you nothing about pacing, and the only way to test a change in approach was to spend one of my six official practice tests. The interesting part of the project turned out not to be the interface but the constraints: the questions are copyrighted, there is no public API, and most of the bank is unsafe to practise with.

moduledrill.com — free, no account, works in any browser.

ModuleDrill home screen showing full test, single module and custom drill options
The home screen. The green panel is the spoiler protection, on by default.

The constraint that shaped it

No public API. College Board publishes a question bank for teachers but documents no way to read it programmatically. I traced the network calls their own site makes and found three undocumented endpoints that answer without authentication and send Access-Control-Allow-Origin: *, which means a browser on any domain can call them directly.

The content is not mine. The obvious build is to download all 3,300 questions and serve them from my own site. That is a mirror of someone else's copyrighted work, and it is the version that gets taken down. So the app ships with no question data at all: it is a single HTML page, and each visitor's browser fetches questions from College Board directly and caches them in IndexedDB. My hosting serves about 73 KB of static files and never touches a question. That decision drove everything else — no backend, no database, no accounts, and as a side effect nothing to collect about anyone.

Most of the bank can hurt the student using it. This was the finding that changed the project. College Board flags questions that are still in active use on test forms, and roughly two thirds of the bank is flagged. Those are exactly the questions that can appear on an official practice test a student hasn't taken yet. Practising with them quietly burns the very thing they are saving. Excluding them by default cut the usable pool from about 3,300 questions to about 1,200 — two thirds of the app's apparent content removed on purpose.

Reconstructing the test

Drawing questions at random produces a set of questions, not a module. A real Reading and Writing module runs through its domains in a fixed order — Craft and Structure, then Information and Ideas, then Standard English Conventions, then Expression of Ideas — and within each domain the skills appear in a set sequence and climb in difficulty. Math is domain-mixed, roughly ascending in difficulty, with the grid-in questions at the end. None of that is described by the API; I worked it out from the metadata and from sitting the test.

It matters more than it sounds. Most students navigate a module by position: skip ahead to the grammar questions, answer those first, come back for the vocabulary. If the order is wrong, the app trains a strategy that doesn't transfer. The first version sorted only by difficulty, and the person who noticed was me, using it.

A Reading and Writing question in the split-pane layout with passage on the left
Reading and Writing: passage left, question right, with the answer eliminator in the corner.

Math questions arrive as MathML and their figures as inline SVG rather than images, which is what lets the whole thing keep working with no connection.

A Math question with a coordinate-plane figure and multiple choice options
Math: the reference sheet and calculator sit in the top bar, as they do in Bluebook.

Hosting

The whole site is static, so it runs on GitHub Pages for nothing: about 73 KB of files, no server process, no database, nothing to scale. The domain is registered through Cloudflare at cost, roughly $10 a year, which I pay myself and which is the entire running cost of the project.

Cloudflare provides DNS only — the apex points straight at GitHub's addresses with proxying deliberately turned off. Routing the traffic through Cloudflare instead would stop GitHub from issuing the HTTPS certificate for the domain, which is a surprisingly easy way to break a working deployment.

Results

The app deliberately does not produce a score out of 1600. The question bank is a flat pool — not adaptive, not equated against a real form — so any scaled number would be invented, and an invented score is worse than none when you are deciding what to revise. It reports raw score and a breakdown by domain, skill and difficulty instead, then every question missed with College Board's own explanation.

Results screen showing raw score and per-domain and per-skill breakdowns
What you get instead of a 1600 scale score.

Key numbers

What I learned

The engineering lesson is that the constraints produced the design. "I must not redistribute their content" is what forced the fetch-in-the-browser architecture, and that in turn gave the app its hosting cost, its privacy properties and its offline behaviour for free. The requirement I would have treated as an obstacle was the thing that made the design good.

The other lesson is about testing. The worst bug in the project was a MathML element that was dropped from the current standard, so Chrome and Safari render nothing for it at all — no error, no fallback. College Board's content still uses it for brackets, in 44% of the math questions, so V(x) = 11x(x - 1) displayed as Vx = 11xx - 1 and the question became unanswerable while still looking like a question. The automated checks all passed, because they verified that the math rendered and never that it rendered correctly. That one, a wrong question order, and a timer that trapped you in a dialog loop when it expired were all found by using the app for its actual purpose rather than by the tests I had written.

On authorship: a good part of the code was written with an AI assistant. I decided what it should do, tested it, found the bugs above, and made the calls that shaped it — excluding the active questions, refusing the fake score, keeping the questions off my own server. That is where the actual work is.

Links

Not affiliated with, endorsed by, or connected to College Board. SAT and Bluebook are their trademarks, used here to describe what the tool is for.