The Problem

Businesses and hobbyists who want to monitor product prices across arbitrary e‑commerce sites lack a self‑hosted solution that can reliably extract the correct price, especially when sites use dynamic layouts, promotional text, or anti‑scraping measures.

What This Does

PriceGhost is a full‑stack TypeScript application that scrapes a product URL with four parallel strategies—JSON‑LD, site‑specific selectors, generic CSS, and AI‑driven analysis—then presents the candidates in a “price voting” modal for user confirmation.

Backend logic lives in backend/src/ (e.g., services/scraper.ts, services/ai-extractor.ts, routes/products.ts). The API is served from backend/src/index.ts and uses JWT authentication (middleware/auth.ts).

Frontend UI is built with React (TSX) under frontend/src/; key components such as PriceSelectionModal.tsx, ProductCard.tsx, and PriceChart.tsx render the voting interface and dashboards. The entry point is frontend/src/main.tsx, compiled by Vite (frontend/vite.config.ts).

How To Use It

Setup

Clone the repo git clone https://github.com/yourorg/PriceGhost.git cd PriceGhost

Build containers (Docker is the only required runtime)

docker compose build

The docker-compose.yml pulls the two service images defined by backend/Dockerfile and frontend/Dockerfile.

Configuration

Copy the example env file and fill in required values:

cp backend/.env.example backend/.env edit backend/.env: DATABASEURL=postgres://user:pass@db:5432/priceghost JWTSECRET=your‑secret AI_ENDPOINT=... (if AI extraction is enabled)

The database migration script backend/src/config/init-db.ts runs automatically on container start; an initial schema is provided in database/init.sql.

Running

docker compose up -d Backend API: http://localhost:4000/api (exposed by backend/Dockerfile). Frontend UI: http://localhost:3000 (served by Nginx as defined in frontend/nginx.conf).

Stop with docker compose down.

Real‑World Use

A small retailer wants to track competitor pricing for 200 SKUs. They deploy PriceGhost on a VPS, add product URLs via the UI, and enable AI extraction. A nightly cron (implemented in services/scheduler.ts) re‑scrapes each URL, stores price history in PostgreSQL, and sends Slack notifications via services/notifications.ts when a price drops below a target.

// Example: schedule a price check import { scheduleJob } from 'node-schedule'; import { scrapeAndStore } from './services/scraper';

scheduleJob('0 2 ', () => scrapeAndStore(productId));

Code Health & Issues

Med – No test suite – No files under tests or .test.*; CI workflow (.github/workflows/docker-build.yml) only builds images, not runs tests. Med – Missing license – Repository root lacks a LICENSE file, creating uncertainty around redistribution. Low – Potential secret leakage – .env.example is present, but actual secrets are not version‑controlled; ensure production env files are never committed. Low – Limited input validation – Routes (e.g., routes/products.ts) rely on raw request bodies; adding schema validation (e.g., Zod) would tighten security. Low – Docker health checks absent – Dockerfiles do not define HEALTHCHECK, making container failure detection harder.

No obvious syntax errors; TypeScript configs (backend/tsconfig.json, frontend/tsjson) are present and the code compiles locally.

The Bottom Line

PriceGhost delivers a functional, containerized price‑tracking stack with a novel multi‑method extraction workflow. It is ready for small‑to‑medium deployments where self‑hosting and AI‑augmented scraping are required, but the lack of automated tests, a license, and some validation safeguards mean additional engineering effort is advisable before production use in regulated environments.