Inspiration

We spent the last 30 days not writing code but sitting in the back offices of local coaching institutes in tier-2 India the ones preparing 200 to 500 students at a time for JEE and NEET, ₹2,500 a month, one director, four teachers, no engineer.

Every one of them told us a version of the same thing. Allen, Aakash, FIITJEE and PW are big coaching opening branches in their city. They win on infrastructure: weekly mocks, instant percentiles, and analytics that tell a teacher which student is about to slide two rank bands. A local institute runs its test on photocopied paper, hands back a score two weeks later, and tells the student to "practice more."

Then we noticed the thing that turned this from a wish into a business. Every institute already owned the content. Thousands of questions, their own faculty's papers, decades of PYQs, purchased test series sitting as PDFs on a laptop, completely dead. The asset was there. The engine to run it was not.

So Classphere is not a student app. It is B2B: the white-labelled testing and analysis engine that a 300-student institute rents so it can operate like a 3,000-student coachings. Their logo, their subdomain, their brand. Nobody sees ours.

What it does

1. A question PDF becomes a live computer-based test.

The institute's Test Head uploads their PDF. Gemini reads it page by page and returns structured questions including stems, options, LaTeX math, diagrams, answer keys, which the staff reviews and publishes as a real computer based test with the real exam interface, per-student question shuffling, and the paper's own marking scheme. What used to be a week of typing is a review pass over a coffee.

This became the wedge we never planned. One institute liked the extraction so much that they are buying only the PDF→JSON pipeline, to feed their own material. We had built a product inside a product.

2. Every attempt comes back as a diagnosis, not a score.

This is the part coaching directors care about, and it is built separately for different exams because their papers, marking and time economics genuinely differ. The engine classifies each answer rather than just marking it:

  • Correct but guessed answered impossibly fast, or flagged for review. Marks you got that you will not get again. No test-series software tells a student this.
  • Free marks questions the student demonstrably knew and lost to a sign error, a misread, or the clock.
  • Attempt strategy reconstructed subject order and time split against the optimal allocation for that exam. "You spent 47% of your paper on Physics."
  • Longitudinal flags "you have failed Carnot Cycle in four consecutive tests. That is not a revision gap, that is a teacher problem."
  • Behavioral read accuracy per 30-minute bucket, the fatigue curve, panic cascades after a hard question.
  • An exam-date-aware study plan 90 days out is a conceptual rebuild; 14 days out is crisis triage: fix the silly errors, touch no new theory.

3. The booster test closes the loop.

From that analysis the platform auto-assembles a private practice paper drawn from exactly the topics the student got wrong, excluding questions they have already seen. Analysis that ends in a PDF report gets read once. Analysis that ends in a test gets done.

Around this sits the boring, essential half: multi-tenant institute portals isolated at the database level, batches and roster CSV import, faculty and Test Department roles, DPPs, PYQ browsing, spaced revision, mistake notebooks, batch-level dashboards for teachers, leaderboards, billing, and an Android build from the same codebase.

How we built it

A Turborepo monorepo: Next.js 16 web app (multi-tenant via a [domain] segment and middleware), an Express + TypeScript API split into 20 domain modules, Supabase Postgres with Row Level Security so a bug in our own code still cannot leak Institute A's data to Institute B, BullMQ on Upstash Redis for anything slow, Cloudflare R2 for assets, and Capacitor for the Android app.

The extraction pipeline is the piece we are proudest of, and it is deliberately not "send the PDF to an LLM and hope":

  1. document_profile.py classifies every page, digital or scanned, column count, and page role. Answer-key and worked-solution pages are excluded before extraction begins.
  2. pymupdf_extractor.py renders each page and emits geometry-annotated HTML carrying question-number anchors.
  3. gemini_page_extractor.py sends Gemini the page image, the next page's image (so a question split across a page break survives) and that HTML, in bounded parallel batches.
  4. question_reconciler.py checks what came back against the anchors and re-asks any page that returned fewer questions than the page provably contains.
  5. question_verification.py scores each extracted question's wording against the text PyMuPDF actually read off that page. Uncertain regions keep a source crop and a review reason instead of shipping confident garbage.

Then a human, the institute's Test Head, reviews and publishes. That handoff is the product's spine: AI does the labor, staff owns the paper.

Challenges we ran into

An invented question is perfectly well-formed. Our first validator checked structure: four options, an answer key, balanced $ for LaTeX. A hallucinated question passes that gate every time, cheerfully. We had to add a second, independent axis source fidelity: does this question's text actually appear on the page it claims to come from. The parser became an auditor. That single reframing is what makes the output trustworthy enough to sell.

Phantom questions from the answer key. A paper came back with 79 questions instead of 75. The solution pages at the back were numbered too, so their numbering produced question anchors and the reconciler dutifully created a blank slot for each. Fixed by making page-role profiling unconditional and we deleted the feature flag that could switch it off, because "off" silently lost capability rather than falling back to something simpler.

Choosing the model on evidence, not vibes. We ran Gemini 2.5 Flash and Gemini 3.1 Flash Lite side by side on a real 180-question NEET paper. Completeness tied at 180/180. But on the one question we checked against the printed page, 2.5 Flash had swapped options B and D a silently wrong answer key, the worst possible failure mode for a testing product. 3.1 Flash Lite matched the source exactly and cost less. We switched, and kept the override in place.

Scoring that guessed. We shipped scoring hardcoded to +4/−1, because that is JEE Main. Then an institute uploaded a paper with its own marking scheme and the percentages were quietly wrong for everyone. Now the Test Head sets duration and marks, the paper carries them, and the analysis reports the paper's marks instead of re-deriving them.

A long tail of unglamorous truth. A global 1MB JSON body parser was the real reason bulk uploads failed, we had raised the upload limit four times chasing the wrong number. A 500-question cap buried inside a database function. Diagrams moved to client-side R2 upload instead of inflating the request. A weekly leaderboard that counted clicks rather than correct answers, so guessing 180 questions beat solving 120. One student enrolled in two batches drew exam codes from both cohorts. Every one of these was found by real institutes using the thing on real papers.

Accomplishments that we're proud of

  • Paying institutes, not pilot users. Three coaching institutes signed in 30 days of ground work and one of them is buying the PDF→JSON extraction as a standalone product, which is the clearest validation we could have asked for.
  • An extraction pipeline that admits what it doesn't know. 180/180 questions on a real NEET paper, with per-question source-fidelity scoring, and a source crop plus a review reason wherever confidence is low. It never ships a wrong answer key as if it were right.
  • A diagnosis no competitor gives. "You got six of these correct by luck, and in the real exam that luck runs out" is the single most human thing a teacher says over a paper and as far as we know, we are the only platform that says it automatically.
  • 779 commits in about ten weeks, from empty repo to production, running live institute traffic with the work log recording the bugs we shipped, not just the features.

What we learned

  • The wedge is rarely the vision. We set out to sell analysis. The first thing anyone reached for a wallet over was PDF→JSON. Listen to what customers try to buy, not to what you meant to sell.
  • Ground beats outreach. Three paying institutes came from sitting in their offices, not from cold email. The demo that closes is opening their own PDF in front of them and having a working CBT before the tea arrives.
  • AI needs an auditor, not a bigger prompt. Every meaningful reliability gain we made came from deterministic machinery around the model anchors, reconciliation, page-role profiling, source-fidelity scoring, not from better prompting.
  • Ship the honest gap. Scanned PDFs are rejected outright today rather than silently mangled, and we tell institutes that to their face. It costs us deals and buys us trust.

What's next for Classphere

OCR, so scanned and photocopied papers stop being a hard no, it is the single biggest limit on selling extraction as a service, and the most common thing an institute has on its laptop. Extraction priced and sold as its own product, since a customer already asked for it that way. Then SSC and GATE exams, which need the same engine and a different marking model. And underneath all of it, the metric we actually care about: a 200-student institute in Indore putting a student in the national top 500 and being able to show exactly which feedback loop got them there.

Built With

Share this project:

Updates