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

Share this project:

Updates