GovernancePulse
What Inspired Us
Local governments often promise roads, drainage, streetlights, and sanitation. Updates scatter across speeches, newsletters, and news. Citizens rarely have a single place to see what was pledged, what’s in progress, and what’s done.
We wanted a system where:
- Every pledge is visible and traceable
- Evidence can’t be changed or hidden
- Citizens can vote on progress in a transparent way
GovernancePulse started as an experiment: combine AI, decentralized storage, and blockchain to turn messy, unstructured documents into clear, verifiable records of government commitments.
What We Learned
AI for Governance Content
Using Google Gemini to classify documents taught us how to work with governance language. Promises, progress reports, and irrelevant content need different handling. We designed prompts focused on infrastructure and public service, then iterated until the model reliably distinguished new pledges, updates, and unrelated content.
Blockchain Beyond Tokens
Blockchain here isn’t about tokens or speculation. It’s about immutability and transparency. Once a pledge or vote is recorded, it stays on the chain. That gives a permanent, auditable history that can’t be altered after the fact.
IPFS for Evidence
IPFS (via Pinata) gave us decentralized, content-addressed storage. Each document gets a CID: a hash-based identifier that guarantees the content. Anyone can check that the evidence hasn’t changed. This fits well with the idea of immutable proof for pledges.
MongoDB for Structured Pledge Data
We used MongoDB with Mongoose to store pledges, artifacts, trigger events, review rounds, and votes. We learned to design schemas that work with both Mongoose and the blockchain: MongoDB holds rich, queryable data (text, relations, metadata), while the chain stores hashes and IDs for verification. We also had to ensure only plain, serializable objects are passed from Server Components to Client Components—Mongoose documents and populated refs had to be mapped to plain objects with .lean() and explicit field selection to avoid serialization errors in Next.js.
Serverless and Real-Time UX
Building on Vercel meant dealing with read-only filesystems, cold starts, and dynamic rendering. We learned how to use /tmp for uploads, call connectDB() before any DB access, and make PDF parsing work in serverless. We also used Server-Sent Events for real-time pipeline updates instead of polling.
Core Components
Artifact ingestion — A folder watcher process files from
artifacts/incoming. Later, we plan to scrape local news and government sites by location.AI classification — Gemini 2.5 Flash classifies each document as
NEW_PROMISE,PROMISE_UPDATE, orIRRELEVANT, and extracts promise text, category, and region.IPFS storage — Pinata stores each document on IPFS and returns a CID. Evidence links in the app point to these immutable references.
Smart contract — A Solidity contract on Polygon Amoy records pledges, evidence, and review rounds. Citizens vote with
castVote(); status is computed from votes and written withupdateStatus().Vote-to-status logic — Final status comes from vote distribution. For a round with vote counts (v_0, v_1, v_2, v_3) (Not Visible, In Progress, Partially Done, Done), the winning option is:
[ \text{status} = \arg\max_{i \in {0,1,2,3}} v_i ]
Ties are broken by a fixed precedence (e.g., Done > Partially Done > In Progress).
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, Tailwind CSS 4 |
| Backend | Next.js API Routes (serverless) |
| Database | MongoDB, Mongoose |
| AI | Google Gemini 2.5 Flash |
| Storage | Pinata (IPFS) |
| Blockchain | Polygon Amoy, Solidity, Viem |
Challenges We Faced
1. PDF Parsing in Serverless
pdf-parse depends on pdfjs-dist, which expects canvas and DOM APIs. On Vercel, we saw DOMMatrix is not defined and @napi-rs/canvas missing. We solved this by:
- Adding
@napi-rs/canvasand listing it inserverExternalPackages - Dynamically importing
pdf-parseonly when handling PDFs - Providing clear errors if PDF parsing fails (e.g., suggest using
.txtor.md)
2. Self-Referential Fetch on Vercel
The dashboard originally fetched data from the app’s own API (/api/promises, etc.). On Vercel, that meant requests to localhost:3000, which wasn’t available. We refactored to call the database directly in Server Components and removed the need for NEXT_PUBLIC_APP_URL.
3. Read-Only Filesystem on Vercel
artifacts/uploaded couldn’t be created because /var/task is read-only. We switched uploads to /tmp when VERCEL is set and made file moves a no-op in serverless, since /tmp is ephemeral.
4. Mongoose Buffering Timeout
The upload route used Mongoose models without calling connectDB() first. Mongoose buffered operations and eventually timed out. Adding connectDB() before any DB access fixed this.
5. Non-Serializable Props (Server → Client)
Populated Mongoose refs (e.g. sourceArtifact) and Set objects caused serialization errors when passed to Client Components. We fixed this by mapping results to plain objects and avoiding passing complex Mongoose documents or non-serializable types across the server–client boundary.
6. Hydration Mismatch from Browser Extensions
Extensions like Grammarly add attributes to <body>, which led to hydration mismatches. We used suppressHydrationWarning on html and body to avoid these false positives.
Vision for the Future
MVP today: Manual artifact upload for demo, AI classification, IPFS storage, blockchain records, and citizen voting.
Next: Automatic scraping from local newspapers and government sites based on the user’s selected location. The location selector will drive which sources are monitored and ingested.
Long term: Broader sources, RSS feeds, official press releases, and more real-time monitoring to make GovernancePulse a continuous, location-aware accountability layer for local government.
Conclusion
GovernancePulse shows how AI, decentralized storage, and blockchain can support civic accountability. Every pledge is traceable, every piece of evidence is immutable, and citizens can participate in tracking progress. We learned to work around serverless constraints, design reliable AI pipelines, and use blockchain for auditability rather than speculation. The result is a working platform at govpls.vercel.app that we’re ready to extend with automatic, location-based data ingestion.
Built With
- google-gemini-api
- mongodb
- mongoose
- next.js-16
- pinata-(ipfs)
- polygon-amoy
- react-19
- solidity
- tailwind-css
- typescript
- viem

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