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
- google-places
- next.js14
- nextauth.js
- tailwindcss
- typescript
- us-census-bureau-acs-api
- usaspending.gov-api
Log in or sign up for Devpost to join the conversation.