DealDrop is a modern web application that allows users to track product prices from any e-commerce website and receive instant email alerts when prices drop. Built with Next.js, Supabase, and Firecrawl, it provides a seamless experience for monitoring deals and saving money.
- Universal Product Tracking: Track products from any e-commerce site (Amazon, Walmart, etc.)
- Automatic Price Monitoring: Daily cron job checks prices and updates product information
- Price History Visualization: Interactive charts showing price trends over time
- Email Alerts: Get notified instantly when prices drop below your tracked price
- User Authentication: Secure Google OAuth authentication via Supabase
- Modern UI: Beautiful, responsive interface built with Tailwind CSS and shadcn/ui components
- Real-time Updates: Server-side rendering with automatic revalidation
- Next.js 16 - React framework with App Router
- React 19 - UI library
- TypeScript - Type-safe development
- Tailwind CSS 4 - Utility-first CSS framework
- shadcn/ui - High-quality component library
- Recharts - Chart library for price visualization
- Sonner - Toast notifications
- Lucide React - Icon library
- Supabase - Backend-as-a-Service (Authentication, Database)
- Firecrawl - Web scraping service for product data extraction
- Resend - Email delivery service for price drop alerts
- Vercel - Deployment platform (recommended)
- Biome - Fast linter and formatter
- TypeScript - Static type checking
dealdrop/
βββ src/
β βββ app/ # Next.js App Router
β β βββ actions/ # Server actions
β β β βββ boundary.ts # Access control utilities
β β β βββ get-me.ts # Get current user
β β β βββ logout.ts # User logout
β β β βββ products.ts # Product CRUD operations
β β βββ api/ # API routes
β β β βββ cron/
β β β βββ check-price/
β β β βββ route.ts # Cron job for price checking
β β βββ auth/
β β β βββ callback/
β β β βββ route.ts # OAuth callback handler
β β βββ layout.tsx # Root layout
β β βββ page.tsx # Home page
β β βββ globals.css # Global styles
β βββ components/ # React components
β β βββ ui/ # shadcn/ui components
β β βββ AddProductForm.tsx # Product addition form
β β βββ AuthButton.tsx # Authentication button
β β βββ AuthModal.tsx # Login modal
β β βββ PriceChart.tsx # Price history chart
β β βββ ProductCard.tsx # Product display card
β βββ lib/ # Utility libraries
β β βββ email.ts # Email sending utilities
β β βββ firecrawl.ts # Web scraping utilities
β βββ types/ # TypeScript type definitions
β β βββ product.ts # Product-related types
β βββ utils/ # Helper utilities
β β βββ supabase/ # Supabase client utilities
β β βββ utils.ts # General utilities
β βββ proxy.ts # Middleware for session management
βββ public/ # Static assets
βββ .gitignore
βββ biome.json # Biome configuration
βββ components.json # shadcn/ui configuration
βββ next.config.ts # Next.js configuration
βββ package.json # Dependencies
βββ postcss.config.mjs # PostCSS configuration
βββ tsconfig.json # TypeScript configuration
- Node.js 18+ and npm/yarn/pnpm
- Supabase account and project
- Firecrawl API key
- Resend API key (for email alerts)
-
Clone the repository
git clone <repository-url> cd dealdrop
-
Install dependencies
npm install # or yarn install # or pnpm install
-
Set up environment variables
Create a
.env.localfile in the root directory:# Supabase Configuration NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your_supabase_anon_key SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key # Firecrawl API FIRECRAWL_API_KEY=your_firecrawl_api_key # Resend Email Service RESEND_API_KEY=your_resend_api_key RESEND_FROM_EMAIL=noreply@yourdomain.com # Cron Job Security CRON_SECRET=your_random_secret_string # Application URL (for email links) NEXT_PUBLIC_APP_URL=http://localhost:3000
-
Set up Supabase Database
Create the following tables in your Supabase project:
Products Table:
CREATE TABLE products ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, url TEXT NOT NULL, name TEXT NOT NULL, current_price DECIMAL(10, 2) NOT NULL, currency TEXT NOT NULL DEFAULT 'USD', image_url TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(user_id, url) ); CREATE INDEX idx_products_user_id ON products(user_id);
Price History Table:
CREATE TABLE price_history ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE, price DECIMAL(10, 2) NOT NULL, currency TEXT NOT NULL, checked_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_price_history_product_id ON price_history(product_id); CREATE INDEX idx_price_history_checked_at ON price_history(checked_at);
Enable Row Level Security (RLS):
-- Enable RLS on products table ALTER TABLE products ENABLE ROW LEVEL SECURITY; -- Users can only see their own products CREATE POLICY "Users can view own products" ON products FOR SELECT USING (auth.uid() = user_id); -- Users can insert their own products CREATE POLICY "Users can insert own products" ON products FOR INSERT WITH CHECK (auth.uid() = user_id); -- Users can update their own products CREATE POLICY "Users can update own products" ON products FOR UPDATE USING (auth.uid() = user_id); -- Users can delete their own products CREATE POLICY "Users can delete own products" ON products FOR DELETE USING (auth.uid() = user_id); -- Enable RLS on price_history table ALTER TABLE price_history ENABLE ROW LEVEL SECURITY; -- Users can view price history for their products CREATE POLICY "Users can view own price history" ON price_history FOR SELECT USING ( EXISTS ( SELECT 1 FROM products WHERE products.id = price_history.product_id AND products.user_id = auth.uid() ) );
-
Configure Supabase OAuth
- Go to your Supabase project dashboard
- Navigate to Authentication > Providers
- Enable Google OAuth
- Add your OAuth credentials
- Add
http://localhost:3000/auth/callbackto redirect URLs (for development) - Add your production URL to redirect URLs (for production)
-
Run the development server
npm run dev # or yarn dev # or pnpm dev
-
Open your browser
Navigate to http://localhost:3000
| Variable | Description | Required |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL | Yes |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Supabase anon/public key | Yes |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key (for cron jobs) | Yes |
FIRECRAWL_API_KEY |
Firecrawl API key for web scraping | Yes |
RESEND_API_KEY |
Resend API key for sending emails | Yes |
RESEND_FROM_EMAIL |
Email address to send alerts from | Yes |
CRON_SECRET |
Secret token for securing cron endpoint | Yes |
NEXT_PUBLIC_APP_URL |
Your application URL (for email links) | Yes |
Stores tracked products for each user.
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
user_id |
UUID | Foreign key to auth.users |
url |
TEXT | Product URL |
name |
TEXT | Product name |
current_price |
DECIMAL | Current price |
currency |
TEXT | Currency code (USD, BDT, INR, etc.) |
image_url |
TEXT | Product image URL |
created_at |
TIMESTAMP | Creation timestamp |
updated_at |
TIMESTAMP | Last update timestamp |
Stores historical price data for chart visualization.
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
product_id |
UUID | Foreign key to products |
price |
DECIMAL | Price at check time |
currency |
TEXT | Currency code |
checked_at |
TIMESTAMP | When price was checked |
- Users can paste any product URL from supported e-commerce sites
- Firecrawl extracts product name, price, currency, and image
- Product is added to user's tracking list
- Initial price is recorded in price history
- Cron job runs daily (configure via Vercel Cron or external service)
- Checks all products in the database
- Updates current prices
- Records price changes in history
- Sends email alerts when prices drop
- Email alerts are sent automatically when a price drops
- Alert includes:
- Product name and image
- Previous and current price
- Price drop percentage
- Amount saved
- Direct link to product
- Interactive line charts showing price trends
- Accessible via drawer component on product cards
- Displays historical price data over time
Automated price checking endpoint for cron jobs.
Authentication: Bearer token via Authorization header
curl -X POST https://your-domain.com/api/cron/check-price \
-H "Authorization: Bearer YOUR_CRON_SECRET"Response:
{
"success": true,
"message": "Price check completed. X products updated, Y price changes, Z alerts sent",
"results": {
"total": 10,
"updated": 9,
"failed": 1,
"priceChanges": 3,
"alertsSent": 2
}
}OAuth callback handler for Supabase authentication.
-
Push your code to GitHub
-
Import project to Vercel
- Go to vercel.com
- Click "New Project"
- Import your GitHub repository
-
Configure environment variables
- Add all environment variables from
.env.local - Set
NEXT_PUBLIC_APP_URLto your Vercel deployment URL
- Add all environment variables from
-
Set up Cron Job
Create
vercel.jsonin the root directory:{ "crons": [ { "path": "/api/cron/check-price", "schedule": "0 9 * * *" } ] }Or use Vercel Cron Jobs dashboard to configure:
- Schedule: Daily at 9 AM UTC (or your preferred time)
- Endpoint:
/api/cron/check-price - Authorization: Bearer token with your
CRON_SECRET
-
Deploy
- Vercel will automatically deploy on every push to main branch
If not using Vercel Cron, you can use external services like:
Configure them to POST to /api/cron/check-price with the Authorization header.
npm run dev- Start development servernpm run build- Build for productionnpm run start- Start production servernpm run lint- Run Biome linternpm run format- Format code with Biome
This project uses Biome for linting and formatting. Configuration is in biome.json.
- Row Level Security (RLS) is enabled on all database tables
- Users can only access their own products and price history
- Cron endpoint is protected with bearer token authentication
- Service role key is only used server-side for cron jobs
- OAuth authentication via Supabase
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is private and proprietary.
- Next.js - React framework
- Supabase - Backend services
- Firecrawl - Web scraping
- shadcn/ui - UI components
- Resend - Email delivery
For issues, questions, or contributions, please open an issue on the repository.
Built with β€οΈ using Next.js and Supabase