Case study · Independent · Civic technology
Modeling government and geography in Civic Maps
A map-first way to answer "who governs this place?" PostGIS boundaries for all 50 states, current federal and state officeholders, and a Next.js site over a 3D globe.
- Role
- Sole developer
- Period
- 2026 to present
- Status
- Live at civicmapshq.com, in active development

Civic Maps is built on a fork of God's Eye View, an open-source 3D globe by Bilawal Sidhu. The globe and its rendering are God's Eye View. The political data model, database, API, ingest, and website are mine.
Overview
Click a point on the map or search an address, and Civic Maps lists the federal and state offices that cover that place. State pages list the governor, both legislative chambers, and each U.S. House district. Each official's page names the office, the party on the record, and the public source.
Problem
Government data is public but scattered. District boundaries come from the Census Bureau, legislators from Congress.gov and Open States, and federal judges from the Federal Judicial Center. Each source uses its own identifiers, and none of them answers the question for a point on a map.
Constraints
- Official sources only, with provenance on every record.
- Public offices only. No private-person tracking.
- The globe is a fork I want to keep merging from upstream, so my code can't spread through it.
- Mobile gets its own layout built around a bottom sheet.
Architecture and technical decisions
- The political core is isolated. The domain model, API, ingest, and backend never import the globe or Cesium, and a check script fails the build if they do.
- PostGIS is the system of record. Records use canonical text IDs such as cm:jurisdiction:us.wa. Source identifiers like Census GEOIDs live on provenance records.
- Containment is a relations table, because a place sits inside several overlapping jurisdictions at once.
- Geometry belongs to a versioned Boundary, so a district keeps its identity when it's redrawn.
- The website is Next.js. It embeds the globe in an iframe and talks to it over a postMessage protocol, and it calls the Civic Maps HTTP API for officeholders.
- Coverage grows by adding ingest adapters and jurisdiction rows, with no changes to the globe.
My contributions
- Designed the domain model: jurisdictions, districts, versioned boundaries, offices, people, terms, legislative bodies, bills, votes, and elections.
- Wrote the PostGIS schema and the HTTP API for point lookup, boundaries, geography, people, roster, and search.
- Built ingest for Census TIGERweb geography in all 50 states, current Congress members, governors, and state legislators from Congress.gov and Open States, and federal district and circuit judges from the FJC directory.
- Added the government layer to the globe and built the Next.js site, including state pages and search by name or district code.
Challenges and tradeoffs
Keeping a fork mergeable means accepting limits. Civic Maps touches only five upstream files, on purpose, and everything else lives in its own directory. That constrains how far it can change the globe, which is the point.
Some state chambers have fewer stored seats than the Census lists. The site shows who is stored and doesn't invent the missing seats.
The globe is a static build and PostGIS isn't, so the globe and the API are deployed separately.
Outcomes
- Live at www.civicmapshq.com, with the globe at map.civicmapshq.com.
- Census geography for all 50 states, plus current federal and state officeholders and federal judges.
- Search opens an official by name or a district by code, such as WA-7.
- Elections, bills, and state high courts are modeled in the domain but not yet in the API or site. They're the next milestones.
Technologies
- TypeScript
- Next.js
- React
- PostgreSQL 16
- PostGIS
- Docker Compose
- CesiumJS
- Vite
- Node.js