Inspiration

Most people have no idea who their city council member is, when their
local budget was last voted on, or what that construction crane going up two blocks away actually means for their neighborhood. Civic
information exists: it's just scattered across a dozen different government websites, none of which were designed to be used by regular people on their phones.

We wanted to build the thing that should already exist: a single
address bar you type your home address into, and everything about your neighborhood, your officials, your money, your permits, your district, loads instantly. The name Porch came from the idea that civic life
used to happen on front porches. Neighbors talked. People knew what was going on. We wanted to bring that back, just on a phone.

What it does

Porch is a mobile-first civic dashboard. You type your address and the app detects your city, then loads:

  • Your district map: an interactive map showing your ward or council
    district, with all boundaries and your searched address pinned
  • Who represents you: live data on your state legislators, with their party, recent bills, inferred issue positions, and contact info, sorted by alignment with your stated values
  • What's being built nearby: active building permits within walking
    distance, with plain-English explanations of what the construction
    means and a countdown to the public comment deadline
  • Where your money goes: a tax breakdown showing how your income
    splits across federal, state, and local taxes, plus the top federal
    grants flowing into your city from USASpending.gov
  • What's happening right now: a city-specific pulse feed organized by category (housing, transit, governance, environment, economy) and
    urgent cards for the most time-sensitive local issues
  • How to get involved: nearby food banks, shelters, legal aid, and
    community organizations, plus volunteer opportunities

The app supports two cities with full feature parity: Ithaca, NY and
New York City. City detection is automatic: search any address in
either city and everything switches instantly.

A civic engagement score gamifies participation. Searching your address, reading permit details, clicking on officials, or signing up
to volunteer all earn points toward levels from Observer up to Community Leader.

How we built it

Next.js 14 with the App Router for the full stack: server-side API routes proxy every external service so no keys are ever exposed to the client.

The map is split in two: Ithaca uses a custom SVG projection map we wrote from scratch: it computes a bounding box from the loaded
GeoJSON, projects lat/lng coordinates into SVG space, and renders everything with pan/zoom. NYC uses Leaflet.js with CARTO's free light
tiles as the basemap and district boundaries fetched live from the NYC ArcGIS REST service. We sourced the district label coordinates and all 51 council member names by parsing the official NYC Council map widget's inline JavaScript.

Live data comes from six external APIs: Mapbox for geocoding, Open States v3 for legislators, Census ACS 5-year for neighborhood statistics, USASpending.gov for federal grants, NYC DOB via Socrata for building permits, and Google Places for nearby civic organizations.

The personalization layer runs silently over all content: urgent cards are re-sorted by relevance to your stated issues, aligned officials surface first, and tax breakdowns use your actual income from onboarding. Authentication is NextAuth.js with bcrypt-hashed
credentials and a multi-step onboarding flow that captures issues, party, income bracket, and address.

The visual system uses no external photos: every card background is a purpose-built CSS gradient paired with an inline SVG illustration (10 types total). The civic score bar is fixed above the bottom nav and persists score in localStorage.

Challenges we ran into

Breaking NYC search silently. The original geocoding calls used Mapbox's bbox parameter to keep results near Ithaca. This is a hard geographic filter, not a bias: it silently discarded every NYC address the user typed with no error message. The fix was switching to
proximity (a ranking hint) so Ithaca still wins on ambiguous queries, but any valid US address resolves.

The webpack cache crash. After making several simultaneous file changes, Next.js's compiled module IDs would desync from the cached .next directory. The symptom was a runtime TypeError: webpack_modules[moduleId] is not a function, the page would load
and immediately crash with a server error. It happened multiple times and the only fix is rm -rf .next. No code change resolves it; the build cache just needs to be fully rebuilt.

Leaflet doesn't know it's in a browser. Leaflet accesses window and document on import, which throws during Next.js server-side rendering. The fix required both wrapping the component with dynamic(..., { ssr: false }) and moving the import("leaflet") call inside a useEffect. Even then, Leaflet's default marker icons break under webpack because the paths are resolved at build time — we had to manually override the icon URL resolution to point at CDN-hosted images.

Getting NYC council data. There's no public API for council member names and district label coordinates. We scraped them from the inline JavaScript inside the NYC Council's WordPress widget page, then hardcoded the 51 entries. Stable and fast — but will need a manual
update after future elections.

Re-fetching on city change without over-fetching. The census and federal spending sections need fresh data when you search a different city, but shouldn't re-fetch on every render or every scroll. A boolean started flag was too blunt. The solution was a lastFetchedCity ref — a new fetch only fires when detectedCity !== lastFetchedCity.current.

Accomplishments that we're proud of

Getting two cities to feel like one coherent app rather than two codebases was harder than expected. The CityConfig type in lib/cities.ts encapsulates everything city-specific: district labels, GeoJSON paths, permit API endpoints, pulse items, urgent cards, color
palettes, so the main page component never has a wall of if (city === "nyc") branches. Adding a third city would mean adding one object to
that file.

The SVG ward map for Ithaca is something we're genuinely proud of. It's pure math: no map library, no tiles, no API call. It reads the GeoJSON, computes a bounding box, projects coordinates into a 400×330 SVG viewport, and handles pan and zoom entirely through a transform
matrix. It works offline and loads in milliseconds.

The permit bottom sheet turns a dry municipal record into something a neighbor could actually act on, plain English explanation of what's being built, why it matters across four different angles (housing, transit, environment, economics), a live countdown to the public
comment deadline, and a direct link to the official portal.

What we learned

Government data is abundant and surprisingly accessible. USASpending.gov, the Census Bureau API, NYC's open data portal, and Open States all have free tiers with more data than we had time to use. The bottleneck isn't access, it's the work of translating
bureaucratic data structures into something a resident can read in 10 seconds.

Address detection as an application primitive is powerful. Making every feature city-aware and coordinate-aware from the start, rather than bolting it on, meant we never had to retrofit location into anything. The whole app follows the address.

Real photos added almost no information and introduced fragile external dependencies. Replacing them with gradient + SVG illustration required more design work upfront but produced a more coherent, faster, and fully controlled visual system.

Gamification that's grounded in real actions works better than
artificial point systems. Every action that earns points in the civic score, searching an address, reading a permit, clicking an official's contact page, is also genuinely useful civic behavior. The points
reinforce the right habits rather than manufacturing engagement.

What's next for Porch

  • More cities. The CityConfig architecture makes it straightforward to add any city with available open data. Boston, Chicago, and Oakland are logical next candidates.
  • Push notifications for permit deadlines. When a permit near your
    saved address has a comment deadline approaching, you should get a reminder, not discover it after the window closed.
  • Real comment submission. Right now the permit sheet lets you write a comment but doesn't submit it anywhere. The goal is direct integration with city comment portals or at minimum a one-tap email to your council rep with the comment pre-drafted.
  • Attendance tracking for public meetings. The meetings API is already wired up. The next step is letting users RSVP, get calendar invites, and see who else from their neighborhood is going.
  • Offline support. The core dashboard, your district, your officials, your recent permits, should work without an internet connection once
    loaded. Service worker caching would make Porch useful in low-connectivity environments.

Built With

Share this project:

Updates