Skip to content
krishivsethPublic

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Where2Liv

See what an apartment will really cost, and how safe the block is, before you tour it.

Where2Liv (also known as "What The Rent?!") is a Chrome extension for San Francisco apartment hunting. Open a listing on Zillow or StreetEasy, click the extension, and it reads the address off the page, estimates the monthly electricity bill from the building's public energy benchmark data, and grades the neighborhood using SF 311 and police incident reports. A separate map app plans walking, cycling or driving routes and scores each one against recent crime data.

What it does

  • Energy bill estimate. The content script pulls the address, bedroom count and square footage from the listing. The backend fuzzy-matches the address against SF's building energy benchmark CSV, scales the building's electricity intensity to the apartment size, applies a building-age efficiency factor and SF seasonal factors, and prices the result with PG&E residential rates. The popup shows the average monthly bill.
  • Safety rating. The backend geocodes the address, pulls 311 service requests and police incident reports within a small radius, and returns a letter grade with a breakdown by category. A Gemini-backed agent writes the summary when a key is set; otherwise the analyzer returns its own structured result.
  • Chat about the building. The popup has a chat box. Gemini classifies the question, then the backend either summarizes recent Google reviews of the building with OpenAI, lists nearby places from Google Places, or answers directly.
  • Safe route planning. Enter a destination in the popup and a Next.js map opens with the listing as origin. It geocodes with Nominatim, fetches alternatives from OSRM, loads the last three months of SF police incidents, and scores each route 0-100 with a letter grade. A crime heatmap is overlaid on the map.

How it works

flowchart LR
    L["Zillow / StreetEasy listing"]
    CS["content.js<br/>scrapes address, rooms, sq ft"]
    POP["Extension popup<br/>React + Vite"]
    BE["Flask backend<br/>port 9005"]
    CSV["SF building energy CSV<br/>+ police incident CSV"]
    SF["SF Open Data<br/>311 API"]
    G["Google Maps, Places<br/>Gemini, OpenAI"]
    SR["safe-route<br/>Next.js map, port 9006"]
    OSM["Nominatim + OSRM<br/>+ SF police data"]

    L --> CS --> POP
    POP -- "/api/estimate, /api/safety, /api/chat" --> BE
    BE --> CSV
    BE --> SF
    BE --> G
    POP -- "opens /route?origin&destination" --> SR
    SR --> OSM
Loading

The backend loads the building CSV and pre-fetches safety data at startup, then caches address lookups, estimates and safety results in memory for one to two hours. The route planner talks to OpenStreetMap services and SF Open Data directly from the browser and does not depend on the Flask backend.

Quick start

You need Python 3, Node 20, and a Google Maps API key with Geocoding and Places enabled.

1. Backend

cd backend
python3 -m venv env && source env/bin/activate
pip install -r requirements.txt
GOOGLE_API_KEY=... python app.py            # http://localhost:9005

SF_Building_Energy_Filtered_Clean.csv ships in the repo. For safety ratings the backend also looks for Police_Department_Incident_Reports__2018_to_Present_20250726.csv and, optionally, SF_311_Cases.csv in backend/. Neither is committed. See backend/SF_311_README.md for where to download them. Without them the safety analyzer falls back to the live 311 API only.

python test_system.py exercises the data loading and estimation pipeline. ./start_server.sh runs the tests and then starts Gunicorn on port 8000, which is how the Railway deployment runs.

2. Extension

cd frontend
npm install
npm run build:extension                     # writes dist/ with manifest.json and content.js

Open chrome://extensions, turn on Developer mode, choose Load unpacked, and pick frontend/dist. Then open a Zillow or StreetEasy listing and click the extension icon.

3. Route planner

cd safe-route
npm install
npm run dev -- -p 9006                      # http://localhost:9006

The popup opens http://localhost:9006/route?origin=...&destination=..., so the route planner has to be on port 9006 for the "plan a route" button to work locally.

Configuration

Backend settings are environment variables. The backend reads a .env file in backend/ through python-dotenv.

Variable Required Purpose
GOOGLE_API_KEY yes Geocoding, Places search, Directions and building review lookup. The backend refuses to initialize without it.
GEMINI_API_KEY no Enables the safety summary agent and the chat intent classifier (gemini-2.5-flash-lite). Without it, safety falls back to the plain analyzer and chat is limited.
OPENAI_API_KEY no Summarizes Google reviews with gpt-3.5-turbo for the /api/reviews route and review questions in chat.
CITY no SF (default) or NYC. Selects which 311 and crime sources the safety analyzer uses. The NYC path is the original implementation and is no longer wired to the shipped data.
PORT no Port for Gunicorn (default 8000). python app.py always uses 9005.

The extension and route planner have no configuration. Backend and route planner URLs are hardcoded in frontend/src/App.tsx, frontend/src/components/ChatInterface.tsx and frontend/public/manifest.json.

API

All routes are on the Flask backend.

Route Purpose
GET /health Liveness and component status
POST /api/estimate Monthly and annual electricity estimate for {address, num_rooms, sq_ft?}
GET /api/search?q=&limit= Fuzzy search of the building dataset
GET /api/building/<property_id> One building's benchmark record
POST /api/safety Safety grade and breakdown for {address | zip_code | borough, radius_miles?}
GET /api/safety/borough-comparison, POST /api/safety/refresh Area comparison and cache refresh
POST /api/safe-routes Google Directions alternatives scored against crime data
POST /api/reviews Google reviews summary for {address, building_name?}
POST /api/chat Routes {query, address} to reviews, nearby places or a general answer

Project layout

backend/            Flask API
├── app.py                 routes, startup, caches, chat intent routing
├── data_processor.py      loads the building energy CSV
├── address_matcher.py     fuzzy address matching
├── bill_estimator.py      kWh and bill estimate per month
├── rate_calculator.py     PG&E residential rates
├── seasonality_factors.py monthly usage multipliers
├── safety_analyzer.py     311 and police data, grades, category breakdown
├── agent.py               Gemini agents for safety summaries
├── route_analyzer.py      Google Directions + crime density scoring
├── reviews_analyzer.py    Google Places reviews + OpenAI summary
├── gunicorn.conf.py, Procfile, railway.toml
└── *.csv                  SF and NYC building energy benchmark data
frontend/           Chrome extension (React, Vite, Tailwind)
├── public/manifest.json   MV3 manifest
├── public/content.js      listing scraper for Zillow and StreetEasy
└── src/                   popup UI, safety and chat components
safe-route/         Next.js route planner with Leaflet map and crime heatmap

Limitations

  • San Francisco only. app.py always loads the SF energy CSV, and the police data is SF. The scraper still runs on StreetEasy and the NYC 311 and NYPD code paths remain, but a NYC listing will not match any building.
  • Estimates, not bills. Benchmark data is annual and building-wide. Monthly numbers come from fixed seasonal factors and apartment sizes guessed from room count. PG&E rates are hardcoded and will drift.
  • Address matching can miss. Listings that are not in the benchmark dataset return no estimate. The scraper depends on Zillow and StreetEasy page structure and breaks when those sites change.
  • Local ports are fixed. The extension expects the backend on 127.0.0.1:9005 and the route planner on localhost:9006.
  • Keys required. Safety summaries, chat and review analysis all need third-party API keys. The route planner calls public Nominatim and OSRM endpoints and is subject to their rate limits.
  • Not a security product. Grades are derived from reported incidents in a small radius and should not be treated as an assessment of personal safety.

License

This project uses SF open data and is intended for educational and research purposes.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages