AI that plans your weekend in Singapore 🎉
🌐 Live App: https://vibeplan-app.vercel.app/
🔌 API Endpoint: https://vibeplan-chromadb-api.onrender.com
🎥 Video Demo: Watch a quick walkthrough (Open Beta)
VibePlan is an AI-powered activity recommendation tool that helps you discover the perfect things to do in Singapore. Whether you're planning a budget date, a family weekend, or just looking for something fun to do, VibePlan personalizes recommendations based on your preferences, budget, and vibe.
🔥 What sets VibePlan apart: Unlike other AI planners that rely on Google or outdated listings, VibePlan taps directly into live social media feeds (Telegram, Instagram) to catch Singapore's hottest deals, hidden gems, and viral spots as they appear. Our automated data ingestion pipeline continuously scrapes, normalizes, and vectorizes trending content, so new pop-ups, 1-for-1 promos, or café launches surface within hours, not weeks.
Visit the live app at vibeplan-app.vercel.app and try these sample prompts:
- "Plan a date under $50 with food, something artsy, and outdoors."
- "Weekend brunch spots with good vibes for 4 people."
- "Chill activities for introverts under $30."
- "Adventurous outdoor activities with a spicy nightlife twist."
The app pulls from 500+ live activities scraped from Singapore's social channels and combines them with real-time web search for the freshest recommendations!
- 🤖 AI-Powered Recommendations - Get personalized activity suggestions based on your preferences
- 💰 Budget-Aware - Filter activities from "Broke Student" to "Atas Boss" budgets
- 🎨 Multiple Activity Types - Outdoor, Sports, Shopping, Food, Museums, Thrift Stores, Artsy venues, and Games
- 👥 Group Size Support - Plan for solo adventures or group activities
- 🧠 MBTI Matching - Optional personality-based recommendations
- 🌶️ Spicy Option - Include nightlife and drinks recommendations
- 📅 Date Range Selection - Plan activities for specific dates
- 📱 Responsive Design - Optimized for both desktop and mobile
- 🔐 Google Authentication - Sign in with your Google account via Supabase
- 📜 Search History - Keep track of your past searches
- Framework: Next.js 14+ with App Router
- Language: TypeScript
- Styling: Tailwind CSS
- UI Components: shadcn/ui
- Authentication: Supabase Auth
- Fonts: Instrument Sans (body) & Instrument Serif (emphasis)
- Icons: Lucide React
- Database: Supabase (PostgreSQL) for user data
- Vector Database: ChromaDB for RAG (Retrieval-Augmented Generation)
- AI/LLM: OpenAI GPT-4o for curation, GPT-3.5-turbo for normalization
- Search Engine: Exa API for real-time content discovery
- Embeddings: OpenAI text-embedding-3-small for vector search
- Telegram Scraping: Telethon (asyncio-based Telegram API client)
- Instagram Scraping: Selenium + ChromeDriver for post content extraction
- Content Normalization: OpenAI GPT-3.5-turbo for LLM-based structuring
- URL Processing: Parallel URL expansion and link classification
- Data Storage: SQLAlchemy + SQLite for staging, ChromaDB for vector storage
- Automation: APScheduler for weekly batch scraping and daily processing
- Maps: Google Maps API for location services
- Authentication: Google OAuth via Supabase
- Real-time Data: Exa API for current activity information
- Social Media: Telegram API integration for trending activities
- RAG System: ChromaDB + OpenAI for intelligent activity matching
- Web Scraping: Selenium for automated venue data collection
- Social Monitoring: Telethon for real-time social media trends
- Content Curation: AI-powered activity database management
🚀 Quick Start: Try the live app at vibeplan-app.vercel.app - no setup required!
👨💻 For Developers: Follow the instructions below to set up a local development environment.
- Node.js 18+ installed
- npm or yarn package manager
- Python 3.9+ installed
- pip (Python package manager)
- A Supabase account (free tier works!)
- OpenAI API key
- Exa API key
- Clone the repository:
git clone https://github.com/yourusername/vibeplan.git
cd vibeplan- Install Node.js dependencies:
npm install- Install Python dependencies:
pip3 install -r requirements.txt- Set up environment variables:
Create a .env.local file in the root directory with the following variables:
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
# AI & Search APIs
EXA_API_KEY=your_exa_api_key
OPENAI_API_KEY=your_openai_api_key
# Google Services (Optional)
GOOGLE_MAPS_API_KEY=your_google_maps_api_key
# Social Media & Scraping (Optional)
TELEGRAM_API_ID=your_telegram_api_id
TELEGRAM_API_HASH=your_telegram_api_hashSee the Supabase Setup section below for detailed instructions.
VibePlan requires two servers to run:
- ChromaDB FastAPI Bridge (Port 8001) - Handles vector database queries
- Next.js Development Server (Port 3000) - Main web application
Terminal 1 - ChromaDB FastAPI Bridge:
python3 chromadb_api.pyTerminal 2 - Next.js Server:
npm run devStart ChromaDB Bridge in background:
python3 chromadb_api.py &Start Next.js:
npm run devOnce both servers are running, open http://localhost:3000 in your browser.
Health Check:
- Local Development:
- Next.js: http://localhost:3000
- ChromaDB API: http://localhost:8001/health
- Production:
- Website: https://vibeplan-app.vercel.app/
- ChromaDB API: https://vibeplan-chromadb-api.onrender.com/health
The data ingestion pipeline scrapes Telegram channels and Instagram posts to populate the ChromaDB with fresh activities.
cd data_ingestion
# Install Python dependencies
pip3 install -r requirements.txt
# Initialize database tables
python main.py setup
# Add Telegram channels to scrape
python main.py add-channel sgdeals
python main.py add-channel sgfoodie
python main.py add-channel sgcafehopping
# Or load channels from environment variable
# Set TELEGRAM_CHANNELS in .env first
python main.py load-channels# Run the scraping pipeline once
python main.py run-once
# Test specific components
python main.py test-telegram # Test Telegram connection
python main.py test-instagram <url> # Test Instagram scraping
# View statistics
python main.py stats # Show scraping statistics
python main.py list-channels # List configured channels# Start the automated scheduler (runs weekly)
python main.py start-scheduler
# This will:
# 1. Scrape Telegram channels every 168 hours (weekly)
# 2. Process and normalize content daily
# 3. Update ChromaDB with new activitiesNote: The data ingestion pipeline requires:
- Valid Telegram API credentials (get from https://my.telegram.org)
- OpenAI API key for content normalization
- ChromeDriver for Instagram scraping (automatically managed)
- Go to https://supabase.com/dashboard
- Click "New Project"
- Fill in your project details:
- Project name:
vibeplan(or any name you prefer) - Database password: Create a strong password
- Region: Choose the closest to your users (e.g., Singapore)
- Project name:
- Click "Create new project"
- Once your project is created, go to Settings > API
- Copy the following values:
- Project URL (under "Project URL")
- anon/public key (under "Project API keys")
- Add these to your
.env.localfile:
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-hereTo enable Google sign-in:
- Go to Authentication > Providers in your Supabase dashboard
- Find "Google" in the list and click to configure
- Toggle "Enable Google provider" to ON
- You'll need to create OAuth credentials in Google Cloud Console:
- Go to Google Cloud Console
- Create a new project or select an existing one
- Navigate to APIs & Services > Credentials
- Click Create Credentials > OAuth 2.0 Client ID
- Configure the OAuth consent screen if prompted
- Choose Web application as the application type
- Add the following to Authorized redirect URIs:
https://your-project-ref.supabase.co/auth/v1/callback - Copy the Client ID and Client Secret
- Paste them into the Supabase Google provider settings
- Click "Save"
- Go to Authentication > URL Configuration
- Add your site URL (for development:
http://localhost:3000) - Add redirect URLs:
http://localhost:3000/auth/callback(for development)- Add your production URL when deploying
VibePlan uses a FastAPI bridge to access ChromaDB from Next.js, bypassing webpack compatibility issues.
┌─────────────────────────────────────────────────────────────────┐
│ DATA INGESTION (Background) │
├─────────────────────────────────────────────────────────────────┤
│ Telegram → Instagram → LLM Normalize → Embed → ChromaDB │
│ (Daily batch scraping + daily processing) │
└─────────────────────────────────────────────────────────────────┘
↓
┌──────────────────┐
│ ChromaDB │
│ 500+ Activities │
│ Vector Storage │
└────────┬─────────┘
│
┌────────────────────────────┴────────────────────────────────────┐
│ RECOMMENDATION ENGINE (Real-time) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User Request → Next.js API → FastAPI Bridge → ChromaDB Search │
│ ↓ ↓ │
│ Exa Search Vector Search │
│ (5 results) (15 results) │
│ ↓ ↓ │
│ └───────── GPT-4o Curator ────┘ │
│ ↓ │
│ 4-6 Final Activities │
│ with Timeline │
└─────────────────────────────────────────────────────────────────┘
-
Data Population (Background):
- Weekly: Scrape Telegram channels → Extract Instagram links → Scrape posts
- Daily: Normalize content with GPT-3.5 → Generate embeddings → Store in ChromaDB
- Result: Always-fresh database of 381+ activities from social sources
-
User Query (Real-time):
- Semantic Keywords: User preferences (MBTI, budget, group size) enriched into semantic keywords
- Dual Data Sources:
- ChromaDB: 15 curated activities from social data (Telegram + Instagram)
- Exa API: 5 real-time web results for fresh content
- LLM Curation: GPT-4o selects 4-6 best activities and creates timeline
- Enhancement: AI estimates prices and generates engaging summaries
chromadb_api.py- FastAPI bridge server (port 8001 locally, deployed on Render)src/app/api/generate/utils/chromaClient.ts- HTTP client for ChromaDB APIsrc/app/api/generate/utils/keywords.ts- Semantic keyword buildersrc/app/api/generate/utils/llmCurator.ts- GPT-4o activity curationtest_chroma_api.py- Test script for semantic searchrequirements.txt- Python dependencies
- Frontend: https://vibeplan-app.vercel.app/
- ChromaDB API: https://vibeplan-chromadb-api.onrender.com
- Health Check: https://vibeplan-chromadb-api.onrender.com/health
- API Docs: https://vibeplan-chromadb-api.onrender.com/docs (FastAPI Swagger UI)
You can query the ChromaDB API directly for semantic search:
# Check API health
curl https://vibeplan-chromadb-api.onrender.com/health
# Search for activities
curl -X POST https://vibeplan-chromadb-api.onrender.com/search \
-H "Content-Type: application/json" \
-d '{
"query": "romantic date night with good food",
"n_results": 10
}'Response Example:
{
"activities": [
{
"title": "1-for-1 Dinner at Mellower Coffee",
"description": "Cozy cafe atmosphere with specialty coffee drinks",
"location": "Singapore",
"price": 25.0,
"tags": ["food", "coffee", "promotion"],
"source_channel": "@sgdeals",
"source_type": "instagram"
}
],
"query": "romantic date night with good food",
"count": 10
}vibeplan/
├── src/
│ ├── app/ # Next.js app directory
│ │ ├── about/ # About page
│ │ ├── api/ # API routes
│ │ │ └── generate/ # Activity generation endpoint
│ │ │ └── utils/ # ChromaDB, LLM, keywords utilities
│ │ ├── auth/ # Auth callback
│ │ ├── history/ # Search history page
│ │ ├── loading/ # Loading page with animation
│ │ ├── login/ # Login page
│ │ ├── profile/ # User profile page
│ │ ├── results/ # Activity results page
│ │ ├── signup/ # Signup page
│ │ ├── layout.tsx # Root layout with fonts
│ │ ├── page.tsx # Home page
│ │ └── globals.css # Global styles
│ ├── components/
│ │ ├── ui/ # shadcn/ui components
│ │ ├── ActivityCard.tsx # Activity display card
│ │ ├── FilterOptions.tsx # Search filters component
│ │ ├── MobileNav.tsx # Mobile navigation
│ │ └── Sidebar.tsx # Desktop sidebar
│ └── lib/
│ ├── supabase.ts # Supabase client
│ ├── supabase-server.ts # Supabase server client
│ └── utils.ts # Utility functions
├── data/
│ └── chroma_db/ # ChromaDB persistent storage
├── data_ingestion/ # Data scraping and ingestion pipeline
│ ├── src/
│ │ ├── scrapers/ # Data source scrapers
│ │ │ ├── base.py # Abstract scraper interface
│ │ │ ├── telegram_scraper.py # Telegram channel scraper
│ │ │ └── insta_normaliser.py # Instagram post scraper
│ │ ├── storage/ # Data storage layer
│ │ │ └── database.py # SQLAlchemy models & DB manager
│ │ ├── processing/ # Content processing
│ │ │ └── normalizer.py # LLM-based content normalizer
│ │ ├── scheduler.py # Automated scraping scheduler
│ │ └── config.py # Configuration management
│ ├── main.py # CLI interface for scraping
│ ├── requirements.txt # Python dependencies
│ └── README.md # Data ingestion documentation
├── chromadb_api.py # FastAPI bridge for ChromaDB
├── requirements.txt # Python dependencies (main)
├── test_chroma_api.py # ChromaDB query testing
├── test_chroma_queries.ipynb # Jupyter notebook for analysis
├── middleware.ts # Auth middleware
├── tailwind.config.ts # Tailwind configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Node.js dependencies
- Navigate to the home page
- Optional filters:
- Select activity types (Outdoor, Food, Artsy, etc.)
- Choose number of people
- Set your budget using the slider
- Select your MBTI type
- Toggle spicy option for nightlife
- Pick a date range
- Required: Describe what you're looking for in the search box
- Click the arrow button or press Enter
- Watch the cooking animation while AI generates recommendations
- Browse personalized activity cards with details
Try these prompts to get started:
- "Plan a date under $50 with food, something artsy, and outdoors."
- "Weekend brunch spots with good vibes for 4 people."
- "Chill activities for introverts under $30."
- "Adventurous outdoor activities with a spicy nightlife twist."
VibePlan's secret sauce is live, social, and trending data.
While other AI planners rely on Google or outdated listings, VibePlan taps directly into:
- Telegram - Singapore deal channels, pop-ups, and promotions
- Instagram - Visual content from trending posts and reels
- Exa.ai - Real-time web search for fresh content
- Social feeds - Catch hottest deals, hidden gems, and viral spots as they appear
We continuously scrape and structure these feeds so new pop-ups, 1-for-1 promos, or café launches surface within hours, not weeks.
┌─────────────────────────────────────────────────────────────────┐
│ DATA INGESTION PIPELINE │
└─────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ Telegram │
│ Channels │ (Batch: 100 messages/channel)
│ (Telethon) │
└──────┬───────┘
│
▼
┌──────────────────┐
│ Link Extraction │ (Regex + URL Expansion)
│ & Classification│
└──────┬───────────┘
│
├─────────────────────┬──────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Instagram │ │ Shortened │ │ Direct │
│ Links │ │ URLs │ │ Storage │
│ Detected │ │ Expanded │ │ (Telegram) │
└──────┬──────┘ └─────────────┘ └──────┬──────┘
│ │
▼ │
┌──────────────────┐ │
│ Instagram │ (Selenium + ChromeDriver) │
│ Post Scraper │ │
│ - Caption │ │
│ - Author │ │
│ - Images/Videos │ │
│ - Metadata │ │
└──────┬───────────┘ │
│ │
└─────────────────┬───────────────────────┘
▼
┌──────────────────┐
│ LLM Normalizer │
│ (GPT-3.5-turbo)│
│ │
│ - Extracts key │
│ information │
│ - Structures │
│ content │
│ - Removes noise │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Vector Embedding│
│ (OpenAI Ada-002)│
└────────┬─────────┘
│
▼
┌──────────────────┐
│ ChromaDB │
│ Vector Storage │
│ (500+ activities)│
└──────────────────┘
│
▼
┌──────────────────┐
│ FastAPI Bridge │
│ │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Next.js API │
│ /api/generate │
└──────────────────┘
- Technology: Telethon (Telegram API client)
- Scraping Strategy:
- Parallel channel scraping (up to 5 concurrent channels)
- 100 messages per channel per batch
- Automatic retry logic with exponential backoff
- Rate limiting to respect Telegram API limits
- Features:
- URL extraction using regex patterns
- Shortened URL expansion (bit.ly, t.co, etc.) with parallel processing
- Instagram link detection and classification
- Message deduplication
- Technology: Selenium + ChromeDriver
- Scraping Approach:
- Headless browser automation
- OpenGraph metadata extraction
- JSON-LD structured data parsing
- Data Extracted:
- Post caption and description
- Author username and name
- Upload date
- Image and video URLs
- Like and comment counts (when available)
- Anti-Detection:
- User-agent rotation
- Automation fingerprint removal
- CDP commands for stealth
- Model: GPT-3.5-turbo
- Purpose: Transform raw social media content into structured, searchable format
- Normalization Process:
- Extract main topic/subject
- Identify key facts and information
- Remove redundant details
- Structure information consistently
- Preserve important context
- Output: Clean, information-dense text optimized for vector search
-
Technology: SQLAlchemy + SQLite
-
Schema:
messages ├── id (Primary Key) ├── channel_username (String) ├── message_id (String, unique per channel) ├── text (Raw content) ├── normalized_text (LLM-processed) ├── links (JSON array) ├── source ("telegram" | "instagram") ├── date (Timestamp) ├── has_links (Boolean) ├── processed (Boolean) └── created_at (Timestamp) scraped_content ├── id (Primary Key) ├── message_id (Foreign Key) ├── url (Source URL) ├── content (Raw scraped content) ├── normalized_text (LLM-processed) └── scraped_at (Timestamp)
- Collection:
telegram_activities - Embedding Model: OpenAI
text-embedding-3-small - Storage: Persistent on-disk storage at
./data/chroma_db - Metadata Structure:
{ "full_data": { "title": "Activity Title", "description": "Normalized description", "location": "Singapore", "venue_name": "Venue Name", "price": 25.0, "tags": ["food", "cafe", "aesthetic"], "duration_hours": 2.0, "offer_type": "promotion", "validity_end": "2025-12-31", "source_channel": "@sgdeals", "source_type": "instagram", "source_link": ["https://instagram.com/p/..."] } }
- Technology: APScheduler (AsyncIO-compatible)
- Schedule:
- Weekly Scraping: Every 168 hours (configurable)
- Daily Processing: Every 24 hours for normalization
- Pipeline Flow:
- Scrape configured Telegram channels in parallel
- Extract and expand URLs
- Scrape Instagram posts from detected links
- Store raw content in SQLite
- Normalize content with LLM
- Generate embeddings and store in ChromaDB
1. Telegram Message Scraped:
"@sgdeals: 🔥 1-for-1 coffee at Mellower Coffee!
Valid till Dec 31. Check: https://instagram.com/p/xyz"
2. Link Detected & Expanded:
URL: https://instagram.com/p/xyz
Type: Instagram Post
3. Instagram Post Scraped:
Caption: "Our December special! Show this post for 1-for-1
on any coffee. Valid Mon-Fri 2-5pm."
Author: @mellowercoffeesg
Images: [coffee_photo_1.jpg, cafe_interior.jpg]
4. LLM Normalization:
"1-for-1 coffee promotion at Mellower Coffee in Singapore.
Valid December 2025, Monday to Friday 2-5pm. Show
Instagram post for redemption. Cozy cafe atmosphere,
specialty coffee drinks available."
5. Vector Embedding Generated:
[0.023, -0.041, 0.089, ...] (1536 dimensions)
6. Stored in ChromaDB:
{
"title": "1-for-1 Coffee at Mellower Coffee",
"description": "...",
"tags": ["food", "coffee", "promotion", "1-for-1"],
"price": 6.50,
"source_channel": "@sgdeals",
"source_type": "instagram",
"source_link": "https://instagram.com/p/xyz"
}
- Parallel Processing: Scrapes multiple channels and expands URLs concurrently
- Robust Error Handling: Automatic retries, exponential backoff, graceful degradation
- Rate Limiting: Respects API limits for Telegram, Instagram, and OpenAI
- Deduplication: Prevents duplicate entries using message IDs
- Incremental Updates: Only processes new content since last scrape
- Extensible Architecture: Easy to add new scrapers (TikTok, Lemon8, etc.)
Environment variables for data ingestion:
# Telegram API
TELEGRAM_API_ID=your_api_id
TELEGRAM_API_HASH=your_api_hash
TELEGRAM_PHONE=+65xxxxxxxx
TELEGRAM_CHANNELS=sgdeals,sgfoodie,sgcafehopping
# OpenAI for normalization and embeddings
OPENAI_API_KEY=sk-...
# Scraping configuration
MAX_MESSAGES_PER_CHANNEL=100
SCRAPING_INTERVAL_HOURS=168
# Database
DATABASE_URL=sqlite:///data_ingestion.dbVibePlan uses a sophisticated AI pipeline to deliver personalized recommendations:
- Vector Database: ChromaDB stores embeddings of 381+ activities and venues
- Semantic Search: Find similar activities based on user preferences
- Context-Aware: AI considers user's MBTI, budget, and activity history
- Real-time Augmentation: Combines ChromaDB results with Exa.ai live web search
- User Input Analysis: Parse preferences, budget, and natural language query
- Semantic Keywords: Enrich query with MBTI traits, budget signals, activity types
- Dual Data Sources:
- ChromaDB: 15 curated activities from social data (Telegram + Instagram)
- Exa API: 5 real-time web results for fresh content
- LLM Curation: GPT-4o selects 4-6 best activities and creates timeline
- Enhancement: AI estimates prices and generates engaging summaries
- Ranking & Filtering: Activities ranked by relevance and user preferences
Example API response format:
{
"activities": [
{
"id": 1,
"name": "Activity Name",
"description": "Activity description",
"category": "Food",
"price": "$20 per person",
"duration": "2-3 hours",
"location": "Location name",
"pax": "2 people",
"tags": ["Tag1", "Tag2"],
"imageUrl": "https://image-url.com"
}
],
"query": "user search query"
}VibePlan is deployed using a two-service architecture:
Live Site: https://vibeplan-app.vercel.app/
- Push your code to GitHub
- Go to vercel.com
- Import your repository
- Add environment variables:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key EXA_API_KEY=your_exa_api_key OPENAI_API_KEY=your_openai_api_key - Deploy!
Important: Update the ChromaDB API endpoint in src/app/api/generate/utils/chromaClient.ts to point to your Render deployment:
const CHROMA_API_URL =
process.env.CHROMA_API_URL || "https://vibeplan-chromadb-api.onrender.com";Live API: https://vibeplan-chromadb-api.onrender.com
- Go to render.com and create a new Web Service
- Connect your GitHub repository
- Configure the service:
- Build Command:
pip install -r requirements.txt - Start Command:
python chromadb_api.py - Environment: Python 3
- Build Command:
- Add environment variables:
OPENAI_API_KEY=your_openai_api_key ALLOWED_ORIGINS=https://vibeplan-app.vercel.app,http://localhost:3000 PORT=10000 - Deploy!
Note: Render uses port 10000 by default. The FastAPI server automatically uses PORT environment variable.
- ✅ Update Supabase auth settings with production URL:
https://vibeplan-app.vercel.app - ✅ Add redirect URL in Supabase:
https://vibeplan-app.vercel.app/auth/callback - ✅ Test ChromaDB API health endpoint: https://vibeplan-chromadb-api.onrender.com/health
- ✅ Verify CORS settings in
chromadb_api.pyinclude production domain - ✅ Test activity generation with production data
npm run buildnpm startnpm run lintRequired for the Next.js frontend and recommendation engine:
| Variable | Description | Required | Example |
|---|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL | ✅ Yes | https://xxxxx.supabase.co |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Your Supabase anonymous key | ✅ Yes | eyJhbGc... |
EXA_API_KEY |
Exa API key for real-time web search | ✅ Yes | c7f153... |
OPENAI_API_KEY |
OpenAI API key for AI processing | ✅ Yes | sk-... |
GOOGLE_MAPS_API_KEY |
Google Maps API key | ❌ No | AIza... |
Required for scraping Telegram channels and Instagram posts:
| Variable | Description | Required | Example |
|---|---|---|---|
TELEGRAM_API_ID |
Telegram API ID from https://my.telegram.org | ✅ Yes | 12345678 |
TELEGRAM_API_HASH |
Telegram API hash from https://my.telegram.org | ✅ Yes | abcdef123... |
TELEGRAM_PHONE |
Your Telegram phone number | ✅ Yes | +6591234567 |
TELEGRAM_CHANNELS |
Comma-separated channel list | ✅ Yes | sgdeals,sgfoodie |
OPENAI_API_KEY |
OpenAI API key for normalization | ✅ Yes | sk-... |
MAX_MESSAGES_PER_CHANNEL |
Messages to scrape per channel | ❌ No | 100 |
SCRAPING_INTERVAL_HOURS |
Hours between scraping runs | ❌ No | 168 |
DATABASE_URL |
SQLite database path | ❌ No | sqlite:///data_ingestion.db |
Note:
- Local Development: ChromaDB runs on
localhost:8001 - Production: ChromaDB API deployed at https://vibeplan-chromadb-api.onrender.com
- No additional configuration needed - the API automatically detects the environment
- Save activities to favorites
- Share activity plans with friends
- Export plans to calendar
- More detailed activity information
- User reviews and ratings
- Real-time availability checking
- Weather-based recommendations
- Interactive map integration
- Mobile app (React Native)
- TikTok Scraper - Capture trending food and cafe videos
- Lemon8 Scraper - Extract aesthetic spots and lifestyle content
- Reddit Integration - r/singapore recommendations and discussions
- Google Reviews API - Real-time ratings and reviews
- Event Platforms - Eventbrite, Peatix for upcoming events
- Food Delivery APIs - GrabFood, Deliveroo for restaurant data
- Real-time Availability - Integration with booking systems
- Price Monitoring - Track price changes and deal expiry
- Image Recognition - Classify venue types from photos
- Sentiment Analysis - Gauge popularity from social sentiment
Problem: Connection refused or fetch failed errors
Solutions for Local Development:
- Make sure the FastAPI bridge is running:
python3 chromadb_api.py - Check if port 8001 is available:
lsof -i :8001 - Verify the health endpoint:
curl http://localhost:8001/health
Solutions for Production:
- Check if Render service is running: Visit https://vibeplan-chromadb-api.onrender.com/health
- Verify environment variables are set in Render dashboard
- Check Render logs for errors in the service dashboard
- Ensure CORS origins include your Vercel domain:
https://vibeplan-app.vercel.app
Note: Render free tier services may spin down after inactivity. First request may take 30-60 seconds to wake up the service.
Problem: ModuleNotFoundError for fastapi, chromadb, etc.
Solution:
pip3 install -r requirements.txtProblem: OPENAI_API_KEY not found error
Solutions:
- Make sure
.env.localexists in the root directory - Verify the key is set correctly in
.env.local - Restart both servers after updating
.env.local
Problem: Collection 'telegram_activities' not found
Solution: You need the pre-populated ChromaDB database. Populate it using the data ingestion pipeline:
cd data_ingestion
python main.py setup
python main.py load-channels
python main.py run-onceProblem: Port 3000 is already in use or Port 8001 is already in use
Solutions:
# For Next.js (port 3000)
lsof -ti:3000 | xargs kill -9
# For FastAPI (port 8001)
lsof -ti:8001 | xargs kill -9Problem: Authentication failed or Phone number not authorized
Solutions:
- Verify API credentials from https://my.telegram.org
- Ensure phone number includes country code (e.g.,
+6591234567) - First run requires SMS verification - check your phone
- Session file
telegram_session.sessionstores auth - delete if corrupted
Problem: Instagram redirected to login or Selenium timeout
Solutions:
- Instagram requires ChromeDriver - ensure it's installed:
brew install chromedriver(macOS) - For private posts, set environment variables:
export IG_USERNAME=your_instagram_username export IG_PASSWORD=your_instagram_password
- Increase timeout in
insta_normaliser.pyif network is slow
Problem: OpenAI API timeout or Rate limit exceeded
Solutions:
- Check OpenAI API key is valid and has credits
- Rate limiting built-in (0.5s delay) - don't modify
- For large batches, increase
time.sleep()innormalizer.py
Problem: chromedriver not found or SessionNotCreatedException
Solutions:
# macOS
brew install chromedriver
# Linux
sudo apt-get install chromium-chromedriver
# Or download manually from:
# https://chromedriver.chromium.org/downloadsProblem: database is locked in SQLite
Solutions:
- Only run one scraping process at a time
- Check for zombie processes:
ps aux | grep python - Delete lock file if needed:
rm data_ingestion.db-journal
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ for the Singapore community