Predict your admission chances into NITs, IIITs, and GFTIs based on JoSAA and CSAB counseling data from 2024. Enter your JEE Main rank, apply filters, build a preference wishlist with personal notes, and export everything as a PDF or text file — ready for actual choice filling.
Live: jee.qzz.io
You enter your JEE rank, category, gender, and home state. The predictor queries a database of ~76,000 historical cutoff entries across 128 institutes and 229+ programs, then classifies each match as High, Medium, or Low probability based on how your rank compares to the last year's closing cutoff.
From there you can:
- Filter by college type (NIT/IIIT/GFTI), branch category, degree type, course duration, and state
- Star individual branches or entire colleges into a personal wishlist
- Reorder your wishlist by typing a position number directly (move choice #47 to #3 in one click)
- Add remarks to each choice ("good placements", "too far from home", etc.)
- Export the final list as a
.txtchoice filling sheet or print a formatted PDF
The predictor supports both JoSAA (Round 6 data, includes CRL + Category rank) and CSAB (Round 3 special counseling) flows.
The project has two independently deployable pieces:
├── src/ # Next.js 15 frontend (App Router, static export)
├── api-worker/ # Cloudflare Worker (backend API)
├── data/ # Raw CSV cutoff data for seeding
├── prisma/ # Database schema + migration SQL
└── scripts/ # Seed script to populate DB from CSVs
Built with Next.js 15 using the App Router. Pages are statically exported — no server-side rendering needed at request time. The build is compiled with @cloudflare/next-on-pages and deployed to Cloudflare Pages.
Key libraries: React 19, Framer Motion (animations), Recharts (comparison charts), Lucide icons.
A single Cloudflare Worker that handles prediction requests. It reads from a Cloudflare D1 database (serverless SQLite) containing all institute metadata and cutoff records.
The worker handles quota resolution (Home State vs Other State vs All India), seat type filtering (OPEN, EWS, OBC-NCL, SC, ST), gender-based seat matching, and probability classification.
The predictor doesn't use a fixed ±N rank window. Instead, margins scale relative to the closing cutoff:
High → userRank ≤ closingRank - min(10000, closingRank × 0.10)
Medium → userRank ≤ closingRank + min(5000, closingRank × 0.05)
Low → userRank ≤ closingRank + min(20000, closingRank × 0.20)
This means a college with closing rank 5,000 has tight margins (±500), while one at 80,000 has wider margins (±16,000). This prevents the predictor from showing unrealistic matches at both ends.
The API isn't protected by a static API key (those are trivially extracted from frontend JS bundles). Instead, it uses a time-windowed cryptographic handshake:
Authentication flow:
- The frontend generates a 5-minute time window:
Math.floor(Date.now() / 300000) - It signs the window with HMAC-SHA256 using a shared secret
- The token
<window>.<hex_signature>is sent as a Bearer token - The worker verifies the signature and checks that the window is within ±1 of its own current window (handles clock drift)
Response encryption:
- After authentication, the worker encrypts the JSON response using AES-GCM-256
- The encryption key is derived from the same HMAC(secret, window) used for auth
- The response contains
{ encrypted, iv, window }— just base64-encoded ciphertext - The frontend derives the same AES key and decrypts locally
This means even if someone intercepts the response, they can't read it without knowing the shared secret.
The shared secret is stored as character codes in the frontend (not plaintext) and as a Wrangler secret (API_SECRET_KEY) on the worker. CORS is restricted to specific allowed origins.
- Node.js 18+
- A Cloudflare account (free tier works)
# Install dependencies
npm install
# Set up the local SQLite database
npx prisma db push
# Seed it with cutoff data from the CSVs
npx tsx scripts/seed.ts
# Start the dev server
npm run devThe app runs at http://localhost:3000. During local dev, API calls can hit the remote worker or you can run the worker locally with npx wrangler dev inside api-worker/.
Copy .env.example or create .env:
DATABASE_URL="file:./dev.db"
NEXT_PUBLIC_API_URL="https://your-worker.your-subdomain.workers.dev"
npx wrangler d1 create your-db-nameCopy the database_id from the output into both wrangler.toml files (root and api-worker/).
npx wrangler d1 execute your-db-name --remote --file=prisma/migration.sqlcd api-worker
npm install
npx wrangler secret put API_SECRET_KEY # enter your shared secret
npx wrangler deployUpdate the ALLOWED_ORIGINS array in api-worker/src/index.ts with your actual Pages domain before deploying.
npx @cloudflare/next-on-pages
npx wrangler pages deploy .vercel/output/static --project-name=your-projectSet NEXT_PUBLIC_API_URL in Cloudflare Pages environment variables to point to your deployed worker.
The char codes in src/lib/auth.ts must decode to the exact same string you set as API_SECRET_KEY on the worker. Generate the codes for your secret:
"your_secret_here".split("").map(c => c.charCodeAt(0))
// paste the output into the keyChars arrays in auth.ts| Layer | Technology |
|---|---|
| Frontend framework | Next.js 15 (App Router) |
| UI | React 19, Framer Motion, Recharts |
| Styling | Tailwind CSS 4 + CSS custom properties |
| Database | Cloudflare D1 (SQLite) |
| ORM | Prisma (with D1 adapter) |
| Backend | Cloudflare Workers |
| Crypto | Web Crypto API (HMAC-SHA256, AES-GCM-256) |
| Hosting | Cloudflare Pages |
src/
├── app/
│ ├── page.tsx # Landing page with animated stats
│ ├── josaa/page.tsx # JoSAA predictor page
│ ├── csab/page.tsx # CSAB predictor page
│ └── layout.tsx # Root layout with footer
├── components/
│ └── PredictorPage.tsx # Main predictor UI (form, results, filters, wishlist)
└── lib/
├── auth.ts # Token generation + AES decryption (client-side)
├── branch-mapper.ts # Classifies 100+ program names into categories
├── constants.ts # States, categories, branch keywords, filters
├── institute-state.ts # Maps institute codes → home states
├── institute-subtype.ts # Identifies NIELITs, Central Universities, etc.
└── prediction-engine.ts # Probability classification logic
api-worker/
└── src/
└── index.ts # Worker: auth verification, DB queries, encryption
data/
├── institutes-*.csv # Institute metadata
├── refine_joosa-*.csv # JoSAA Round 6 cutoff data
└── refine_csab_2025-*.csv # CSAB cutoff data
This project is open source. Feel free to fork and adapt it for other counseling systems (WBJEE, MHT-CET, etc).