Headless price watcher for used music gear across marketplaces (Reverb, eBay, and Amazon), with alerts to Discord and an optional dashboard.
- Loads a watchlist from
config/watchlist.yml - Queries marketplaces via adapters (US sellers only to avoid tariff issues)
- Normalizes listings and applies keyword matching with include/exclude terms (supports regex)
- Filters by min/max price thresholds (optionally including shipping)
- Calculates market stats (min/max/avg/median) for price tracking outside thresholds
- De-duplicates alerts using
data/state.json - Price-drop alerts: Re-alerts when a previously-seen listing drops below threshold
- Sold tracking: Detects when listings disappear and marks them as sold in the dashboard
- Writes run history to
data/history.json - Sends Discord webhook alerts for new matches and price drops
- Runs on a schedule via Pipedream triggering GitHub Actions
- Install and build:
npm install npm run build
- Copy env and fill in values:
cp .env.example .env
- Run:
source .env && npm run watch
Required:
DISCORD_WEBHOOK_URL- Discord webhook for alertsREVERB_TOKEN- Reverb API token
Optional (enable additional marketplaces):
EBAY_CLIENT_ID/EBAY_CLIENT_SECRET- eBay Buy Browse API credentialsAMAZON_ACCESS_KEY/AMAZON_SECRET_KEY/AMAZON_PARTNER_TAG- Amazon PA-API 5.0 (requires Associate account)
Optional settings:
EBAY_ENV-production(default) orsandboxLOG_LEVEL-debug,info(default),warn, orerror
GitHub Actions scheduled workflows are notoriously unreliable—they often run late, skip runs entirely, or get deprioritized during high-traffic periods. To ensure consistent twice-hourly runs, this project uses Pipedream to trigger the GitHub Actions workflow via workflow_dispatch.
- Create a Pipedream workflow with a cron trigger (e.g., every 30 minutes)
- Add a step to trigger the GitHub Actions workflow using the GitHub API:
- Endpoint:
POST /repos/{owner}/{repo}/actions/workflows/watcher.yml/dispatches - Body:
{ "ref": "main" }
- Endpoint:
- Authenticate with a GitHub personal access token (needs
repoandworkflowscopes)
- Create a Discord webhook for the channel you want alerts in
- Add GitHub repo secrets (Settings > Secrets):
DISCORD_WEBHOOK_URLREVERB_TOKENEBAY_CLIENT_ID/EBAY_CLIENT_SECRET(optional)AMAZON_ACCESS_KEY/AMAZON_SECRET_KEY/AMAZON_PARTNER_TAG(optional)
- Adjust products & thresholds in
config/watchlist.yml - Workflows:
.github/workflows/watcher.yml- Price watching + dashboard deployment (triggered by Pipedream).github/workflows/ci.yml- Build validation on push/PR
Products are configured in config/watchlist.yml:
products:
- id: my-product
name: 'Product Name'
minPriceUsd: 100 # Skip listings below this (filters accessories)
maxPriceUsd: 500 # Alert threshold
marketplaces: ['reverb', 'ebay', 'amazon']
includeTerms: # At least one must match
- 'product name'
- 'alternate name'
- '/product\s*v\d+/i' # Regex pattern (wrapped in /.../)
excludeTerms: # None can match
- 'case'
- 'cover'
- 'parts'
- '/\bfor\s+parts\b/' # Regex patternRegex support: Terms wrapped in /pattern/ are treated as regular expressions. Flags can be added after the closing slash (e.g., /pattern/i for case-insensitive). By default, all regex patterns are case-insensitive.
- Reverb: Reverb API with Bearer token auth
- eBay: Buy Browse API with OAuth2 client credentials
- Amazon: Product Advertising API 5.0 with AWS Signature v4 (requires Associate account)
All adapters filter to US-based sellers only. If a marketplace fails, the run continues and reports errors in the summary.
Alerts are sent as rich embeds with:
- Listing title, image, and link
- Price, shipping, and effective total
- Marketplace and condition
- Threshold comparison
Price-drop alerts are highlighted with:
- Green color and 📉 emoji
- Previous price → new price with savings amount
- "PRICE DROP" label in footer
Sold tracking: When a previously-matched listing is no longer found in search results for 3 consecutive runs, it's marked as sold. Sold items display with a "SOLD" badge in the dashboard and are automatically cleaned up after 5 days.
The Next.js dashboard in apps/dashboard provides:
- Stats overview: Last run time, items scanned, alerts sent, errors
- Product cards: Each watched product with alert thresholds and market stats
- Market pricing: Live min/max/avg/median prices with sample listings
- Hits section: All matches under threshold, sorted by price (with SOLD badges for items no longer available)
- Activity charts: Scan activity and alerts over time (Recharts)
- Product filtering: Filter all views by product
- Dark mode: Automatic via system preference (no toggle needed)
Built with MUI (Material UI) and deployed as a static site.
Run locally:
cd apps/dashboard
npm install
npm run devGitHub Pages: The dashboard auto-deploys to GitHub Pages on each watcher run.
The project has comprehensive test coverage using Vitest:
- 115 tests across 11 test files
- 97%+ code coverage (statements, branches, functions, lines)
Run tests:
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage reportTest coverage includes:
- All marketplace adapters (eBay, Reverb, Amazon)
- Core modules (state management, config parsing, logging, matching)
- Discord notification delivery
- Retry logic and rate limiting
docs/PRD.md- Product requirementsdocs/ARCHITECTURE.md- System architecturedocs/QUERY_STRATEGY.md- Search strategy detailsdocs/DISCORD_EMBEDS.md- Discord message formatAGENTS.md- Instructions for coding agents
MIT License - see LICENSE for details.