A full-stack web application for tracking and managing Idealista.com property listings during home hunting. Save properties, add personal notes, rate them, schedule visits, and organize your property search with AI-powered bioclimatic analysis.
- 📋 Property Scraping: Automatically fetch property details from Idealista.com URLs using Apify
- 🔐 User Authentication: Secure email/password authentication with Supabase
- 💾 Cloud Database: All data stored in Supabase with Row Level Security (RLS)
- 📝 Personal Notes: Add notes and thoughts for each property
- ⭐ Star Ratings: Rate properties from 1-5 stars
- 💚 Enthusiasm Score: Track your excitement level (1-10) for each property
- 🔄 Duplicate Prevention: Won't add the same property twice
- 📊 Kanban Board: Visual workflow with 4 stages (New → Scheduled → Visited → Archived)
- 📅 Visit Scheduling: Schedule property visits with date picker
- ✅ Visit Tracking: Mark properties as visited with date
- 🔄 Reschedule/Cancel: Easily reschedule or cancel visits
- 📦 Archive Management: Archive properties and restore when needed
- 🤖 Window Analysis: AI-powered window and bioclimatic analysis using Gemini Vision API
- 🏠 Bioclimatic Scoring: Automated scoring based on window quality, orientation, and energy features
- 💡 Smart Recommendations: Get AI-generated recommendations for energy improvements
- 📸 Image Analysis: Upload property photos for detailed window and energy analysis
- 📱 Responsive Design: Works on desktop and mobile devices
- 🔄 Data Migration: Seamlessly migrate from localStorage to cloud database
- ⚡ Real-time Updates: Optimistic UI updates with React Query
- 🎨 Modern UI: Clean, intuitive interface with drag-and-drop ready architecture
Frontend:
- React 19 + TypeScript
- Vite (build tool)
- React Query (@tanstack/react-query) - data fetching & caching
- Supabase Client (@supabase/supabase-js) - authentication & database
- CSS (custom styling with modern layouts)
Backend:
- Node.js + Express
- TypeScript
- Apify API (Idealista.com scraper)
- Google Gemini Vision API - AI image analysis
- Supabase - PostgreSQL database with RLS policies
Database:
- Supabase (PostgreSQL)
- Row Level Security (RLS) policies
- Automated triggers for timestamps and analysis storage
- Node.js (v18 or higher)
- npm or yarn
- Apify API token (get one here)
- Supabase project (create one here)
- Google Gemini API key (get one here)
Frontend:
npm installBackend:
cd server
npm install- Create a new project at supabase.com
- Run the database migrations in the Supabase SQL Editor:
- Execute
supabase/migrations/001_initial_schema.sql - Execute
supabase/migrations/002_rls_policies.sql - Execute
supabase/migrations/003_triggers.sql
- Execute
- Get your Supabase URL and anon key from Project Settings > API
Frontend .env:
cp .env.example .envEdit .env:
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
Backend server/.env:
cd server
cp .env.example .envEdit server/.env:
APIFY_API_TOKEN=your_apify_token_here
GEMINI_API_KEY=your_gemini_api_key_here
PORT=3001
Terminal 1 - Backend:
cd server
npm run devBackend will run on http://localhost:3001
Terminal 2 - Frontend:
npm run devFrontend will run on http://localhost:5173
- Open http://localhost:5173 in your browser
- Sign up for a new account or log in
- If you have existing localStorage data, you'll be prompted to migrate it
- Paste an Idealista.com property URL into the form
- Click "Add Property" and wait for the data to load
- Properties appear in the "New" column of the Kanban board
- Add notes, ratings, and enthusiasm scores to your properties
- Schedule visits by clicking "Schedule Visit" and selecting a date
- Mark properties as visited or archive them
- Upload property photos for AI-powered window analysis (optional)
capstone/
├── src/ # Frontend React app
│ ├── components/ # React components
│ │ ├── auth/ # Authentication components
│ │ │ ├── AuthPage.tsx # Auth page wrapper
│ │ │ ├── LoginForm.tsx # Login form
│ │ │ └── SignUpForm.tsx # Sign up form
│ │ ├── KanbanBoard.tsx # Main Kanban board
│ │ ├── KanbanColumn.tsx # Individual Kanban column
│ │ ├── PropertyTile.tsx # Property card in Kanban
│ │ ├── PropertyCard.tsx # Detailed property view (legacy)
│ │ ├── PropertyForm.tsx # URL input form
│ │ └── MigrationPrompt.tsx # localStorage migration UI
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.ts # Authentication hook
│ │ └── useProperties.ts # Property data & mutations
│ ├── lib/ # Library configuration
│ │ ├── supabase.ts # Supabase client
│ │ └── queryClient.ts # React Query client
│ ├── types/ # TypeScript interfaces
│ ├── utils/ # Utility functions
│ │ ├── localStorage.ts # localStorage helpers
│ │ └── migration.ts # Data migration utilities
│ ├── services/ # API client
│ ├── App.tsx # Main app component
│ └── main.tsx # Entry point
├── server/ # Backend Express API
│ └── src/
│ ├── routes/ # API endpoints
│ │ ├── properties.ts # Property scraping
│ │ └── analysis.ts # Window analysis
│ ├── services/ # External services
│ │ ├── apifyService.ts # Apify integration
│ │ └── geminiService.ts # Gemini Vision API
│ └── index.ts # Server entry point
├── supabase/ # Database configuration
│ └── migrations/ # SQL migrations
│ ├── 001_initial_schema.sql
│ ├── 002_rls_policies.sql
│ └── 003_triggers.sql
├── CLAUDE.md # Documentation for Claude Code
└── TODO.md # Project roadmap
npm run dev- Start development servernpm run build- Build for productionnpm run lint- Run ESLintnpm run preview- Preview production build
npm run dev- Start development server with hot reloadnpm run build- Compile TypeScriptnpm start- Run production server
- User authenticates with Supabase
- User pastes Idealista.com property URL
- Frontend sends URL to backend API
- Backend calls Apify actor to scrape property data
- Scraped data is returned to frontend
- Frontend saves property to Supabase database with user metadata
- Property appears in "New" column of Kanban board
- User uploads property photos
- Frontend sends image to backend
/api/analysis/windowendpoint - Backend processes image with Gemini Vision API
- AI analyzes windows, glazing, orientation, and energy features
- Bioclimatic score and recommendations generated
- Results stored in database and displayed to user
- Row Level Security (RLS) ensures users only see their own properties
- Supabase handles authentication and session management
- All database operations are protected by RLS policies
Scrape property data from Idealista.com URL
Request:
{
"url": "https://www.idealista.com/..."
}Response:
{
"success": true,
"data": { /* property data */ }
}Analyze property photos for window quality and bioclimatic features using Gemini Vision API
Request:
{
"imageUrl": "https://example.com/property-photo.jpg",
"propertyId": "uuid"
}Response:
{
"success": true,
"analysis": {
"windows": {
"frame_material": "aluminum",
"glazing_type": "double",
"window_to_wall_ratio": 0.25,
"size": "medium",
"condition": "good",
"confidence": 0.85
},
"energy_features": {
"shutters": true,
"external_shading": false,
"modern_features": ["tilt-and-turn"]
},
"orientation": {
"estimated": "south",
"confidence": 0.7,
"reasoning": "Based on light patterns..."
},
"bioclimatic_score": {
"score": 7.5,
"strengths": ["Good natural light", "Double glazing"],
"weaknesses": ["No external shading"]
},
"recommendations": [
{
"action": "Install external blinds",
"priority": "medium",
"estimated_cost": "€500-800",
"annual_savings": "€150-200/year"
}
]
}
}Health check endpoint
- Frontend proxies
/api/*requests to backend during development (configured invite.config.ts) - Property data schema is flexible - stores whatever Apify returns
- Each property gets a UUID from Supabase
- React Query manages data fetching, caching, and mutations
- Optimistic updates provide instant UI feedback
- RLS policies in Supabase ensure data isolation between users
- Window analysis uses Gemini 2.5 Flash model for multimodal (vision + text) analysis
- All timestamps are managed by Supabase triggers
Backend won't start:
- Check that
server/.envexists and has validAPIFY_API_TOKENandGEMINI_API_KEY - Ensure port 3001 is not already in use
- Verify all dependencies are installed:
cd server && npm install
Frontend won't start:
- Check that
.envexists and has validVITE_SUPABASE_URLandVITE_SUPABASE_ANON_KEY - Verify all dependencies are installed:
npm install
Authentication issues:
- Verify Supabase project is active and URL/key are correct
- Check Supabase dashboard for authentication settings
- Ensure RLS policies are properly set up (run migrations)
Property scraping fails:
- Verify Apify token is valid and has sufficient credits
- Check that URL is from Idealista.com
- Look at browser console and server logs for errors
Window analysis not working:
- Verify
GEMINI_API_KEYis valid inserver/.env - Check that Gemini API is enabled in your Google Cloud project
- Ensure image URLs are accessible
- Check server logs for Gemini API errors
Data not persisting:
- Verify Supabase connection is working
- Check browser network tab for failed API calls
- Ensure RLS policies allow your user to insert/update data
- Check Supabase dashboard logs for errors
Migration from localStorage:
- Migration prompt should appear automatically if localStorage data exists
- Data is copied (not moved) - original localStorage data remains
- Check browser console for migration errors
MIT