projects/Pulpulitiko
A civic transparency platform for the Philippines that ties politicians to debt, loans, asset disclosures and polls, with an AI-ready API so assistants can query it directly.

The problem. Political information in the Philippines is scattered across news sites, government PDFs and spreadsheets. Voters have no single place to see how a politician connects to national debt, foreign loans, asset disclosures (SALN) or confidential funds.
What I built. Pulpulitiko, a platform that puts politicians at the center and links them to presidential administrations from 1965 to today, sovereign debt records, foreign loan events, SALN filings and confidential and intelligence funds. It also includes discussion threads, verified polls, voter education and a "My Representatives" finder. The backend is written in Go with a Nuxt frontend.
The result. A live, searchable civic database. I also built in an MCP server (with OAuth 2.0 and API-key security) so AI assistants can query political finances, bills and debt data in a structured way instead of scraping pages.
Key architectural decisions, concrete code implementations, and performance wins behind this project.
Click any node below to inspect its role, tech stack, and engineering implementation.
Server-side rendered bilingual interface with responsive dark mode and instant navigation.
Engineering Highlights:
Political reporting platforms typically treat politicians as shallow text tags, detaching elected officials from systemic debt, foreign loan obligations, and fiscal records incurred during their terms.
Refactored the relational schema to anchor the database around politicians as the central entity, enforcing foreign key relationships and indexation across sovereign debt servicing records (1965–present), foreign loan events, and yearly asset disclosures.
Investigative articles often discuss combinations of diverse civic entities (a politician, a bilateral loan package, and a sovereign debt record) without an efficient, non-breaking way to model arbitrary relational bonds.
Built a polymorphic linking table with composite unique constraints and dual B-tree indexes, allowing editorial content to bind dynamically to any entity type while preventing duplicate references.
Modern external AI agents (like Claude or custom research agents) need programmatic, secure, and structured real-time access to the platform's civic database without scraping HTML or bypassing authentication.
Embedded a native Go MCP server using mark3labs/mcp-go featuring 19 modular tool registries, supporting both stdio and HTTP transports with RFC-compliant OAuth 2.0 and API-key security.
User-generated comments and rich political articles could become vectors for XSS attacks and ReDoS exploits when embedding third-party media or social iframes.
Implemented a strict Go Bluemonday sanitization policy that constrains CSS classes, enforces length limits against DoS attacks, and restricts iframes strictly to approved domains before database persistence.
Static robots.txt configurations risk exposing non-production staging environments to web crawlers or indexing incorrect localhost domain origins in sitemaps.
Built a server-rendered Nuxt 3 route handler that dynamically injects runtime site URLs into sitemap directives, applies 24-hour edge caching headers, and blocks crawlers from admin and authentication routes.
// community_discussion
Have thoughts, questions, or ideas regarding this system's architecture? Leave a comment below with your GitHub account.