Inspiration
Voting systems—whether in organizations, communities, or even small businesses—often lack transparency and verifiability. Traditional systems can be manipulated, altered, or disputed, and users have no cryptographic proof that their vote was recorded correctly.
We wanted to build a system where every vote is verifiable, immutable, and recoverable, combining blockchain, decentralized storage, and modern web UX into a single flow.
What it does
ClearVote is a verifiable voting platform where:
Users connect a wallet and cast a vote Each vote is minted as an NFT on Solana Vote data is stored in MongoDB for fast querying Images and metadata are stored on IPFS via Pinata Users receive an optional email receipt via a microservice on Vultr A moderator-only dashboard allows full audit and verification
Even if the database is wiped, votes can be recovered from on-chain NFT metadata, making the system resilient and tamper-proof.
How we built it
Frontend Next.js (App Router) Wallet connection using Phantom Voting UI with image-based candidates Confirmation page with NFT + email flow
Backend (Web App) API routes in Next.js
MongoDB for: polls collection votes collection (source of truth) Vote casting logic + NFT mint orchestration
Blockchain Layer NFT minting via Metaplex on Solana Each vote = 1 NFT containing: pollId option selected voter wallet timestamp
Storage Images + metadata uploaded to IPFS via Pinata
Microservice (Infra) FastAPI service deployed on Vultr Handles SMTP email delivery Sends vote receipt with: image metadata link explorer link
MLH Track - Solana
We used Solana to:
Mint each vote as an NFT Ensure immutability and public verifiability Allow recovery of vote data even if off-chain systems fail
Each vote becomes a cryptographic proof of participation.
MLH Track - Vultr
We deployed a dedicated FastAPI microservice on Vultr to:
Handle SMTP email delivery Keep infrastructure modular and scalable Demonstrate real-world production architecture
NEXT_PUBLIC_EMAIL_SERVICE_URL=http://45.63.65.146:8000
The backend endpoint is provided by Vultr
This separation shows how blockchain apps integrate with traditional backend systems.
MLH Track - MongoDB
We used MongoDB to:
Store poll definitions Store vote records and NFT metadata Power real-time results and dashboards
We intentionally designed MongoDB as a cache layer, with blockchain as the ultimate source of truth.
Challenges we ran into
Handling NFT metadata correctly (image vs metadata URI confusion) Wallet rendering issues and IPFS gateway compatibility Keeping MongoDB counters consistent with actual vote records Managing async flow: vote → mint → store → email Docker + dependency issues on Vultr (containerd conflicts) CORS + cross-origin calls between frontend and microservice
Accomplishments that we're proud of
Fully working end-to-end flow: Vote → NFT → Mongo → Email receipt Recovery-ready architecture using blockchain metadata Clean UX with wallet + image-based voting Moderator-only verification dashboard Production-style microservice deployed on cloud infra
What we learned
How NFT metadata structure affects rendering across wallets Importance of separating: source of truth (blockchain) query layer (database) How to deploy and debug Docker services on cloud VMs How to integrate Web3 + Web2 systems in a real application Designing systems for data recovery and auditability
What's next for ClearVote
On-chain vote verification without relying on backend ZK-proof voting for privacy-preserving elections Multi-poll governance system (DAO-style) Mobile-friendly voting + QR code sharing Email receipts with embedded NFT previews Role-based access control (admin / auditor / use
Built With
- mongodb
- nextjs
- pinata
- solana
- typescript
- vultr
Log in or sign up for Devpost to join the conversation.