DEETNUTS is a Next.js application for publishing MHT-CET college and admissions data in a searchable format. The repository contains the web application, data-access layer, upload utilities, and migration tools for MHT-CET datasets.
Live properties:
The current codebase covers the following data domains:
| Domain | Coverage in Repository | Notes |
|---|---|---|
| MHT-CET state cutoffs | 2024 rounds 1-3, 2025 rounds 1-4, 2026 round 1 | Profile-aware cutoffs derived from official CAP data |
| MHT-CET all-India cutoffs | 2024 rounds 1-3 | API handlers exist for all three rounds |
| MHT-CET seat matrix | 2024 | Batch-ingested from CSV |
| MHT-CET college master data | 2024 | Used for directory and detail pages |
Runtime architecture:
- Next.js 16.3.7 with the App Router
- React 19.2.8 with React Compiler enabled
- TypeScript across application and scripts
- Self-hosted PocketBase for auth, application data, and private avatar storage
- PocketBase publishes no host port. Its optional production administration route is proxied through Cloudflare Access, per-host origin mTLS, Nginx and an origin-side JWT/audience/email verifier.
- Standalone Docker build for deployment
High-level flow:
Browser
-> Next.js App Router pages and route handlers
-> lib/* data access helpers
-> PocketBase Auth / collections
CSV / JSON source files
-> scripts/* ingestion utilities
-> PocketBase SDK
-> PocketBase collections
For a full system description, see docs/ARCHITECTURE.md.
deetnuts/
├── app/ # App Router routes, layouts, loading states, API handlers
├── components/ # Shared UI components and feature-specific presentation
├── data/ # Checked-in supporting data files used by the app and imports
├── docs/ # Maintained technical and operational documentation
├── ejam/ # Vendored eJAM predictor runtime and verified release data
├── lib/ # Data clients, auth helpers, metadata, and utilities
├── public/ # Static assets
├── scripts/ # Data ingestion, migration, and maintenance scripts
├── pocketbase/ # Pinned image, hooks, migrations, and one-time migration image
├── supabase/ # Historical source schema retained for migration provenance
└── utils/ # Supporting utility modules
Prerequisites:
- Node.js 22 or newer is the recommended version for the checked-in Docker build
- npm
Install and start the app:
git clone https://github.com/kewonit/deetnuts
cd deetnuts
npm ci
npm exec --yes --package=pnpm@11.1.3 -- pnpm --dir ejam install --frozen-lockfile
cp .env.example .env.local
npm run devOpen http://localhost:3000 after the dev server starts.
The application runtime uses private PocketBase service credentials. At minimum, provide:
NEXT_PUBLIC_APP_URL=http://localhost:3000
POCKETBASE_INTERNAL_URL=http://127.0.0.1:8090
POCKETBASE_SERVICE_EMAIL=backend@example.com
POCKETBASE_SERVICE_PASSWORD=32-to-72-random-characters
AUTH_STATE_SECRET=at-least-32-random-charactersNotes:
- The browser never receives PocketBase administrator or service credentials.
- Supabase variables are accepted only by the explicit one-time source migration. They must not appear in the application runtime environment.
- Most
scripts/entrypoints load.env. The web app uses the standard Next.js.env.localflow. If you run a CLI utility directly, keep the required values in your shell or a local.envfile.
Common commands:
npm run dev
npm run build
npm run start
npm run lint
npm run typecheck
npm run test:platform
npm run formatDeployment operations are documented in deploy/README.md.
The JEE Main and JEE Advanced predictor uses the eJAM workspace under ejam/,
including predictor/data source modules, verified release data, shared UI
tooling, and upstream licence and attribution files. The root production build
uses the workspace's Tailwind toolchain to generate public/ejam/ui.css.
Install both the root npm dependencies and the frozen eJAM pnpm dependencies
before building. Production CI and the Docker image use the same two lockfiles.
The checked-in MHT-CET eligibility-map generator reads eJAM reference data from this in-repository runtime rather than relying on a sibling checkout.
The repository is configured for a private, standalone Next.js container deployment on DigitalOcean.
next.config.mjsenables standalone output, version-skew protection, React Compiler, scoped caching, and production security headers. On-demand prerenders use a release-scoped persistent cache inside the dedicated.next/cachevolume while the image filesystem stays read-only.Dockerfilebuilds and runs the standalone server as a non-root user on a digest-pinned Node 22 Alpine image.docker-compose.ymldefines blue/green web slots, private-network PocketBase, an Access JWT verifier, an unprivileged Nginx origin, and a disabled Reddit-worker profile..github/workflows/production.yamlverifies the application, publishes private attested image digests, scans them, and invokes the restricted deployment command.deploy/README.mddocuments the host layout, backups, one-time source migration, and external DigitalOcean, Cloudflare, Google OAuth, and GHCR configuration.docs/PROTECTED_POCKETBASE_API.mdis the guarded, costed rollout and recovery runbook forapi.deetnuts.com.
The repository contains the complete Supabase-to-PocketBase migration path:
lib/pocketbaseClient.tsis the private service adapter used by runtime data access.- Upload and maintenance scripts use the official PocketBase SDK.
scripts/migrate-supabase-to-pocketbase.tstakes a read-only repeatable snapshot, imports auth/data/storage, verifies exact counts and digests, configures Google OAuth, and creates a pre-cutover backup.- The source Supabase project is rollback-only after cutover and is not a runtime dependency.
Run the migration only through deploy/bin/deetnuts-pocketbase-migrate. The command controls the temporary import hook. It disables batch migration features when verification finishes.
Feature-local documentation is also available in: