Sin Liang LeeSL Lee

24×100

A map of Pittsburgh’s ~11,000 City-owned vacant lots that shows, lot by lot, what could be built, what’s blocking it (zoning, money, site) and the next step.

Role
Everything: product, system design, data pipeline and rules, built with Claude coding agents
Team
Solo
Context
AI for Housing Hackathon (AI Horizons 2026, Pittsburgh)
Stack
TypeScript, React 19, Vite 8, Python 3.12, LangChain, LangGraph, Google Gemini, Vercel
24×100’s citywide map of Pittsburgh: City-owned vacant lots as dots, colored by what blocks a two-unit house, beside the layers and their counts and a panel saying 428 lots in the 6 checked districts are big enough but too narrow.
From the walkthrough: the citywide map, the zoom into the Hill, then 2241 Mahon St, where a two-unit house gets 4 ft to build on.

What it is

It is for the people who get affordable homes built: housing nonprofits and CDCs, small and mid-size developers, municipal planners and policy analysts. Pick a lot and it says what could be built there, what blocks it and the next step, down to a draft letter for each office. Every number is traced to its public source, and whatever it doesn’t know, it says so.

The name is the standard Pittsburgh lot, 24 ft wide and 100 ft deep. One on Mahon Street in the Hill meets its district’s minimum lot size exactly, yet a two-unit house there gets 4 ft of width: 24 − 10 − 10, after the 10 ft side setbacks. Every lot down the street shows the same sliver.

Made solo over 26–27 Sep 2026, for the hackathon’s Track 1: Development Feasibility & Pro Forma Navigator.

What I built

  • Orchestrated Claude Opus 5.5 coding agents to build it end to end, the data pipeline, the rule extraction and the interface, under the goals, rules of evidence and product decisions I set, and reviewed the work.
  • The rules of evidence: a model only proposes rules and drafts words; one TypeScript engine computes every number; an unknown is shown as unknown, never as a pass; and nothing is sent, paid for or signed by an agent.
  • The sign-off on the zoning rules the app computes: the 20 rules the Mahon Street and Larimer results use, then 48 more in four districts.
  • Development Ease: a range out of 100, never a lone number, from six parts (zoning fit, approvals, ownership and assembly, site, water and sewer, money at full cost), each clear, blocking or unknown. An unknown takes points off only the low end, so it never makes a lot look easier.
  • Rule what-ifs: the citywide classifier runs again with one clause of the code read differently. Strike the last sentence of §925.06.C and 196 more City-owned lots could hold a two-unit house. A what-if, not the law.

Technical notes

  • Six districts are computed, from rules a person signed: 2,318 City-owned vacant lots checked, of which 428 are big enough for a two-unit house but too narrow. Districts with no signed rules stay grey, never a guess.
  • Rule extraction on RM‑M: 11 of 11 fields agree with the answer key, and 21 of 21 quotes are verbatim inside their cited sections. A district costs $0.06–$0.16 to extract at paid rates.
  • No personal data: owner names and mailing addresses are never requested or stored, and a test walks every output for them. The app shows owner types only.
  • CI on every push: typecheck, Vitest, pytest, and a build that must reproduce every committed data file byte for byte.

How it’s built

  1. Public dataPulled, timestamped, hashedWPRDC, City of Pittsburgh ArcGIS, Allegheny County, HUD and OpenStreetMap, and the Pittsburgh Code, Title 9 (zoning).
  2. Python pipelinePull, join, reconcileLot areas are checked against the deeds, and conflicts shown, not settled. A refresh re-pulls every dataset and shows what changed.
  3. The modelProposes rules, drafts wordsGemini, through LangChain, reads the saved code into typed rules, each with a verbatim quote, and code re-checks every quote. The agents (LangGraph) plan, pick checks and draft.
  4. A personSigns, sends, spendsA rule stays pencil until a named person signs it, and only then is it counted. No letter is sent and no study paid for by an agent.
  5. TypeScript engineComputes every numberEnvelopes and checks, the citywide classifier, money at full cost, Development Ease, the letters. A verifier blocks any number an agent wrote that the engine or a source doesn’t hold.
  6. The siteStatic, on VercelA React 19 app (Map, Plan, Graph, Table, Compare) and a static JSON API, built by Vite 8.
Simplified from the project’s README. Pencil: what a model proposed and no person has signed; it is shown, never counted.
24×100’s inspector for 2241 Mahon St, lot 25: “Only with subsidy”, Ease 0–40 of 100. “The rules leave only 4 ft to build on, against your 16 ft plan; a home needs $57.2k–$150k of subsidy before land, at full cost.” Cards for buildable width, build cost, the newest new-build sale and what is left after building, then the Development Ease table: zoning fit, a variance, −35; approvals needed, open, 0 to −30.
Fig. 1 Lot 25’s Development Ease: 0–40 of 100, and the parts behind the range, each with its source.