Overview
A multi-store price tracker: save product URLs and background scrapers periodically re-fetch prices into a shared database, so you get in-app + email alerts when a price drops below your threshold — with per-product price history. It currently covers Indian fashion & streetwear stores, with plans to expand to Amazon, Flipkart, and other major sites. v1.
- Track products across multiple e-commerce sites; background scrapers re-fetch prices on a schedule into a shared Supabase (Postgres) database.
- In-app + email price-drop alerts (Resend) with per-user thresholds, plus a hand-rolled SVG price-history chart.
- Multi-process architecture: an Express API, a Node 5-site scraper loop, and two Python (FastAPI) scraper microservices.
- Built with a friend — I owned the per-site scrapers (all sites except Myntra & Ajio), the alerts + email pipeline, and the React frontend.
The problem
Tracking prices across multiple e-commerce sites is manual and easy to forget — and a single current price tells you nothing about whether it's actually a good deal.
My approach
Users save product URLs; background scrapers periodically re-fetch prices into a shared Supabase Postgres DB, store per-product history, and fire in-app + email alerts when a price drops below the user's threshold.
What I owned
Built with a friend. I built the per-site scrapers for every site except Myntra & Ajio (his Python service), the in-app + email alert pipeline, and the React frontend. He owns the two Python scrapers and — after migrating the database from Firebase to Supabase — the bulk of the API layer.
The hard part
We shipped a single Culture Circle scraper in two days, then hit the wall: every site has its own page structure and anti-bot defenses, so one scraper can't cover them all. That pushed me into a scraper-per-site architecture and the tooling around it — concurrency pooling, proxies, headless vs. headful browsers, Playwright/Puppeteer. My toughest piece was Nykaa: Akamai blocks plain HTTP, so I drove it with a singleton Puppeteer browser, a page pool, and request interception (blocking images/CSS/fonts); my Souled Store scraper degrades gracefully — pricing is mandatory, inventory/detail best-effort.
Architecture
Three independent processes write to one shared Supabase DB: an Express API (JWT-authed, with a cron email worker), a Node scraper loop covering five sites, and two Python FastAPI microservices (Myntra, Ajio). A two-tier Supabase client enforces per-user row-level security.
Why I built it
I started this mainly to learn real Git/GitHub collaboration — branching, forking, stashing — having only ever used add/commit/push on main as a solo dev. A friend who knew version control suggested we build something together; we brainstormed, he pitched the price scraper, and I picked up scraping architecture along the way.
Architecture — four services, one shared database
Add a product URL · Supabase JWT on every request
Auth gate + RLS · intake router · atomic price/alert RPCs · Resend email cron
5 sites via detectSite dispatch · 3× retry, then DLQ
Myntra + Ajio · FastAPI · own async scrape loops
products · user_products · price history · alerts · failed-scrape DLQ (RLS-enforced)
Four independent processes that never call each other (except API→Python for intake) — they coordinate only by reading and writing the shared Postgres tables.
v1 with 9–10 sites listed — NOT in production. Honest flags: the core alert-evaluation logic lives in Supabase RPCs that aren't version-controlled; Firebase is leftover reference code from before my friend's Supabase migration (auth is Supabase); no automated tests yet.