# Project export: Dwelligence

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: An AI-powered property search that combines commute intelligence, neighborhood amenities, and lifestyle context in one map.
- Devpost: https://devpost.com/software/dwelligence
- GitHub: https://github.com/vinn03/dwelligence
- Video: https://www.youtube.com/embed/COTtmyBRYJE?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — Vince (62 commits), Claude (6 commits)

## Devpost submission (written by the team)

### Inspiration

Have you ever fallen in love with an apartment listing, only to realize the commute to your workplace would be a nightmare? I've been there. Juggling multiple browser tabs between Zillow and Google Maps just to figure out if a property actually fits my lifestyle. The problem became crystal clear: Finding the right home shouldn't require becoming a data analyst. You're not just picking a property, you're choosing where you'll spend hours commuting each week, where you'll grab coffee before work, where you'll decompress at nearby parks. Current real estate platforms completely miss this context. Dwelligence was born from this frustration. I set out to build the property search platform I wish existed, one that understands your lifestyle and helps you find homes that actually work for how you live.

### What it does

Dwelligence reimagines real estate search by putting commute intelligence and lifestyle context at the center. Core Experience Set Your Workplace - Tell Dwelligence where you work, and it shows you what matters: how long it takes to get there Choose Your Transport Mode - Drive, bike, transit, or walk - see commute times instantly update across all listings Explore the Map - Properties display real commute times, not just addresses. Routes visualize on the map as you explore See Nearby Amenities - Properties are joined with open-source POI data to give users an understanding of nearby amenities to a listing. AI-powered results- Ask Gemini for any specifics on nearby amenities, and for specific queries tailored to your home-seeking criteria. AI-Powered Discovery Ask in plain English: "Show me 2BR apartments near parks under $2500" The Gemini AI integration: Parses your natural language query into structured filters Understands lifestyle preferences (amenities, commute priorities) Ranks properties intelligently based on your specific needs Clarifies ambiguous requests ("nearby" by car or on foot?) Neighborhood Intelligence Click any property to explore what's actually nearby: Amenity Visualization - See parks, cafes, grocery stores, transit stops plotted on the map Transport-Aware Proximity - Results adjust based on whether you're walking, biking, or driving Ask AI About Neighborhoods - "Are there any coffee shops nearby?" returns top-rated places with photos, hours, and map markers Features Route Alternatives - See up to 3 different routes with real-time traffic Favorites System - Save and compare properties across sessions Rent vs. Buy Toggle - Seamlessly switch between rental and purchase searches Rich Filtering - Price, bedrooms, bathrooms, property type (apartments + house rentals) How I built it Tech Stack Frontend: React 19 with Vite for lightning-fast development @vis.gl/react-google-maps for interactive mapping Tailwind CSS for responsive, modern UI React Context API for state management with localStorage persistence Backend: Node.js + Express serving a RESTful API PostgreSQL on Supabase for reliable, scalable data storage Google Maps APIs - Distance Matrix, Directions, Geocoding, and Places Gemini API for natural language understanding and intelligent ranking H3 Geospatial Indexing (Uber's hexagonal system) for millisecond-speed proximity queries node-cache for aggressive API response caching Architecture Highlights 1. Simple but Powerful Database Design Uses simple lat/lng columns with BETWEEN queries for viewport filtering Pre-calculated H3 indexes at 3 resolutions (r5, r6, r7) for different transport modes String-based H3 matching enables O(1) amenity lookups vs. O(n) distance calculations 2. Intelligent Caching Strategy Commute calculations cached for 24 hours per property-workplace-mode combination Geocoding results persisted to minimize API calls In-memory cache reduces Google Maps API costs by ~90% 3. Batch Optimization Single Distance Matrix API call calculates commutes for up to 25 properties simultaneously Debounced map updates (500ms) prevent excessive API calls during pan/zoom Lazy loading for detailed property views reduces initial page load 4. H3 Hexagonal Spatial Index Rather than calculating distances for every amenity query, I pre-indexed everything: Resolution 7 (~1.22km edge): Walking distance Resolution 6 (~3.23km edge): Biking distance Resolution 5 (~8.54km edge): Driving distance This allows queries like "properties near parks" to execute in milliseconds using simple SQL: 5. AI Integration Architecture Gemini parses natural language → structured filters Backend queries database with H3-optimized proximity joins Gemini ranks filtered results based on user intent Frontend displays ranked properties with AI explanations Data Pipeline Property Data: 252 hand-crafted Bay Area listings with realistic prices and locations Geocoding: All addresses converted to lat/lng via Google Geocoding API H3 Indexing: Properties and amenities indexed at 3 resolutions using h3-js library Amenity Data: 8 categories fetched from OpenStreetMap Overpass API (parks, grocery, cafes, restaurants, transit, gyms, pharmacies, community centers) Challenges I ran into 1. Slow Proximity Queries at Scale Problem: Calculating distances between every property and every amenity (O(n²) complexity) was painfully slow. Solution: Implemented Uber's H3 hexagonal spatial index. Pre-indexing amenities at 3 resolutions reduced query time from ~500ms to ~5ms - a 100x speedup! No PostGIS required. 2. Ambiguous Natural Language Queries Problem: User asks for "properties near cafes" - but near by what mode of transport? Walking distance is very different from driving distance. Solution: Enhanced Gemini prompts to detect ambiguity and ask clarifying questions. Default to walking distance but show UI indicator that lets users refine. Built a needsTransportModeClarity flag into the AI response schema. 3. Real-Time Map Performance Problem: Rendering 100+ property markers with commute calculations while panning/zooming caused janky UI. A slower internet connection also prevented the vector-based map from rendering across many occasions. Solution: Debounced viewport change events (500ms), limited to 100 properties max per viewport, used React Context to prevent unnecessary re-renders, and implemented a raster basemap fallback (which is more performant) in the case of a slower internet connection. 4. Commute Calculation Edge Cases Problem: What if the user searches by amenities but hasn't set a workplace? What if Google Maps returns an error for a specific route? Solution: Allow amenity-only searches without workplace (commute fields show "Set workplace to see commute") Graceful degradation - if a single property's commute fails, show "Commute unavailable" but still display the property Persist workplace in localStorage so returning users don't lose context 5. Data Quality & Coverage Problem: OpenStreetMap data has gaps for certain amenity types in some neighborhoods. Solution: Supplemented OSM with Google Places API for critical amenities like grocery stores. Added visual indicators when amenity data is limited for an area. Accomplishments I'm proud of Technical Achievements I built a production-ready full-stack app in 36 hours with features that rival established platforms: ✅ Full CRUD backend API with intelligent caching ✅ Interactive map with real-time commute visualization ✅ AI-powered search using Gemini API ✅ Geospatial indexing system (H3) for lightning-fast queries ✅ 252-property dataset with realistic Bay Area data ✅ Multi-modal routing (4 transport modes) ✅ Persistent favorites and filter preferences ✅ Responsive design that works on desktop and mobile UX Innovations Commute-First Design: Unlike Zillow or Redfin, commute time isn't buried 3 clicks deep - it's front and center on every listing. Transport-Mode Awareness: The entire app adapts when you switch from "walking" to "biking" - amenities re-filter, rankings update, and hex boundaries resize. This level of context-awareness is unique in real estate search. Natural Language Search: Ask like a human - "2BR near parks under $2500" - and get intelligent results. The AI understands lifestyle priorities, not just database filters. Neighborhood Chat: Click "Ask AI" on any property and query its surroundings conversationally: "Are there any coffee shops nearby?" Returns real places with photos and map markers. This turns passive browsing into interactive discovery. Scale & Performance Sub-50ms queries for complex proximity searches across 252 properties and 1000+ amenities thanks to H3 indexing. 90% API cost reduction through intelligent caching strategies. Zero database migrations during development - schema was well-designed from day one. Problem-Solving I solved the "20 browser tabs" problem. One interface now combines: Zillow (property listings) Google Maps (routes and commutes) Yelp (nearby amenities) What I learned Technical Learnings 1. Geospatial indexing is a game-changer Before H3, my amenity queries took 500ms. After H3, they took 5ms. Hexagonal grids are elegant, uniform, and blazingly fast for proximity queries. I learned that sometimes the right data structure matters more than raw optimization. 2. API design matters as much as implementation I initially built individual endpoints for each feature. Consolidating to a /map-bounds endpoint that returns properties + filters + commute data in one call reduced round trips by 70%. 3. Caching strategy defines your scalability With no caching, I'd hit Google Maps API limits in 2 hours of testing. With aggressive caching (24h for commutes, localStorage for preferences), the app can serve hundreds of users for days on the free tier. 4. AI prompt engineering is an art My first Gemini prompts returned inconsistent JSON. I learned to: Explicitly define output schema Use one-shot examples Add "return ONLY valid JSON" instructions Build fallback parsing with regex Add ambiguity detection flags Product & Design Learnings 1. Progressive disclosure prevents overwhelm I display compact property cards by default, then expand to show route alternatives, nearby amenities, and AI chat only when users click. This keeps the interface clean while offering power-user depth. 2. Edge cases make or break UX Empty search results, missing commute data, ambiguous queries - these "unhappy paths" took 30% of my development time but define whether users trust the product. Process Learnings 1. Design docs save time I spent 7 hours writing a detailed design doc before coding. This prevented scope creep, aligned architecture decisions, and gave me a clear MVP → stretch goal progression. 2. Cache-first, optimize later Every API call was wrapped in caching from day one. I didn't prematurely optimize code, but I did prevent redundant external API calls. This saved both time and money.

### What's next

Short-Term Enhancements Preferred Commute Time - Set a preferred commute time for commute visualization. Crime & Walkability Scores - Integrate Walk Score API and local crime data Add your listing - Allow hosts/realtors to add property listings through a POST endpoint, which would trigger h3 checks (with amenity aggregations into any new h3 produced from this) Medium-Term Features Cost Comparison Dashboard - Total cost of living (rent + transport + parking) Virtual Tours Integration - Embed 360° tours and video walkthroughs Schedule Showings - Direct integration with landlords/agents Long-Term Vision Real MLS Integration - Partner with Zillow/Redfin APIs for live listings Expansion to More Cities - Start with NYC, LA, Boston, Seattle Mobile App - React Native version for iOS/Android Browser Extension - Add Dwelligence data to Zillow/Craigslist listings Business Model Ideas Freemium SaaS - Free for basic search, premium for unlimited favorites/alerts Agent Partnerships - Revenue share with real estate agents who get leads API Licensing - Sell the commute intelligence API to other platforms Corporate Partnerships - Help companies attract talent by showcasing commute-friendly housing near their offices Try it Out GitHub Repository: https://github.com/yourusername/dwelligence Quick Start (Local) Requirements: Node.js 18+ PostgreSQL database (Supabase free tier works!) Google Maps API key (Distance Matrix, Directions, Geocoding, Places APIs enabled) Gemini API key (free tier available) Built With React 19 Vite Tailwind CSS Google Maps JavaScript API Google Distance Matrix API Google Directions API Google Geocoding API Google Places API Gemini API (Google AI) Node.js Express.js PostgreSQL H3 (Uber's Geospatial Library) OpenStreetMap (via Overpass API) Axios node-cache Team Solo developer project built in 36 hours for Calhacks 12.0.

## README (from the GitHub repository)

# 🏡 Dwelligence

**Smart real estate search powered by commute intelligence and AI**

Dwelligence reimagines property search by prioritizing what matters most: **where you work and how you'll get there**. Set your workplace, choose your transport mode, and instantly see commute times for every listing. AI-powered search understands natural language queries like "2BR near parks under $2500" and delivers ranked results based on your lifestyle needs.

Built during a 36-hour hackathon to solve a real problem: finding the perfect apartment shouldn't require opening 20 browser tabs to check commute times.

---

## ✨ Features

### 🗺️ **Commute-First Property Search**

- **Set your workplace** and see commute times overlaid on every property listing
- **Multi-modal routing**: Drive 🚗, Bike 🚴, Transit 🚈, or Walk 🚶
- **Interactive map** with property markers, routes, and nearby amenities
- **Smart ranking**: Properties sorted by commute time + price for your perfect balance

### 🤖 **AI-Powered Search**

- **Natural language queries**: "2 bedroom apartments near coffee shops under $3000"
- **Gemini AI integration**: Understands preferences, filters ambiguity, ranks intelligently
- **Ask about neighborhoods**: Chat with AI about nearby amenities for any property
- **POI discovery**: Find grocery stores, gyms, restaurants near your future home

### 🏘️ **Neighborhood Intelligence**

- **Amenity visualization**: See parks, cafes, transit stops within walking/biking/driving distance
- **H3 geospatial indexing**: Lightning-fast proximity queries across 8 amenity types
- **Transport-aware filtering**: Amenities adjust based on your preferred transport mode
- **Interactive hex boundaries**: Visualize your walkable/bikeable neighborhood

### 🎯 **Advanced Filtering**

- **Rent vs. Buy toggle**: Switch between rental and for-sale properties
- **Price, bedrooms, bathrooms, property type** (apartments + house rentals)
- **Persistent filters**: Your preferences are saved across sessions
- **Real-time updates**: Map refreshes as you pan and zoom

### ⭐ **Favorites & Comparisons**

- **Save properties** to your favorites (persisted in localStorage)
- **Quick access tab**: Review saved listings anytime
- **Compare commutes**: See how different properties stack up

---

## 🚀 Quick Start

### Prerequisites

- Node.js 18+
- PostgreSQL database (Supabase recommended)
- Google Maps API key with Distance Matrix, Directions, Geocoding, and Places APIs enabled
- Gemini API key (for AI features)

### 1. Clone & Install

```bash
git clone https://github.com/yourusername/dwelligence.git
cd dwelligence

# Install backend dependencies
cd backend
npm install

# Install frontend dependencies
cd ../frontend
npm install
```

### 2. Set Up Database

**Option A: Supabase (Recommended)**

1. Create a free account at [supabase.com](https://supabase.com)
2. Create a new project and save your database password
3. Get your connection string from Project Settings → Database

**Option B: Local PostgreSQL**

```bash
createdb dwelligence
```

### 3. Configure Environment Variables

**Backend** (`backend/.env`):

```env
DATABASE_URL=postgresql://user:password@host:5432/database
GOOGLE_MAPS_API_KEY=your_google_maps_api_key
GEMINI_API_KEY=your_gemini_api_key
PORT=3001
NODE_ENV=development
```

**Frontend** (`frontend/.env`):

```env
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key
VITE_API_URL=http://localhost:3001/api
```

### 4. Initialize Database

```bash
cd backend

# Run schema
node scripts/run-schema.js

# Seed with 252 Bay Area properties
npm run seed

# Calculate H3 indexes for amenity features
node scripts/calculateH3ForProperties.js

# (Optional) Fetch real amenity data from OpenStreetMap
node scripts/fetchOSMAmenities.js
```

### 5. Start Development Servers

**Terminal 1 - Backend:**

```bash
cd backend
npm run dev
# Runs on http://localhost:3001
```

**Terminal 2 - Frontend:**

```bash
cd frontend
npm run dev
# Runs on http://localhost:5173
```

Visit `http://localhost:5173` and start exploring! 🎉

---

## 📚 Tech Stack

### Frontend

- **React 19** - Modern UI library with concurrent features
- **Vite** - Lightning-fast build tool and dev server
- **Tailwind CSS** - Utility-first styling
- **@vis.gl/react-google-maps** - Official Google Maps React library
- **React Context API** - Global state management
- **Axios** - HTTP client for API requests

### Backend

- **Node.js + Express** - RESTful API server
- **PostgreSQL** - Relational database with geospatial queries
- **Google Maps APIs** - Distance Matrix, Directions, Geocoding, Places
- **Gemini API** - AI-powered natural language processing and ranking
- **H3** - Uber's hexagonal hierarchical spatial index
- **node-cache** - In-memory caching for API responses

### Infrastructure

- **Supabase** - Managed PostgreSQL hosting
- **OpenStreetMap** - Open-source amenity data via Overpass API

---

## 🏗️ Architecture

### Component Structure

```
App
├── Header
│   ├── ListingTypeToggle (Rent/Buy)
│   ├── SearchBar (with AI toggle)
│   ├── AskBar (AI natural language search)
│   ├── WorkplaceInput
│   ├── TransportModeToggle
│   └── Filters
├── MapContainer
│   ├── PropertyMarkers
│   ├── Tooltip (hover preview)
│   ├── RoutePolylines (commute visualization)
│   ├── AmenityMarkers (nearby amenities)
│   ├── POIMarkers (AI search results)
└── RightPanel
    ├── TabsContainer (Top Picks / AI Results / Favorites)
    └── DetailedListingView
        ├── Details Tab
        ├── Commute Tab (route alternatives)
        ├── Nearby Tab (amenity visualization)
        └── Ask Tab (AI neighborhood chat)
```

### Data Flow

1. **User sets workplace** → Stored in Context + localStorage
2. **Map viewport changes** → Debounced API call to `/api/properties/map-bounds`
3. **Properties returned** → Filtered by listing type, price, beds, baths
4. **Commute calculation** → Batch request to Google Distance Matrix API (cached 24h)
5. **Properties ranked** → Sorted by commute time + price
6. **Markers rendered** → Displayed on map with commute times

### Database Schema

```sql
properties (
  id, address, lat, lng, price, bedrooms, bathrooms,
  sq_ft, property_type, sale_type, image_url,
  h3_index_r7, h3_index_r6, h3_index_r5  -- Geospatial indexes
)

amenities (
  id, name, type, lat, lng, address, osm_id,
  h3_index_r7, h3_index_r6, h3_index_r5
)
```

**No PostGIS required!** Uses simple `BETWEEN` queries for lat/lng viewport filtering and H3 string matching for proximity queries.

---

## 🎨 Key Features in Detail

### 1. Commute Calculation Engine

- **Batch optimization**: Single Distance Matrix API call for up to 25 properties
- **Multi-modal routing**: Separate calculations for drive, bike, transit, walk
- **Intelligent caching**: 24-hour cache per property-workplace-mode combination
- **Route alternatives**: Up to 3 route options with polyline visualization
- **Real-time traffic**: Incorporates current traffic conditions

### 2. AI Search & Ranking (Gemini Integration)

**Query Parsing:**

```javascript
"2BR near parks under $2500"
→ {
    bedrooms: { min: 2, max: 2 },
    priceRange: { max: 2500 },
    amenityPreferences: ["park"],
    transportMode: "walking"
  }
```

**Intelligent Ranking:**

- Combines structured filters with natural language understanding
- Considers commute time, price, amenities, and user intent
- Provides human-readable explanations for each ranking

**Neighborhood Chat:**

- Ask questions like "Are there any coffee shops nearby?"
- Returns top 5 places with ratings, hours, photos from Google Places API
- Markers numbered on map for easy reference

### 3. H3 Geospatial Indexing

**Multi-resolution indexing** for different transport modes:

- **Resolution 7** (~1.22km edge): Walking distance
- **Resolution 6** (~3.23km edge): Biking distance
- **Resolution 5** (~8.54km edge): Driving distance

**Fast proximity queries:**

```sql
SELECT * FROM amenities
WHERE h3_index_r7 = property.h3_index_r7
-- Returns all amenities in 

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 63 recognized source files, 205 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- Google Gemini (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- PostgreSQL (technology) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Tailwind CSS (technology) — detected in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository; commit authorship or trailers

## Codebase structure (from repository index)

### Files (67 of 67)

```
.gitignore
backend/package.json
backend/scripts/calculateH3ForProperties.js
backend/scripts/fetchOSMAmenities.js
backend/scripts/schema.sql
backend/src/middleware/errorHandler.js
backend/src/routes/amenities.js
backend/src/routes/commute.js
backend/src/routes/properties.js
backend/src/routes/search.js
backend/src/server.js
backend/src/services/database.js
backend/src/services/gemini.js
backend/src/services/googleMaps.js
backend/src/utils/scoring.js
CLAUDE.md
frontend/.gitignore
frontend/eslint.config.js
frontend/index.html
frontend/package.json
frontend/postcss.config.js
frontend/README.md
frontend/src/App.jsx
frontend/src/components/Header/Header.jsx
frontend/src/components/Header/search/AskBar.jsx
frontend/src/components/Header/search/Filters.jsx
frontend/src/components/Header/search/ListingTypeToggle.jsx
frontend/src/components/Header/search/SearchBar.jsx
frontend/src/components/Header/ui/Logo.jsx
frontend/src/components/Header/ui/MapRenderToggle.jsx
frontend/src/components/Header/workplace/TransportModeToggle.jsx
frontend/src/components/Header/workplace/WorkplaceInput.jsx
frontend/src/components/Header/workplace/WorkplacePrompt.jsx
frontend/src/components/Listing/Listing.jsx
frontend/src/components/Listing/SkeletonCard.jsx
frontend/src/components/Map/MapContainer.jsx
frontend/src/components/Map/markers/AmenityMarkers.jsx
frontend/src/components/Map/markers/POIMarkers.jsx
frontend/src/components/Map/markers/PropertyCenterMarker.jsx
frontend/src/components/Map/markers/PropertyMarker.jsx
frontend/src/components/Map/markers/WorkplaceMarker.jsx
frontend/src/components/Map/overlays/RoutePolylines.jsx
frontend/src/components/Map/overlays/Tooltip.jsx
frontend/src/components/Map/utils/PinMarker.js
frontend/src/components/RightPanel/ai/AIInterpretationBanner.jsx
frontend/src/components/RightPanel/ai/AskListingTab.jsx
frontend/src/components/RightPanel/property-display/CommuteTab.jsx
frontend/src/components/RightPanel/property-display/DetailedListingView.jsx
frontend/src/components/RightPanel/property-display/DetailsTab.jsx
frontend/src/components/RightPanel/property-display/NearbyTab.jsx
frontend/src/components/RightPanel/property-display/PropertyGrid.jsx
frontend/src/components/RightPanel/property-display/TravelModeIcon.jsx
frontend/src/components/RightPanel/RightPanel.jsx
frontend/src/components/RightPanel/TabsContainer.jsx
frontend/src/components/shared/EmptyState.jsx
frontend/src/components/shared/LoadingSpinner.jsx
frontend/src/constants/index.js
frontend/src/context/AppContext.jsx
frontend/src/hooks/useAskProperty.js
frontend/src/hooks/usePropertySorting.js
frontend/src/index.css
frontend/src/main.jsx
frontend/src/services/api.js
frontend/tailwind.config.js
frontend/vite.config.js
README.md
TODO.md
```

### Dependencies

- backend/package.json: @google/generative-ai@^0.21.0, @googlemaps/google-maps-services-js@^3.4.0, cors@^2.8.5, dotenv@^16.4.5, express@^4.21.2, h3-js@^4.1.0, node-cache@^5.1.2, nodemon@^3.1.9, pg@^8.13.1
- frontend/package.json: @eslint/js@^9.36.0, @types/react@^19.1.16, @types/react-dom@^19.1.9, @vis.gl/react-google-maps@^1.3.5, @vitejs/plugin-react@^5.0.4, autoprefixer@^10.4.20, axios@^1.7.9, eslint@^9.36.0, eslint-plugin-react-hooks@^5.2.0, eslint-plugin-react-refresh@^0.4.22, globals@^16.4.0, postcss@^8.5.1, react@^19.1.1, react-dom@^19.1.1, tailwindcss@^3.4.17, vite@^7.1.7

### Recent commits (newest first)

- removed map viewport limit
- dwelligence logo in the cneter
- better slider contrast
- price range handling improvments
- removed unused scripts and mock data
- Merge pull request #1 from vinn03/frontend-refac
- aria additions for accessibility improvement
- constants added
- fixed typeerror associated w pinmarker
- handling duplicate code
- api service: typedefs + error handling + timeout + abortcontroller for request cancellation
- property listing sidepanel code refactor
- memoization and callback implementation across app
- disabled AI search as it is currently flawed
- component migration ->>>>
- removed commute calculation
- deleted md file
- tailwind config cnh and readme updated
- example question sends
- yippee database expandsion

## Key source files (fetched from GitHub, selected and truncated for size)

### CLAUDE.md

```markdown
- Ensure to always update the README if needed
- Ensure that imports are properly resolved if moving files
- Always suggest to move code into sub-components if possible (code should never be more than 5 nests deep)

```

### TODO.md

```markdown
# Post-Hackathon TODOs

## Security: Google Maps API Key Configuration

### Problem
Currently using the same API key for both frontend and backend, which exposes the key in the browser.

### Solution
Set up proper API key restrictions in Google Cloud Console:

**Option 1: Two Separate Keys (Recommended)**
1. Create **Frontend Key**:
   - Restrict to: HTTP referrers only (`yourdomain.com/*`)
   - Enable only: Maps JavaScript API
   - Update: `frontend/.env` → `VITE_GOOGLE_MAPS_API_KEY`

2. Create **Backend Key**:
   - Restrict to: IP addresses only (your server IP)
   - Enable: Distance Matrix API, Directions API, Geocoding API
   - Update: `backend/.env` → `GOOGLE_MAPS_API_KEY`

**Option 2: Single Key with Dual Restrictions**
- Add both HTTP referrer AND IP address restrictions to existing key
- Works from your domain AND your server, but nowhere else

### Why This Matters
- Prevents API key abuse if someone copies it from browser DevTools
- Limits blast radius if key is compromised
- Follows security best practices

### Resources
- [Google Maps API Key Best Practices](https://developers.google.com/maps/api-security-best-practices)
- [API Key Restrictions](https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions)

```

### frontend/package.json

```
{
  "name": "dwelligence-frontend",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^19.1.1",
    "react-dom": "^19.1.1",
    "@vis.gl/react-google-maps": "^1.3.5",
    "axios": "^1.7.9"
  },
  "devDependencies": {
    "@eslint/js": "^9.36.0",
    "@types/react": "^19.1.16",
    "@types/react-dom": "^19.1.9",
    "@vitejs/plugin-react": "^5.0.4",
    "autoprefixer": "^10.4.20",
    "eslint": "^9.36.0",
    "eslint-plugin-react-hooks": "^5.2.0",
    "eslint-plugin-react-refresh": "^0.4.22",
    "globals": "^16.4.0",
    "postcss": "^8.5.1",
    "tailwindcss": "^3.4.17",
    "vite": "^7.1.7"
  }
}

```

### backend/package.json

```
{
  "name": "dwelligence-backend",
  "version": "1.0.0",
  "description": "Backend API for Dwelligence - Map-based real estate search with commute intelligence",
  "main": "src/server.js",
  "type": "module",
  "scripts": {
    "dev": "node --watch src/server.js",
    "start": "node src/server.js",
    "seed": "node scripts/seed-database.js",
    "seed:amenities": "node scripts/seed-amenities.js"
  },
  "keywords": ["real-estate", "maps", "commute", "ai"],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "@google/generative-ai": "^0.21.0",
    "@googlemaps/google-maps-services-js": "^3.4.0",
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.21.2",
    "h3-js": "^4.1.0",
    "node-cache": "^5.1.2",
    "pg": "^8.13.1"
  },
  "devDependencies": {
    "nodemon": "^3.1.9"
  }
}

```

### frontend/src/main.jsx

```javascript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

```

### frontend/src/App.jsx

```javascript
import Header from './components/Header/Header';
import MapContainer from './components/Map/MapContainer';
import RightPanel from './components/RightPanel/RightPanel';
import { AppProvider } from './context/AppContext';

function App() {
  return (
    <AppProvider>
      <div className="h-screen w-screen flex flex-col overflow-hidden">
        {/* Header */}
        <Header />

        {/* Main content: Map + Right Panel */}
        <div className="flex-1 flex overflow-hidden">
          {/* Map Container */}
          <div className="flex-1 relative">
            <MapContainer />
          </div>

          {/* Right Panel */}
          <RightPanel />
        </div>
      </div>
    </AppProvider>
  );
}

export default App;

```

### backend/src/server.js

```javascript
import express from "express";
import cors from "cors";
import dotenv from "dotenv";

// Import routes
import propertiesRouter from "./routes/properties.js";
import commuteRouter from "./routes/commute.js";
import searchRouter from "./routes/search.js";
import amenitiesRouter from "./routes/amenities.js";

// Import middleware
import { errorHandler } from "./middleware/errorHandler.js";

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3001;

// Middleware
app.use(cors());
app.use(express.json());

// Health check
app.get("/health", (req, res) => {
  res.json({ status: "ok", timestamp: new Date().toISOString() });
});

// API Routes
app.use("/api/properties", propertiesRouter);
app.use("/api/commute", commuteRouter);
app.use("/api/search", searchRouter);
app.use("/api/amenities", amenitiesRouter);

// Error handling middleware (must be last)
app.use(errorHandler);

app.listen(PORT, () => {
  console.log(`🚀 Dwelligence API running on http://localhost:${PORT}`);
  console.log(`📍 Environment: ${process.env.NODE_ENV || "development"}`);
});

```

### frontend/src/constants/index.js

```javascript
export const FILTERS = {
  PRICE_MIN: 0,
  PRICE_MAX: 10000,
  DEFAULT_LISTING_TYPE: 'rent',
};

export const MAP = {
  DEFAULT_CENTER: { lat: 37.7749, lng: -122.4194 },
  DEFAULT_ZOOM: 15,
  BOUNDS_OFFSET: 0.01,
  DEBOUNCE_TIMEOUT: 500,
  TILE_LOAD_TIMEOUT: 3000,
};

export const TRANSPORT_MODE_RANGES = {
  walking: { label: 'Walking Distance', range: '~1.2km', emoji: '🚶' },
  bicycling: { label: 'Biking Distance', range: '~3.2km', emoji: '🚴' },
  driving: { label: 'Driving Distance', range: '~8.5km', emoji: '🚗' },
  transit: { label: 'Transit Distance', range: '~1.2km', emoji: '🚈' },
};

export const ROUTE_COLORS = ['#4285F4', '#34A853', '#FBBC04'];

export const MARKER_COLORS = {
  selected: '#2563EB',
  selectedStroke: '#1E40AF',
  default: '#FFFFFF',
  defaultStroke: '#E5E7EB',
};

export const AMENITY_TYPES = [
  { id: 'park', label: 'Parks', emoji: '🌳' },
  { id: 'grocery', label: 'Groceries', emoji: '🛒' },
  { id: 'cafe', label: 'Cafes', emoji: '☕' },
  { id: 'restaurant', label: 'Restaurants', emoji: '🍽️' },
  { id: 'transit_station', label: 'Transit', emoji: '🚈' },
  { id: 'gym', label: 'Gyms', emoji: '💪' },
  { id: 'pharmacy', label: 'Pharmacies', emoji: '💊' },
  { id: 'community_center', label: 'Community', emoji: '🏢' },
];

export const EXAMPLE_QUESTIONS = [
  'Are there any coffee shops nearby?',
  'What grocery stores are close?',
  'Where can I find gyms?',
  'Any good restaurants in the area?',
  'Is there a pharmacy nearby?',
];

export const PLACEHOLDER_IMAGE = 'https://via.placeholder.com/400x300';

```

### frontend/postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

### frontend/vite.config.js

```javascript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
})

```

[53 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]