← Back to Ships
web · completed · 2026-07 → 2026-07

Vigía

Interactive map of Peruvian open-government data: budget, services, payroll and public-works risk

Next.jsReactTypeScriptPostgreSQLSupabaseMapLibre GLPythonTailwind CSS

🏆 2nd Place — Hackathon DSC PUCP · Vibecoding 2026 (organized by @dsc.pucp and @gdgopen).

The Peruvian State manages more than S/ 220 billion a year. Vigía integrates four open-data sources from the State into a single interactive map and answers a question that today has no accessible answer: how is the State performing in your region?

Four layers, one platform

  • 💰 Budget — MEF Consulta Amigable: which regions and ministries fail to execute their allocation?
  • 🏥 Services — MINSA (RENIPRESS) + MINEDU: which districts lack clinics, schools and hospitals?
  • 👥 Payroll — SERVIR / open data: where is public employment concentrated, and which regimes dominate?
  • 🏗️ Public works — OCDS + INFOBRAS + OECE: which projects show risk signals? (explainable 0–100 score)

The user isn’t only the auditor hunting for fraud — it’s the citizen, the NGO, the journalist and the regional planner who need to understand how the State performs as a whole.

Architecture

A medallion lakehouse + analytical Postgres, layered: ingestion decoupled from serving, business logic centralized in the database, a thin API, and a clear server/client boundary in the front end.

Bronze (raw) → Silver (normalized) → Gold (crossed + aggregated) → API → 4-layer map
  • Ingestion (Bronze): Python · requests · BeautifulSoup · pandas · psycopg2 — one adapter per state source
  • Database: PostgreSQL (Supabase) · pg_trgm · materialized views · a SQL scoring function
  • API: Next.js 14 Route Handlers · pg (direct SQL, no ORM)
  • Frontend: Next.js App Router · React 18 · MapLibre GL · Tailwind CSS
  • Deploy: Vercel + Supabase

Learnings

  • Keeping the red-flag scoring in SQL (a compute_red_flag_scores() function plus materialized Gold views) instead of app code lets the Next.js API stay a thin pass-through and makes the scoring auditable in one place
  • A natural-language "Agente Vigía" chat can answer questions over real data with zero LLM cost — intent matching against pre-aggregated Gold views is deterministic, free, and fast enough to feel conversational
  • A Bronze → Silver → Gold medallion layout with one Python adapter per state data source decouples messy scraping/ingestion from a clean analytical serving layer
  • Querying Postgres directly with pg (no ORM) from Next.js route handlers over the Supabase pooler keeps the API trivial when the heavy lifting already lives in materialized views