Project Info
Inspiration
When a city debates rent control, a minimum wage, or an upzoning plan, nobody actually knows who it will help and who it will hurt until years later — after it's law, and the damage or benefit is already done. Policy gets made on ideology and vibes, and the people hurt most are usually the ones with the least voice in the room. Even when someone does care, they have no easy way to turn that concern into action. We wanted to flip the order of operations: see the distributional consequences of a policy before anyone votes — on a model of your own community — and then act on it.
What it does
PolicyPulse has two halves that flow into each other. The Pulse Map finds your area and surfaces the real bills moving around you right now — live federal legislation from Congress.gov and state bills from OpenStates — plotted as markers on a 3D map, alongside a rail of real local policy news. Every marker is a real bill; nothing is mock data. The Simulator lets you click any bill (or paste your own) and watch it play out across a statistically representative population of synthetic residents built from live U.S. Census (ACS) data for that state — real population, income, rent, racial composition, and housing tenure. The residents live through three years. Second-order effects cascade: a landlord facing rent control sells the building, so tenants get displaced; a wage floor rises, so a small business cuts hours. An inequality spotlight then reveals exactly who gets hurt and who benefits — broken down by race, income, and housing status — with the Gini coefficient before and after. Then we close the civic loop three ways. First, hear the people: click any resident to read — and now hear — their AI-generated, first-person story, voiced aloud with a voice matched to that resident. Second, find your fit: a personalized mode simulates whether a specific location is a good fit for you in particular, based on your own situation, rather than the community in aggregate. Third, act on it: "Email your representative" looks up your real federal and state legislators, then drafts a respectful constituent email citing the exact bill and the simulation's findings about who it affects — opening a prefilled email for state legislators, or the official contact form with the draft copied for members of Congress. Two more surfaces back up the credibility. A /validate page runs real, studied policies (like San Francisco's 1994 rent-control expansion) through the same engine and checks the predicted direction of effects against published research. And a /lab runs Monte Carlo uncertainty bands and sensitivity analysis, so you see the range of outcomes rather than a single cherry-picked run.
How we built it
Our stack is Next.js (App Router, React Server Components, server-sent-event streaming), React, TypeScript, and Tailwind on the front end. Agent orchestration runs on Mastra with multiple Anthropic Claude agents. Deepgram Aura powers the resident voices. Mapbox GL + deck.gl render the 3D map and geocoding. Live civic data comes from U.S. Census ACS, Congress.gov, OpenStates, and GNews, with optional Redis mirroring every run. The engine is the technical core. We ground a population in live Census ACS data, then spawn individual residents whose joint distribution of race × income × housing tenure × neighborhood matches the real community — so a low-income renter of a given background appears at the real-world rate, not by independent chance, and spatial segregation emerges naturally. A Claude PolicyAnalyst agent parses a free-text bill into a structured impact model: mechanism, intensity, who benefits, who pays, and likely unintended consequences. The simulation then runs in two passes per round. In the first pass, actor agents — small landlords and business owners — make probabilistic decisions that generate shocks. In the second, those shocks ripple out to every other resident across Month 1 → Month 6 → Year 1 → Year 3, tracking rent burden, displacement, wellbeing, and whether each person had to leave. The entire run streams to the dashboard in real time over SSE, backed by a durable event log so a shared link can replay the whole run from scratch. Graceful degradation is built in: with zero API keys the app still runs end to end on heuristic parsing, template stories, and clearly-labeled fallback datasets. Every live surface degrades to an honest empty state rather than ever inventing data.
Challenges we ran into
The first challenge was making synthetic residents representative, not just random. Matching each demographic on its own is easy; matching the joint distribution — so income–tenure correlation and segregation emerge naturally — is what makes the inequality analysis meaningful rather than decorative. That took real care in the spawning logic. The second was a subtle, invisible metric bug. Per-group impact was being read before each run finalized, so the headline "net impact by demographic" panel silently showed zero for every group, on every policy. We caught it by testing deterministically across policy types, confirmed the real differentiated numbers existed, and fixed where they were surfaced rather than touching the numbers themselves. The third was keeping the model honest. It would have been easy to make every bill "show displacement" for drama. We made the engine principled instead: displacement only appears where a real housing mechanism exists, so a privacy law correctly shows ~0% while rent control and upzoning move the needle. The fourth was voice without overreach. We match Deepgram voices to resident gender (inferred from our name pools) and a slight age lean — deliberately not race, to avoid stereotyping — and keep it deterministic so a resident always sounds the same.
Accomplishments we're proud of
We built a simulation grounded in real U.S. Census data that produces genuinely differentiated, defensible distributional outcomes rather than random noise dressed up as analysis. We wired seven real external data and AI integrations — Census, Congress.gov, OpenStates, GNews, Mapbox, Anthropic, and Deepgram — into one coherent product, each with an honest fallback. We landed an emotional payload that actually works: hearing a displaced resident tell their own story in a human voice turns an abstract statistic into something you feel. We treated intellectual honesty as a design principle, with directional validation against published studies, visible uncertainty bands, and honest empty states instead of fabricated data. And we closed the loop from awareness to action: you don't just learn who a bill hurts, you can email the person who votes on it in two clicks.
What we learned
The hard part of "AI for policy" isn't the AI — it's earning trust. Real Census grounding, directional validation, transparent assumptions, and honest empty states matter more than any single model output. PolicyPulse is a tool for building intuition about who's affected, not a forecast, and stating that clearly makes it more credible, not less. We also learned how much rigor it takes to make a simulation defensible: the difference between "the numbers look plausible" and "we can show you why each number is what it is" is most of the work.
What's next
for PolicyPulse We want deeper validation against more published studies, additional policy mechanisms beyond housing and labor, and finer-grained Census grounding at the county and city level. We also want to grow the personalized "find your fit" mode into a full planner that answers a bigger question: where should I live, and how would these policies actually treat someone like me?
PolicyPulse
See the law moving around you — then stress-test it on a digital twin of your own community.
PolicyPulse has two halves that flow into each other:
- The Pulse Map (homepage) — a live, tilted 3D map of the United States that finds your area and surfaces the real federal and state bills moving around you right now, alongside a rail of local policy news. No mock data: every marker is a real bill from Congress.gov / OpenStates, every story is real local news.
- The Simulator (
/simulate) — click any bill (or paste your own) and watch it play out across a statistically representative population of AI residents built from live U.S. Census (ACS) data for that state. Residents live through three years; second-order effects cascade (a landlord sells → tenants get displaced; a wage floor rises → a small business cuts hours), and an inequality spotlight reveals exactly who gets hurt — before anyone votes.
What it does
The Pulse Map (homepage)
- Finds your area from the browser's geolocation (or a ZIP / city search), reverse-geocoded with Mapbox.
- Pulls the real bills around you — live federal legislation from the Congress.gov API and state legislation from OpenStates — and plots them as glowing markers on a 3D map that flies to your state.
- Streams local policy news for your area from GNews in an auto-scrolling rail.
- Click a marker to read the bill, then “Simulate this policy” hands it off to the simulator.
The Simulator (/simulate)
- A bill arrives from the map (or you paste your own and pick a state).
- Ingestion grounds the population in live U.S. Census ACS data for that state — real population, median income, rent, racial composition, income distribution, tenure, and industry mix. Without a Census key it falls back to grounded, clearly-labeled datasets.
- A Mastra PolicyAnalyst agent parses the free-text bill into a structured impact model (mechanism, intensity, who benefits, who pays, likely unintended consequences).
- Proportional spawning creates individual residents whose joint distribution of race × neighborhood × income × tenure × employment matches the real community.
- Residents live through Month 1 → Year 3. Each round layers market drift, direct policy effects, and cascading shocks between agents — streamed live to the dashboard.
- The Inequality Spotlight quantifies disparities (e.g., displacement by race), the Gini shift, materialized unintended consequences, and ranked who-gets-hurt / who-benefits segments.
- Click any resident to read their AI-generated first-person story (a Mastra Resident agent on Claude Haiku).
There's also a /validate page that runs real, studied policies (e.g., SF's 1994 rent-control expansion) through the same engine and compares the predicted direction of effects against the documented findings of published research.
Tech & sponsor integrations
| Layer | Tech |
|---|---|
| Framework | Next.js 16 (App Router, RSC, SSE streaming), React 19, TypeScript, Tailwind v4 |
| Agents & orchestration | Mastra — PolicyAnalyst + Resident agents, a jurisdiction-ingestion tool, and a 2-step simulation workflow |
| LLM | Anthropic Claude Haiku via Mastra's model router |
| Nervous system | Redis — Streams (event log), JSON (snapshots), TimeSeries (metric trends), Pub/Sub |
| Live civic data | U.S. Census ACS (population), Congress.gov (federal bills), OpenStates (state bills), GNews (local news), Mapbox (3D map + geocoding) |
| Live ingestion | Browserbase — optional headless session to verify community data |
| Viz | Mapbox GL + deck.gl (3D map), Recharts, Framer Motion, Lucide |
Graceful degradation is a feature: with no API keys at all, the app still runs end-to-end — heuristic policy parsing, template resident stories, grounded datasets, and an in-memory event bus. Each live surface degrades to an honest empty state (“connect this key” / “no results”) rather than ever inventing data: no Mapbox token shows a connect-token prompt, no Census key falls back to labeled datasets, and no Congress / OpenStates / GNews key shows an empty rail. Add keys to light up the live integrations.
Getting started
npm install
npm run dev
Open the printed URL (e.g. http://localhost:3000). With no keys you'll get the Pulse Map's “connect Mapbox” prompt and the /simulate dashboard running on labeled datasets — fully functional. Add keys (below) to go fully live, then restart npm run dev (env vars load on boot).
Environment variables
Copy .env.example to .env.local and add what you have — everything is optional and each key lights up one surface:
Live Pulse Map + Census-grounded population:
NEXT_PUBLIC_MAPBOX_TOKEN— renders the 3D map and powers geolocation / search (account.mapbox.com).CENSUS_API_KEY— grounds the simulated population in real ACS data (api.census.gov).CONGRESS_API_KEY— real federal bills (api.congress.gov).OPENSTATES_API_KEY— real state-legislature bills (open.pluralpolicy.com).GNEWS_API_KEY— real local policy news (gnews.io).
Simulator agents + nervous system:
ANTHROPIC_API_KEY— enables the Mastra Haiku agents (policy analysis + resident stories).REDIS_URL— mirrors every run into Redis Stack (Streams/JSON/TimeSeries/Pub-Sub).BROWSERBASE_API_KEY+BROWSERBASE_PROJECT_ID+ENABLE_BROWSERBASE=1— optional live ingestion (alsonpm i playwright-core).
Architecture
src/
app/
page.tsx Pulse Map landing (live bills near you, client)
simulate/page.tsx The simulator dashboard (client)
validate/page.tsx Historical validation
api/
geo/ Reverse/forward geocoding (Mapbox)
policies/ Real federal (Congress.gov) + state (OpenStates) bills
news/ Real local policy news (GNews)
census/ Live ACS demographic profile for a state
simulate/ POST: start a run
stream/[runId]/ SSE: live event stream (backlog replay + live tail)
run/[runId]/ Full run snapshot
agent/[runId]/[id]/ Resident narrative (Haiku) + trajectory
runs/ · health/ · validate/
lib/
civic.ts Pulse Map types + geometry (markers, arcs)
usePulse.ts Homepage hook (locate -> fetch bills/news/census)
states.ts US state metadata (FIPS, centroids)
cache.ts TTL cache for live API calls (quota-friendly)
sources/ census · congress · openstates · news · geocode
engine.ts Simulation engine (rounds, cascades, second-order effects)
metrics.ts Aggregation + inequality analysis (disparities, segments, Gini)
personas.ts Proportional agent spawning
demographics.ts Grounded Census/ACS/BLS-shaped fallback datasets
policy.ts Heuristic policy parser (offline brain)
orchestrator.ts Paced live run driver -> bus events
bus.ts · runStore.ts · redis.ts The "nervous system"
ingest.ts Jurisdiction ingestion (live Census, + optional Browserbase)
historical.ts Validation cases vs. published studies
useSimulation.ts Simulator client hook (SSE consumption, rAF-batched)
mastra/
index.ts Mastra instance
agents/ policy-analyst, resident
tools/ ingest-jurisdiction
workflows/ simulation
components/ Pulse Map (PulseMap, NewsRail, PolicyDetail, LocationBadge) + dashboard UI
A note on honesty
The bills on the Pulse Map are real (Congress.gov / OpenStates) and the news is real (GNews). The simulated population is directionally realistic: with a Census key it's built from real ACS data for the state; without one it falls back to approximate, clearly-labeled datasets drawn from the shape of public Census/ACS/BLS data (grounded data vs national avg). Two demographic fields (income-tier “neighborhoods” and per-group immigrant share) are transparently derived from the real ACS figures and labeled as such. The simulation engine itself is a transparent, parameterized model of well-studied policy dynamics (rent control, minimum wage, zoning, etc.) — not a forecast. Synthetic residents are illustrative, not representative of any real person. Historical figures on /validate are reference points for directional validation, summarized from the cited studies. PolicyPulse is a tool for building intuition about distributional effects, not a substitute for formal policy analysis.
Analysis
View
Metric
- 12
- 11
- 10
- 5
- 3
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- Next.jsIn code
- ReactIn code
- RedisIn code
- Tailwind CSSIn code
- TypeScriptIn code
- AnthropicClaimed
- Node.jsClaimed
6 of 8 appear in the indexed code. 2 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeConfig
- CodexConfig
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
839 KB
Source files
144
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
lukeeskinner/PolicyPulse
173 files · 11.0 MB · @ 2f0cbab
Structure
Interface
50 files · 29%Screens, components and styles rendered to the user.
API & routing
25 files · 14%Request entry points: routes, handlers and controllers.
Application logic
61 files · 35%Domain rules, services and shared utilities.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- TypeScript91%
- Markdown7%
- CSS1%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
package.json
npm · 28- @browserbasehq/sdk
- @deck.gl/core
- @deck.gl/layers
- @deck.gl/mapbox
- @deck.gl/react
- @mastra/core
- clsx
- deck.gl
- framer-motion
- lucide-react
- mapbox-gl
- next
- playwright-core
- react
- react-dom
- react-map-gl
- recharts
- redis
- +10 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.