{"id":48133014,"url":"https://github.com/chf3198/home-harbor","last_synced_at":"2026-04-04T16:41:04.500Z","repository":{"id":335606776,"uuid":"1146450664","full_name":"chf3198/home-harbor","owner":"chf3198","description":"AI-powered real estate search with AWS serverless (Lambda, DynamoDB, S3), React/Vite frontend, OpenRouter AI. Portfolio for Realtor.com Staff SWE. Cost: $0/month (100% free tier)","archived":false,"fork":false,"pushed_at":"2026-03-20T01:54:04.000Z","size":1028,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-20T17:44:09.847Z","etag":null,"topics":["ai","aws","dynamodb","jest","lambda","nodejs","openrouter","playwright","portfolio","react","real-estate","serverless","staff-engineer","tailwindcss","typescript","vite"],"latest_commit_sha":null,"homepage":"https://chf3198.github.io/home-harbor/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chf3198.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-31T05:35:19.000Z","updated_at":"2026-03-20T01:54:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/chf3198/home-harbor","commit_stats":null,"previous_names":["chf3198/home-harbor"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/chf3198/home-harbor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chf3198%2Fhome-harbor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chf3198%2Fhome-harbor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chf3198%2Fhome-harbor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chf3198%2Fhome-harbor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chf3198","download_url":"https://codeload.github.com/chf3198/home-harbor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chf3198%2Fhome-harbor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31405708,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","aws","dynamodb","jest","lambda","nodejs","openrouter","playwright","portfolio","react","real-estate","serverless","staff-engineer","tailwindcss","typescript","vite"],"created_at":"2026-04-04T16:41:02.138Z","updated_at":"2026-04-04T16:41:04.477Z","avatar_url":"https://github.com/chf3198.png","language":"JavaScript","readme":"# HomeHarbor\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\".github/banner.svg\" alt=\"HomeHarbor Banner\" width=\"100%\"\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://chf3198.github.io/home-harbor/\"\u003e\u003cimg src=\"https://img.shields.io/badge/🚀%20Live%20Demo-Try%20It!-10b981?style=for-the-badge\" alt=\"Live Demo\"\u003e\u003c/a\u003e\n    \u003ca href=\"#quick-start\"\u003e\u003cimg src=\"https://img.shields.io/badge/Quick%20Start-Guide-6366f1?style=for-the-badge\" alt=\"Quick Start\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/chf3198/home-harbor/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/chf3198/home-harbor?style=for-the-badge\u0026color=6366f1\" alt=\"Release\"\u003e\u003c/a\u003e\n    \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-PolyForm%20NC%201.0-blue?style=for-the-badge\" alt=\"PolyForm Noncommercial\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003e\n    \u003cimg src=\"https://img.shields.io/badge/AWS-Lambda-FF9900?style=flat-square\u0026logo=awslambda\u0026logoColor=white\" alt=\"AWS Lambda\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/React-18-61DAFB?style=flat-square\u0026logo=react\u0026logoColor=white\" alt=\"React\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Vite-5-646CFF?style=flat-square\u0026logo=vite\u0026logoColor=white\" alt=\"Vite\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/TypeScript-5-3178C6?style=flat-square\u0026logo=typescript\u0026logoColor=white\" alt=\"TypeScript\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Tailwind-3-06B6D4?style=flat-square\u0026logo=tailwindcss\u0026logoColor=white\" alt=\"Tailwind\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/DynamoDB-4053D6?style=flat-square\u0026logo=amazondynamodb\u0026logoColor=white\" alt=\"DynamoDB\"\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003e\u003cstrong\u003eCost: $0.00/month\u003c/strong\u003e · \u003cstrong\u003e54 Tests\u003c/strong\u003e · \u003cstrong\u003e31 Components\u003c/strong\u003e · \u003cstrong\u003e6 Lambda Functions\u003c/strong\u003e · \u003cstrong\u003e211K+ Properties\u003c/strong\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n---\n\n# HomeHarbor\n\n**HomeHarbor** is an AI-powered real estate search application built on a serverless AWS architecture that costs $0/month. Users search with natural language — \"3 bedroom homes under $400k near Hartford\" — and the AI extracts structured filters and queries 211K+ Connecticut property records from the CT Open Data Socrata API in real time. Built with AWS Lambda (6 functions), DynamoDB, S3, CloudFront, React 18 + Vite, TypeScript, Tailwind CSS, OpenRouter (routing to Llama 3.3 70B and Molmo 72B vision), and tested with 54 tests across Jest, Vitest, and Playwright.\n\n---\n\n## Project Overview\n\n| Category | What Was Built |\n|----------|---------------|\n| **Cloud Architecture** | 6 Lambda functions, DynamoDB, S3, CloudFront, EventBridge, Secrets Manager |\n| **AI/NLP Integration** | Natural language → structured query filters via LLM (OpenRouter) |\n| **Cost Engineering** | $0.00/month — 100% AWS free tier |\n| **Resilience** | Cascading model fallbacks, graceful degradation |\n| **Frontend** | React 18 SPA (31 components) + single-file HTML option |\n| **Testing** | 54 tests: Jest, Vitest, Playwright E2E, production UAT |\n| **Data** | 211K+ CT property records via Socrata API |\n\n**Status:** ✅ Fully deployed and functional\n\n---\n\n## Architecture\n\n```\nFrontend (React SPA on GitHub Pages)\n         │ HTTPS\n         ▼\n   API Gateway\n         │\n         ▼\nLambda Functions (Node.js 20)\n ├── properties-socrata.ts  → CT Open Data Socrata API (211K+ records)\n ├── chat.ts                → OpenRouter: Llama 3.3 70B (filter extraction)\n ├── analyze.ts             → OpenRouter: Molmo 72B (vision analysis)\n ├── describe.ts            → OpenRouter: Llama 3.3 70B (property descriptions)\n ├── redfin-ingestion.ts    [code complete, not deployed]\n └── street-view-fetch.ts   [code complete, not deployed]\n         │\n         ▼\nInfrastructure\n ├── DynamoDB  (cache)\n ├── S3        (images)\n └── Secrets Manager (API keys)\n```\n\n### AI Filter Extraction\n\nThe core technical challenge: converting natural language to structured database filters.\n\n```\nUser: \"Show me 3 bedroom homes under $400k near Hartford\"\n         │\n         ▼\nLambda chat.ts — prompt engineering:\n  - CT town knowledge embedded\n  - Handles ambiguous queries\n  - Extracts multiple filter types\n         │\n         ▼\nOpenRouter API (cascading model fallbacks):\n  1. Try:  meta-llama/llama-3.3-70b\n  2. Fall: google/gemini-flash\n  3. Fall: anthropic/claude-haiku\n         │\n         ▼\nExtracted: { beds: 3, maxPrice: 400000, city: \"Hartford\" }\n```\n\n### Key Architectural Decisions\n\n| Decision | Rationale |\n|----------|-----------|\n| **Serverless Lambda** | Zero idle cost, auto-scaling, no server management |\n| **OpenRouter for LLM** | Single API for multiple models with built-in fallbacks |\n| **Socrata API (not scraping)** | Legal, reliable, structured government data |\n| **React + single-file HTML** | SPA for rich UX; file:// option for demos without a server |\n| **GitHub Pages hosting** | Free, reliable, CI/CD via Actions |\n\n---\n\n## What Was Built\n\n### Deployed and Working ✅\n\n- 6 Lambda functions — Properties, Cities, Metadata, Chat, Analyze, Describe\n- CT Open Data Socrata API — real-time queries to 211K+ property records\n- AI-powered natural language search — queries automatically extract structured filters\n- React SPA — deployed to GitHub Pages with CI/CD\n- Production UAT tests — automated Playwright suite running against GitHub Pages\n\n### Code Written, Not Yet Deployed 📝\n\n| Feature | Lambda File | Notes |\n|---------|-------------|-------|\n| Redfin Market Data | `redfin-ingestion.ts` | Code complete, not in SAM template |\n| Street View Photos | `street-view-fetch.ts` | Code complete, not in SAM template |\n\n---\n\n## Quick Start\n\n### 1. Deploy AWS Infrastructure\n\n```bash\ncd infrastructure\n./aws-setup.sh\n```\n\n### 2. Configure API Keys\n\n```bash\naws secretsmanager update-secret \\\n  --secret-id home-harbor/api-keys-dev \\\n  --secret-string '{\n    \"OPENROUTER_API_KEY\": \"sk-or-v1-YOUR-KEY\",\n    \"GOOGLE_MAPS_API_KEY\": \"AIzaSy-YOUR-KEY\"\n  }'\n```\n\n- **OpenRouter:** [openrouter.ai/keys](https://openrouter.ai/keys) (free tier available)\n- **Google Maps:** [console.cloud.google.com](https://console.cloud.google.com/apis/credentials)\n\n### 3. Deploy Lambda Functions\n\n```bash\ncd lambda \u0026\u0026 npm install \u0026\u0026 npm run build \u0026\u0026 npm run deploy\n```\n\n### 4. Run the UI\n\nOpen [public/index.html](public/index.html) directly in your browser. No local server required. To connect to live data, update the `HOME_HARBOR_CONFIG` block inside the HTML with your API Gateway base URL.\n\n---\n\n## Lambda Functions\n\n| Function | File | Description |\n|----------|------|-------------|\n| **Properties** | `properties-socrata.ts` | Real-time search via CT Open Data. GET /properties, /cities, /metadata. 211K+ records. |\n| **Chat** | `chat.ts` | Natural language → structured filters. POST /chat. Llama 3.3 70B with fallbacks. |\n| **Analyze** | `analyze.ts` | AI vision analysis of property photos. POST /analyze. Molmo 72B. |\n| **Describe** | `describe.ts` | AI property descriptions. POST /describe. Llama 3.3 70B. |\n| **Redfin Ingestion** | `redfin-ingestion.ts` | Monthly market data from Redfin Data Center. *(Code complete, not deployed)* |\n| **Street View** | `street-view-fetch.ts` | Google Street View exterior photos. *(Code complete, not deployed)* |\n\n---\n\n## Tech Stack\n\n### AWS Services\n\n| Service | Purpose |\n|---------|---------|\n| Lambda | Serverless compute (Node.js 20) |\n| DynamoDB | NoSQL cache with on-demand scaling |\n| S3 | Object storage for data and images |\n| CloudFront | Global CDN |\n| EventBridge | Scheduled automation |\n| Secrets Manager | Encrypted API key storage |\n\n### AI \u0026 Frontend\n\n| Technology | Purpose |\n|-----------|---------|\n| OpenRouter | LLM API gateway (free tier) |\n| Llama 3.3 70B | Text generation and filter extraction |\n| Molmo 72B | Vision model for image analysis |\n| CT Open Data (Socrata) | 211K+ Connecticut property records |\n| React 18 + Vite | Frontend SPA (31 components) |\n| TypeScript 5 | Type-safe Lambda code |\n| Tailwind CSS 3 | Styling |\n| Playwright | E2E and production UAT tests |\n\n---\n\n## Cost Breakdown\n\n| Service | Monthly Usage | Cost |\n|---------|--------------|------|\n| Lambda | 10 executions | $0.00 (free tier) |\n| DynamoDB | 5K items | $0.00 (free tier) |\n| S3 | 500 MB | $0.00 (free tier) |\n| CloudFront | 1 GB transfer | $0.00 (free tier) |\n| OpenRouter AI | 1200 requests | $0.00 (free tier) |\n| **Total** | | **$0.00/month** |\n\n---\n\n## Testing\n\n```bash\nnpm test                 # Jest unit tests with coverage\nnpm run test:e2e         # Playwright E2E against local mock server\nnpm run test:uat         # Playwright UAT against GitHub Pages (production)\nnpm run test:uat:headed  # UAT with visible browser\n```\n\n---\n\n## Project Structure\n\n```\nhome-harbor/\n├── public/                   # Single-file UI (works via file://)\n│   └── index.html            # 1477 lines — complete UI with embedded data\n├── frontend/                 # React frontend (Vite)\n│   └── src/\n│       ├── App.jsx\n│       ├── components/       # 31 React components\n│       └── hooks/\n├── lambda/                   # Serverless functions (TypeScript)\n│   └── src/\n│       ├── properties-socrata.ts\n│       ├── chat.ts\n│       ├── analyze.ts\n│       └── describe.ts\n├── infrastructure/\n│   └── aws-setup.sh\n├── tests/\n└── docs/\n    ├── DATA_SOURCES.md\n    ├── LESSONS_LEARNED.md\n    └── CHANGELOG.md\n```\n\n---\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [QUICKSTART.md](QUICKSTART.md) | Step-by-step deployment guide |\n| [IMPLEMENTATION_SUMMARY.md](IMPLEMENTATION_SUMMARY.md) | What was built and why |\n| [docs/DATA_SOURCES.md](docs/DATA_SOURCES.md) | Data sourcing strategy |\n| [docs/LESSONS_LEARNED.md](docs/LESSONS_LEARNED.md) | Development insights and hard-won lessons |\n\n---\n\n## About\n\n**Curtis Franks** — Full-stack software engineer specializing in serverless AWS architecture and AI integration.\n\n- Portfolio: [curtisfranks.com](https://curtisfranks.com)\n- LinkedIn: [linkedin.com/in/curtisfranks](https://linkedin.com/in/curtisfranks)\n\n---\n\n## License\n\n**[PolyForm Noncommercial 1.0.0](LICENSE)** — free for personal, educational, and non-commercial use. Commercial use requires a paid license. See [COMMERCIAL-LICENSE.md](COMMERCIAL-LICENSE.md) or contact [curtisfranks@gmail.com](mailto:curtisfranks@gmail.com).\n\n© 2026 Curtis Franks\n\n---\n\n*Built with ☕ and curiosity · February 2026*\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchf3198%2Fhome-harbor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchf3198%2Fhome-harbor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchf3198%2Fhome-harbor/lists"}