DealSniper is a full stack web app for tracking product prices. Users can create an account, log in, save product links, set target prices, and check whether an item is at or below their desired price.
- User signup and login with JWT authentication
- Protected dashboard for each user
- Add tracked products with:
- product URL
- target price
- optional title
- optional image URL
- View all tracked products
- Search tracked products by title or URL
- Delete tracked products
- Check the latest scraped price for a tracked product
- See whether an item is at or below the target price
- React
- Vite
- React Router
- Shadcn UI / Tailwind-style components
- Node.js
- Express
- PostgreSQL
- JWT authentication
- Puppeteer with stealth plugin for scraping
DealSniper/
frontend/
backend/
Create a .env file in your backend folder and add the following:
PORT=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
POSTGRES_PORT=
DATABASE_URL=
JWT_SECRET=
JWT_EXPIRES_IN=| Variable | Description |
|---|---|
PORT |
Port your backend server runs on |
POSTGRES_USER |
PostgreSQL username |
POSTGRES_PASSWORD |
PostgreSQL password |
POSTGRES_DB |
PostgreSQL database name |
POSTGRES_PORT |
PostgreSQL port |
DATABASE_URL |
Full PostgreSQL connection string |
JWT_SECRET |
Secret key used to sign JWT tokens |
JWT_EXPIRES_IN |
JWT expiration time, for example 1d |
git clone <your-repo-url>
cd DealSnipercd frontend
npm installcd ../backend
npm installA docker-compose.yml file is included to spin up the PostgreSQL database. Make sure Docker is installed and running, then start the database with:
docker compose up -dThe compose file reads directly from your .env file, so make sure it is filled out before running the command.
You should also create the required tables before running the app. For example, if your app uses a tracked_items table and a users table, make sure those exist in PostgreSQL.
Example schema:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE tracked_items (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
url TEXT NOT NULL,
target_price NUMERIC(10, 2) NOT NULL,
current_price NUMERIC(10, 2),
title TEXT,
image_url TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);From the backend folder:
npm run devFrom the frontend folder:
npm run dev- Open the frontend in your browser
- Create an account using the signup page
- Log in with your account credentials
- A JWT token will be stored in local storage after successful login
- Go to the dashboard
- Click Add Tracked Item
- Enter:
- product URL
- target price
- optional title
- optional image URL
- Submit the form
- Use the search bar on the dashboard
- Search by product title or URL
- Click Check now on a tracked item
- The app will scrape the product page and update the current price
- If the current price is less than or equal to the target price, the item will be marked as a deal
- Click Delete to remove a tracked item from your dashboard
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/auth/signup |
Create an account |
POST |
/api/auth/login |
Log in and receive a JWT |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/products |
Get all tracked items for the logged-in user |
POST |
/api/products |
Add a tracked item |
DELETE |
/api/products/:id |
Delete a tracked item |
PUT |
/api/products/:id/check |
Scrape and update the current price |
Protected routes require a bearer token.
Example header:
Authorization: Bearer your_jwt_token_here- Some ecommerce websites may block scraping or change their HTML structure
- Scraping works best on simpler product pages
- Large ecommerce sites may require more advanced scraping protections
- Automatic scheduled price checks
- Email or push notifications for deals
- Better store-specific scraping
- Price history charts
- Product image/title auto-fill
- Backend search and filtering
- Make sure the backend is running
- Make sure the frontend is calling the correct backend URL, such as
http://localhost:3000
- Make sure the user is logged in
- Make sure a valid JWT token exists in local storage
- Make sure the token is sent in the
Authorizationheader
- The website structure may not match your scraper logic
- The website may block bots
- Try testing with a simpler product page
Fawaz Rizwan