PropertyShop is an intelligent property search application that uses AI agents to gather, analyze, and present comprehensive real estate data.
- Conversational Search: Chat with an AI concierge to specify your property requirements
- Multi-Agent System: Coordinated agents handle different aspects of property search
- Real-time Updates: Progressive loading of results as data becomes available
- Comprehensive Data:
- Property listings from Zillow
- Walk scores for each property
- Crime statistics by zip code
- Property tax rates by county
- Median rent comparisons
- School district grades (optional)
- Design preference matching with AI vision analysis
The application consists of two main components:
- Landing page with chat interface
- Results page with multiple data grids
- Real-time updates via Server-Sent Events (SSE)
- Agent A1 (Concierge): Orchestrates the search and interacts with users
- Agent A2 (Property Search): Searches Zillow via Apify actors
- Agent A5 (Tax Rates): Scrapes property tax data
- Agent A7 (Design Match): Analyzes property images with Claude vision API
- Tool A3 (Rent/Schools): Scrapes rent and school data from niche.com
- Tool A4 (Walkability): Scrapes walk scores from walkscore.com
- Tool A6 (Crime Stats): Scrapes crime data from crimegrade.org
- Node.js 18+ and npm
- Python 3.11+
- Claude API key (from Anthropic)
- Apify API key
-
Clone the repository
cd property_shop -
Set up environment variables
cp .env.local.example .env.local
Edit
.env.localand add your API keys:CLAUDE_API_KEY: Your Anthropic Claude API keyAPIFY_ZZCSS_KEY: Your Apify API key
-
Install Python dependencies
cd python pip install -r requirements.txt -
Install Node.js dependencies
cd .. npm install
You need to run both the Python backend and Next.js frontend:
-
Start the Python backend (in one terminal):
cd python python main.pyThe backend will start on
http://localhost:8000 -
Start the Next.js frontend (in another terminal):
npm run dev
The frontend will start on
http://localhost:3000 -
Open your browser to
http://localhost:3000
- Landing Page: Enter your initial property search request or click the help button to start chatting
- Chat Interface: Answer the concierge's questions about your preferences:
- Property type (residential/commercial)
- Target zip code (required)
- School district importance
- Crime rate concerns
- Design preferences
- Confirmation: Review and confirm your preferences
- Results Page: Watch as results stream in real-time:
- Property listings appear first
- Additional data (crime, tax, rent, schools) loads progressively
- Design matches are calculated if preferences were specified
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS
- Server-Sent Events (SSE)
- Python 3.11+
- FastAPI
- Agno (multi-agent framework)
- Claude Sonnet 4 (Anthropic)
- BeautifulSoup4 (web scraping)
- Apify (Zillow data)
GET /health- Health checkPOST /chat- Send message to concierge agentPOST /search- Start property search and return SSE streamDELETE /session/{session_id}- Delete a search session
property_shop/
├── app/ # Next.js frontend
│ ├── page.tsx # Landing page
│ ├── components/
│ │ └── ChatInterface.tsx # Chat overlay
│ └── results/
│ ├── page.tsx # Results page
│ ├── components/ # Grid components
│ └── hooks/
│ └── useSearchResults.ts # SSE hook
├── python/ # Python backend
│ ├── main.py # FastAPI server
│ ├── config.py # Configuration
│ ├── agents/ # AI agents
│ │ ├── a1_concierge.py
│ │ ├── a2_property_search.py
│ │ ├── a5_tax_rates.py
│ │ └── a7_design_match.py
│ ├── tools/ # Agent tools
│ │ ├── a3_rent_schools.py
│ │ ├── a4_walkability.py
│ │ └── a6_crime_stats.py
│ └── utils/ # Utilities
│ ├── apify_client.py
│ └── geocoding.py
└── .env.local # Environment variables (create from .env.local.example)
- Web scraping may be rate-limited or blocked by some sites. The application includes 1-second delays between requests.
- Some data sources may not always be available or may return "unable to find" for certain locations.
- The Apify actors require a valid Apify account and API key.
- Claude API usage will incur costs based on your Anthropic plan.
This application requires separate deployments for the frontend and backend since they use different technologies.
-
Push your code to GitHub
-
Import to Vercel
- Go to vercel.com
- Import your repository
- Vercel will auto-detect Next.js
-
Set Environment Variables in Vercel
- In your Vercel project settings, add:
NEXT_PUBLIC_API_URL: Your deployed backend URL (see below)- Example:
https://your-app.railway.app
-
Deploy
- Vercel will automatically build and deploy your frontend
The Python FastAPI backend needs to be deployed to a service that supports Python applications. Here are recommended options:
-
Create a
Procfilein thepython/directory:web: uvicorn main:app --host 0.0.0.0 --port $PORT -
Create a
runtime.txtin thepython/directory:python-3.11.0 -
Deploy to Railway:
- Go to railway.app
- Connect your GitHub repository
- Set the root directory to
python/ - Add environment variables:
CLAUDE_API_KEYAPIFY_ZZCSS_KEY
- Railway will automatically detect and deploy your FastAPI app
-
Update Vercel Environment Variable:
- Copy your Railway app URL (e.g.,
https://your-app.railway.app) - Add it as
NEXT_PUBLIC_API_URLin Vercel
- Copy your Railway app URL (e.g.,
-
Create a
render.yamlin the project root:services: - type: web name: property-shop-api env: python buildCommand: cd python && pip install -r requirements.txt startCommand: cd python && uvicorn main:app --host 0.0.0.0 --port $PORT envVars: - key: CLAUDE_API_KEY sync: false - key: APIFY_ZZCSS_KEY sync: false
-
Deploy:
- Go to render.com
- Connect your repository
- Render will use the
render.yamlconfiguration
-
Install Fly CLI and login:
curl -L https://fly.io/install.sh | sh fly auth login -
Create a
fly.tomlin thepython/directory:app = "property-shop-api" [build] [env] PORT = "8000" [[services]] internal_port = 8000 protocol = "tcp" [[services.ports]] port = 80 handlers = ["http"] [[services.ports]] port = 443 handlers = ["tls", "http"]
-
Deploy:
cd python fly launch fly secrets set CLAUDE_API_KEY=your_key APIFY_ZZCSS_KEY=your_key fly deploy
The backend already has CORS enabled in main.py. Verify it includes your Vercel domain:
app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, restrict to your Vercel domain allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )
For production, update allow_origins to:
allow_origins=["https://your-app.vercel.app", "http://localhost:3000"],
CORS errors in production:
- Verify
NEXT_PUBLIC_API_URLis set correctly in Vercel - Check that your backend CORS settings include your Vercel domain
- Ensure the backend is actually running and accessible
Local development CORS errors: Make sure the Python backend is running on port 8000 and the Next.js frontend on port 3000.
Missing API keys: Check that environment variables are set in both Vercel (frontend) and your backend service.
Web scraping failures: Some sites may block automated requests. Consider using VPN or adjusting user agents in the scraping tools.
Geocoding issues: The free Nominatim service may be rate-limited. Add delays or use a paid geocoding service for production.
EventSource/SSE connection failures:
- Ensure the backend URL is correct
- Some hosting providers may have timeout limits on SSE connections
- Check browser console for specific error messages
This project is for educational purposes.