Inspiration
Every scholarship season, students are asked to prove the same facts over and over: GPA above a threshold, income below a limit, active enrollment. They upload transcripts, bank statements, and IDs. Providers receive far more than they need, and students lose control of data they can never take back.
That gap inspired ScholarProof. Our tagline is simple:
Prove you're qualified. Don't reveal why.
We wanted a flow where a student can show a provider ELIGIBLE or NOT ELIGIBLE without handing over the underlying numbers. With Midnight live on mainnet, we could finally put that idea on a production privacy network, not as a slide deck, but as a working app.
What we learned
Building on Midnight taught us that privacy is a system design problem, not a single feature.
We learned how to separate:
- Private witnesses: GPA, income, age, years completed, enrollment (never disclosed on-ledger)
- Public policy: thresholds like $\text{GPA} \geq 3.5$, $\text{income} < \$5{,}000$, $\text{age} < 25$
In Compact, eligibility becomes a circuit of assertions:
$$ \text{eligible} \iff (\text{gpa} \geq g_{\min}) \land (\text{income} < I_{\max}) \land (\text{age} < A_{\max}) \land (\text{years} \geq Y_{\min}) \land (\text{enrolled}) $$
We also learned where AI should not be the trust layer. An LLM can help interpret natural-language scholarship requirements into structured policies, but eligibility must be decided by a deterministic engine plus cryptographic verification, not by model output.
Finally, we learned the practical Midnight stack: Compact contracts, the TypeScript SDK, proof-server integration, and graceful fallback modes when the full compiler pipeline isn't available locally.
How we built it
ScholarProof is a full-stack monorepo with a clear privacy boundary:
Student credentials (private) + Scholarship policy ↓ AI extracts requirements → validated JSON schema ↓ Deterministic eligibility engine (Django) ↓ Midnight proof service (TypeScript) + proof server ↓ Application stores proof_reference only ↓ Provider sees ELIGIBLE / requirement verification, not raw values
Frontend: React, TypeScript, Vite, Tailwind Role-based dashboards for students, providers, and university issuers, plus a Privacy Demo with before/after comparison.
Backend: Django + DRF (Python 3.12 via uv) JWT auth, scholarship policies, credential storage, eligibility checks, and strict API permissions so providers never receive sensitive payloads.
Midnight layer: Compact + TypeScript
scholarproof-eligibility.compact defines private witnesses and public thresholds. Our proof service generates and verifies commitments and proofs via the Midnight SDK and optional proof server.
Demo data: Seeded student SP-1042 with GPA 3.82, income $4,500, age 22, against scholarships like Future Leaders (eligible) and Academic Excellence ($\text{GPA} \geq 3.9$, not eligible).
Before vs. after (Integrate Midnight track)
| Before | After |
|---|---|
| Student uploads transcripts and income docs | Student holds credentials privately |
| Provider sees full sensitive records | Provider sees VERIFIED ✓ per requirement |
| Privacy risk on every application | Only proof reference and boolean result shared |
Challenges we faced
Compact toolchain setup: Getting compact installed, running compact update, and compiling circuits was a real onboarding hurdle. We documented the full path and built fallback modes (LOCAL_COMMITMENT / MIDNIGHT_PARTIAL) so the demo still works before full circuit compilation.
Privacy at every API boundary: It wasn't enough to hide fields in the UI. We enforced student-only credential endpoints, provider serializers that exclude payloads, and stored only proof_reference on applications, not GPA or income.
AI without trusting AI: Scholarship text is messy. We used LLM extraction with strict Pydantic validation, but the eligibility engine and Midnight layer remain the authority. The UI explicitly states: "AI is not the trust authority."
End-to-end demo reliability: Small bugs broke the story: paginated API responses crashing the student dashboard, auth races after login, and Decimal serialization when calling the Midnight service. Fixing those made the hackathon demo path stable from login, to eligibility check, to proof generation, to provider verification.
Making privacy visible: ZK proofs are powerful but invisible. We added step-by-step proof generation UI, per-requirement VERIFIED badges, and a Privacy Demo page so judges can see what stayed private.
Why Midnight
Scholarship eligibility is exactly the kind of problem Midnight was built for: selective disclosure of a boolean outcome without leaking the underlying attributes. ScholarProof isn't "blockchain for scholarships." It's privacy infrastructure for real-world credential checks, deployed on a live mainnet network during a hackathon where privacy actually matters.
Prove you're qualified. Don't reveal why.
Built With
- auth
- compact
- django
- drf
- jwt
- python
- react
- tailwind
- typescript
- vite

Log in or sign up for Devpost to join the conversation.