MGNREGA Portal
A full-stack government-data portal that ingests district-level MGNREGA statistics from India's data.gov.in Open API, caches them in Postgres, and surfaces them through interactive charts, side-by-side comparisons, and a bilingual AI assistant — built to make rural-employment data readable even for low-literacy users.
Context
MGNREGA — India’s rural employment guarantee scheme — publishes a lot of performance data: employment, wages, works completed, social-inclusion metrics by district. It’s technically public and practically unusable: scattered, rate-limited, and shaped for machines, not citizens.
The portal aggregates and caches that data locally, then presents district-level insight with visualizations, comparisons, and plain-language explanations — so a non-technical rural user or a local official can actually read it.
Getting the data in
The government Open API is rate-limited and paginated, so I couldn’t hit it live per request. A batched scraper service (batch size 100, retry with backoff) pulls the district resource and persists it to Postgres via Prisma — a local caching layer that both dodges the rate limit and keeps the site up when the source API isn’t.
node-cron jobs keep it fresh: a daily incremental sync and a weekly full historical pass, with every run recorded in a SyncLog table so you can see exactly what landed and when.
Making it readable
The front end is a React + Recharts dashboard: historical trend charts, a comparison page for up to four districts side by side with CSV/Excel export, and rankings by a selectable metric. Everything is bilingual (English / Hindi) with short “how to read this chart” notes for low-literacy users.
A Gemini 2.5-flashassistant sits on top — it explains MGNREGA, analyses a district’s numbers in plain language, and detects navigation intent so “show me Rajkot” actually routes there. Geolocation auto-detects the visitor’s district to skip the search entirely.
Decisions & tradeoffs
- Cache locally, don’t proxy. Mirroring the data into Postgres was the only way to get interactive charts on a rate-limited source without the whole UI stalling.
- Gemini for language, not numbers. The assistant explains and navigates; the figures it quotes come from the cached dataset, not from the model.
- Bilingual from the start. The audience is rural and often Hindi-first — English-only would have defeated the point of making the data accessible.
What I would change
The sync is state-scoped and defaults narrow; I’d generalise the ingestion to cover all states out of the box and add a proper freshness indicator per district. And the assistant’s navigation intent is rule-plus-model today — I’d ground it against the actual district list so it can never route somewhere that isn’t in the cache.