Project Info
Inspiration
A big part of our inspiration was taken from AirBnb and the features and issues that the app had solved. Yet, when re-imagining it as if it were built in 2025 within the big age of AI, it felt intuitive to have incorporated AI into streamlining the grueling process of real estate. From a consumer side, it's often difficult to parse through thousands of different listings just to be able to find someplace safe, affordable, and available for you to stay at during a vacation. From a seller's side, the process ranging from having to manually obtain sample photos of your property to deciding how much to charge when you have zero prior experience in selling a property, is both challenging and difficult.
What it does
Homi makes it easy for guests to find safe, affordable stays and helps hosts showcase their properties to maximize profit through the following features... AI agents curating personalized, potential homes for consumers to stay at AI agents automating the listing process, removing any headache from a first time seller.
How we built it
Homi is built entirely on a FastAPI backend and Next.js frontend. The backend itself runs on uvicorn with REST API + Websocket endpoints. Core Technical Implementations For usage of real-time object detection we employ the use of YOLOv8n. An open-source model coming from a large family of similar object detection usage. This model runs server-side with session-based aggregation storing detections in-memory with frame metadata. We also use this to capture and later transmit images as data URIs over WSS. We employ Groq llama 3.3 70b to extract structured search params (location, dates, guests, price) from natural language. A state machine then tracks missing params, and triggers follow-up questions through the use of Anthropic's Claude Sonnet 4.5. Once complete, params trigger Elasticsearch hybrid search with relevance threshold filtering. Another key feature is our Tinder-style swiping interface. Using Framer Motion gesture handlers on React client. each swipe tracked to Supabase + Letta for preference learning. Saved listings auto-ranked using Claude with contextual reasoning (price drops, preference alignment, availability, etc.)
Challenges we ran into
AirBnb itself doesn't offer open API keys to students and therefore, we had to be clever in the ways in which we obtained the listing data. We had to pivot a couple of times. Beginning from an AR-powered application, we were unfortunate in our attempts to try and automate machine learning workflows on-top of our hardware and obtain outputs in a server-less environment. We then centered ourselves around an AI-native approach through the use of open-source models and AI agents.
Accomplishments we're proud of
Creating a fully, custom designed, suite. One that incorporates elements from every single one of us meaning that this project is entirely our own. Arriving to a finished product, as a deliverable isn't always promised despite that being the entire point of Hackathons. Doing this with two first-time Hackathon attenders nonetheless!
What we learned
Lots, and lots about hardware. Hardware, in the form of AR glasses, served as one of the main axioms and previous "invariants" to our product as it enabled custom pricing for listings as well as customer previews; having a hand in both buyer + seller workflows. Also, since one of our teammates had a background as a designer we really could delegate a lot more time into making a User-focused design + maintain a Product-focused mindset. These two paired together resulted in a beautiful UI made with users in mind to appease their life and make using our application all that much easier.
What's next
Globalization! Currently Homi is only available for US locations. A future plan that we've all thought about is how we can globalize Homi for any person hoping to find a nice place to stay without all of that headache associated.
Homi - Conversational Vacation Rental Search
The Problem
Over 80% of Airbnb hosts are individuals, not companies. Many list only one property—a family beach house, a mountain cabin they inherited, a spare room in their home. These everyday people lack the time or design skills to create professional listings. They're stuck filling endless forms, writing descriptions that sound generic, guessing at competitive prices, and hoping their amateur iPhone photos attract bookings.
On the flip side, guests scroll endlessly through hundreds of listings, clicking through 20+ photos per property, trying to feel a vibe from static images. They toggle through 50+ filter dropdowns, read descriptions that all say "cozy" and "charming," and still can't tell if a place actually matches what they're looking for.
The process is slow, unpersonalized, and fundamentally outdated.
What if listing and finding vacation rentals didn't have to take hours?
What We Built
Homi reimagines vacation rental search as a conversation, not a form. Instead of toggling filters, you describe what you want. Instead of scrolling endlessly, you swipe through intelligently matched properties. Instead of guessing at pricing and amenities, AI handles it automatically.
We built four key innovations that make this possible:
Prompt-Based Semantic Search Say goodbye to keyword matching. We trained our search to understand what you mean, not just what you say. Ask for "a cozy place with beach vibes" and it finds properties with ocean views and hammocks, even if the listing never uses those exact words. The system uses vector embeddings to understand intent—it's like having a friend who actually gets what you're looking for instead of a robot that only knows exact matches.
Smart Mapping with Dynamic Radius Ever search for "San Francisco" and get results in San Jose 50 miles away? We built a geocoding system that understands city sizes. Search for NYC and it looks within 35 miles (because NYC is huge). Search for Napa and it keeps it tight at 15 miles (because that's the whole valley). The system automatically maps over 40 US cities to GPS coordinates and adjusts search radius based on how sprawling or compact each city actually is.
AI-Powered Dynamic Pricing Hosts don't have to guess what to charge anymore. Our pricing engine analyzes market rates for similar properties, calculates demand patterns (weekends vs weekdays, holiday premiums), and suggests competitive pricing with actual reasoning: "Similar 3-bedroom beach houses in your area go for $350-$450. Your ocean view and hot tub justify $380 on weekends. Holiday season? Bump it to $450."
Real-Time Object Detection for Listings When hosts create listings, our vision system scans uploaded photos to automatically detect amenities. Upload a photo of your backyard and it spots the pool, hot tub, and BBQ grill. Show it your kitchen and it recognizes modern appliances and granite countertops. The system identifies over 50 property features automatically—no more manually checking boxes for every amenity. It also scores image quality, filtering out blurry shots and keeping only the best angles.
What Makes It Different
Traditional vacation rental search:
- Toggle through 50+ filter dropdowns
- Scroll through endless listings
- Read generic descriptions
- No learning or personalization
Homi:
- Describe what you want in plain English (or by voice)
- Swipe through intelligently matched results
- System learns your preferences
- Auto-organized saved listings
How It Works
1. Conversational Search
Instead of filter menus, just describe what you want:
You: "Beach house in California"
Homi: "When are you planning to visit?"
You: "Next weekend, 3 people"
Homi: "What's your budget per night?"
You: "Under $300"
The system extracts structured parameters (location, dates, guests, budget) from natural language across multiple conversation turns.
2. Semantic Search & Matching
Uses vector embeddings to understand intent beyond keywords:
- "Beach house with hot tub" matches properties even with different wording
- Geographic radius filtering (dynamic based on city size)
- Relevance threshold filtering (only show quality matches)
- Hybrid approach: semantic + keyword + structured filters
3. Swipe Interface
Results displayed in Tinder-inspired cards showing:
- Photo carousel
- Amenities
- Location + distance
- Price per night
- Beds/baths
- Rating
Swipe right = save, left = pass. System learns from swipe patterns.
4. Preference Learning
Tracks behavior to improve future searches:
- Swipe patterns (what features do you like?)
- Search history (typical destinations, budgets)
- Automatically incorporates learned preferences into future searches
5. Auto-Organized Favorites
Saved listings automatically sorted by:
- Original search relevance
- Learned preferences
- Current availability
- Price changes
Technical Architecture
Frontend Stack
- Framework: Next.js 16 (App Router)
- Language: TypeScript, React 19
- Styling: Tailwind 4
- Key Libraries: Framer Motion (swipe gestures), Vapi SDK (voice)
Key Routes:
/discover/text- Text-based conversational search/discover/voice- Voice input with push-to-talk/discover/swipe- Tinder-esque property cards/sell- Host listing creation (simulated)
Backend Stack
- Framework: FastAPI (Python)
- Validation: Pydantic models
- Architecture: Service-oriented with dependency injection
Core Services:
ConversationService (services/conversation_service.py)
- Multi-turn dialogue management
- Parameter extraction using Claude
- Follow-up question generation
- State tracking across conversation
VisionService (services/vision_service.py)
- Image quality scoring
- Amenity detection from photos
- Multi-image analysis
LettaService (services/letta_service.py)
- User memory and context
- Preference learning from swipe patterns
- Historical search patterns
PricingService (services/pricing_service.py)
- Market rate analysis
- Competitive pricing recommendations
- Calendar-based pricing strategies
VoiceService (services/voice_service.py)
- Audio transcription via Groq Whisper
- Push-to-talk interface support
Search & Data Layer
ElasticClient (utils/elastic_client.py)
- Vector embeddings for semantic search
- Hybrid search (semantic + keyword + filters)
- Geo-radius filtering
- Relevance scoring
SupabaseClient (utils/supabase_client.py)
- PostgreSQL database (listings, users, swipes)
- Object storage (images)
- User session management
Geocoding (utils/geocoding.py)
- City name → GPS coordinates
- Dynamic radius calculation by city size
- 40+ US cities mapped
AI Models
Anthropic Claude Sonnet 4.5
- Conversational search dialogue
- Parameter extraction
- Content generation
- Vision analysis
Groq
- Fast parameter extraction (Llama)
- Audio transcription (Whisper)
- Real-time inference requirements
Vapi
- Voice synthesis (11labs)
- Speech-to-speech interface
- Push-to-talk implementation
Elasticsearch Vector Search
- Semantic embeddings
- K-NN similarity search
- Filtered vector queries
Key API Endpoints
Search Flow:
POST /api/search/conversation
- Input: user message, conversation history, extracted params so far
- Output: assistant response, updated params, missing params, search status
POST /api/search/execute
- Input: extracted params, relevance threshold
- Output: ranked listings above threshold
POST /api/voice-to-text
- Input: audio file (webm)
- Output: transcribed text
User Tracking:
POST /api/swipe
- Input: user_id, listing_id, action (like/pass), metadata
- Output: success confirmation
- Side effect: Updates Letta with preference data
GET /api/saved-listings/{user_id}
- Output: Auto-ranked saved listings with reasoning
Voice Interface:
GET /api/vapi/public-key
- Output: Vapi public key for client initialization
GET /api/vapi/assistant
- Output: Assistant configuration (voice, model, system prompt)
Data Flow
Conversational Search Flow
1. User Input (text or voice)
↓
2. ConversationService.process_message()
- Calls Claude with conversation history
- Extracts parameters from user message
- Validates extracted params (location not multi-city, guests reasonable, etc)
- Merges with previously extracted params
- Checks if all required params collected
↓
3a. If params incomplete:
- Generate follow-up question for next missing param
- Return question + quick-reply suggestions
3b. If params complete:
- Signal ready_to_search
- Proceed to search execution
↓
4. Search Execution
- Build semantic query from params
- Generate embedding
- Query Elasticsearch with filters + vector search
- Apply geo-radius if location specified
- Filter by relevance threshold
- Rank results
↓
5. Return Results
- Top matches as swipeable cards
- Store search in user history (Letta)
Voice Interface Flow
1. User clicks mic button
↓
2. MediaRecorder captures audio
↓
3. User clicks again to stop
↓
4. Audio blob sent to /api/voice-to-text
↓
5. Groq Whisper transcribes
↓
6. Transcription sent to /api/search/conversation
(same flow as text search)
↓
7. Assistant response returned
↓
8. Vapi speaks response (11labs voice)
↓
9. Repeat for multi-turn conversation
Swipe Learning Flow
1. User swipes right/left on listing
↓
2. POST /api/swipe with action + listing metadata
↓
3. If swipe right:
- Save to user's favorites (Supabase)
- Send to Letta with full listing details
4. Letta analyzes pattern:
- Preferred amenities (pools, hot tubs, etc)
- Price range
- Property types (house vs apartment)
- Locations
↓
5. Future searches:
- Boost listings matching learned preferences
- Pre-fill common parameters
- Suggest locations based on history
Getting Started
Backend Setup
cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Add API keys to .env
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Required Environment Variables:
ANTHROPIC_API_KEY=sk-ant-...
GROQ_API_KEY=gsk_...
ELASTIC_CLOUD_ID=...
ELASTIC_API_KEY=...
SUPABASE_URL=https://...
SUPABASE_KEY=...
VAPI_API_KEY=...
VAPI_PUBLIC_KEY=...
Frontend Setup
cd frontend
npm install
npm run dev
Database Seeding
cd backend
python seed_data.py # Seeds Elasticsearch + Supabase with 40 listings
Dataset: 40 vacation rental listings across 30 US cities with GPS coordinates
Project Structure
vibe/
├── frontend/
│ ├── app/
│ │ ├── discover/
│ │ │ ├── text/page.tsx # Text-based search UI
│ │ │ ├── voice/page.tsx # Voice interface with Vapi
│ │ │ └── swipe/page.tsx # Tinder-inspired cards
│ │ ├── sell/ # Host flow (demo only)
│ │ └── components/ # Shared UI components
│ └── lib/
│ └── api.ts # API client wrapper
│
├── backend/
│ ├── main.py # All route handlers
│ ├── services/
│ │ ├── conversation_service.py # Multi-turn search
│ │ ├── vision_service.py # Image analysis
│ │ ├── letta_service.py # User memory
│ │ ├── pricing_service.py # Market analysis
│ │ └── voice_service.py # Transcription
│ ├── utils/
│ │ ├── elastic_client.py # Search engine
│ │ ├── supabase_client.py # Database
│ │ └── geocoding.py # GPS mapping
│ ├── agents/fetch_agents/ # Autonomous agents
│ ├── seed_data.py # Database seeding
│ └── test_*.py # Test scripts
│
└── README.md
Development & Testing
Running Tests
cd backend
# Test conversational search
python test_buyer_seller_flows.py
# Test geo-search with all cities
python test_geo_direct.py
# Test full integration
python test_comprehensive.py
Architecture Decisions
Why FastAPI?
- Native async/await support for concurrent API calls
- Automatic OpenAPI docs
- Pydantic validation
- Fast enough for hackathon scale
Why Next.js 16 App Router?
- Server + client components
- Built-in routing
- TypeScript support
- Fast refresh for development
Why Elasticsearch?
- Vector search with hybrid queries
- Geographic filtering
- Scalable to millions of listings
- Rich query DSL
Why Claude Sonnet 4.5?
- Best-in-class conversation capabilities
- Excellent parameter extraction
- Vision API for image analysis
- Long context windows for conversation history
Why Groq?
- Fastest inference (important for real-time feel)
- Good enough for parameter extraction
- Whisper for audio transcription
Performance Considerations
Conversational Search: ~1-2s response time (Claude API call) Search Execution: ~500ms (Elasticsearch query + ranking) Voice Transcription: ~1-2s (Groq Whisper) Voice Synthesis: ~1-3s (Vapi 11labs)
Optimizations:
- Conversation state cached client-side
- Elasticsearch results cached (5min TTL)
- Lazy loading for images
- Optimistic UI updates for swipes
Built for CalHacks 2025
Analysis
View
Metric
- 42
- 23
- 6
- 1
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FastAPIIn code
- HTMLIn code
- Next.jsIn code
- OpenAIIn code
- PythonIn code
- ReactIn code
- SupabaseIn code
- Tailwind CSSIn code
- TypeScriptIn code
11 of 11 appear in the indexed code.
AI coding agents
- Claude CodeConfig · Commits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
959 KB
Source files
122
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
thenerd31/homi
172 files · 3.9 MB · @ 2890a62
Structure
Interface
37 files · 22%Screens, components and styles rendered to the user.
API & routing
1 file · 1%Request entry points: routes, handlers and controllers.
Application logic
57 files · 33%Domain rules, services and shared utilities.
+1 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python39%
- TypeScript36%
- Markdown20%
- HTML5%
- CSS0%
- Shell0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
backend/requirements.txt
pypi · 27- aiohttp
- anthropic
- arize-phoenix
- cosmpy
- elasticsearch
- fastapi
- groq
- httpx
- letta
- numpy
- openai
- opencv-python
- openinference-instrumentation-anthropic
- opentelemetry-api
- opentelemetry-sdk
- pillow
- psycopg2-binary
- pydantic
- +9 more
frontend/package.json
npm · 22- @emotion/react
- @emotion/styled
- @mui/icons-material
- class-variance-authority
- clsx
- framer-motion
- lucide-react
- next
- react
- react-dom
- tailwind-merge
- +11 more
package.json
npm · 1- gl-matrix
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.