When the scraper finds multiple valid prices (e.g., Amazon main price +
other sellers), skip AI verification entirely. AI was "correcting"
valid alternative prices to the main buy box price.
Now with multiple candidates, users see all options in the modal and
choose themselves - no AI interference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Amazon products can have multiple prices:
- Main buy box price
- "Other Sellers" prices
- Subscribe & Save prices
- New & Used prices
The scraper now extracts ALL prices, not just the main one. This allows
anchor price matching to find the specific price the user selected.
Also fixed AI verification overriding user's anchor price selection.
When user deliberately chose a price (e.g., "other sellers" at $52.91),
don't let AI "correct" it to the main buy box price ($79.99).
Changes:
- Amazon scraper now collects all price variants
- extractSiteSpecificCandidates handles allPrices array
- Anchor matching now always returns (no fall-through to AI override)
- Increased anchor tolerance from 10% to 15% for small sales
- Added debug logging showing all candidate prices
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous logic checked preferred method first, which could select
a wrong price even when anchor price was available. Now:
1. PRIORITY 1: Anchor price - if user confirmed a price, find closest
match (within 10% tolerance) across ALL candidates
2. PRIORITY 2: Preferred method - only used if no anchor match found
3. PRIORITY 3: Consensus voting
Also added debug logging to trace anchor price saving and retrieval.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a user confirms a price from the modal, we now store it as an
"anchor price". On subsequent refreshes, if multiple price candidates
are found (common with variant products like different sizes/colors),
we select the candidate closest to the anchor price.
This fixes the issue where variant products would randomly switch to
a different variant's price on refresh.
Changes:
- Add anchor_price column to products table
- Save anchor price when user confirms a price selection
- Use anchor price to select correct variant on refresh
- 20% tolerance - if no candidate is within 20% of anchor, fall back to consensus
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add prominent "You Choose the Price. Always." section at the top
- Explain the 4-method extraction system (JSON-LD, site-specific, CSS, AI)
- Detail the Price Selection Modal and its benefits
- Compare to competitors (Keepa, CamelCamelCamel, Honey)
- Add new "Multi-Strategy Price Extraction" feature section
- Add "Supported Retailers" table with browser rendering info
- Mention AI Arbitration as a new capability
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix TypeScript narrowing issue in Best Buy scraper
- Add browser rendering for JS-heavy sites (Best Buy, Target, Walmart, Costco)
- Improve Best Buy site-specific scraper with better selectors and logging
- Skip payment plan prices (/mo, per month, etc.)
- Enhance AI HTML preparation:
- Extract JSON-LD data before removing scripts
- Add price element extraction for better context
- Increase character limit from 15000 to 25000
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Always show price selection modal when adding a product so users can verify
- Use browser rendering for known JS-heavy sites (Best Buy, Target, Walmart, Costco)
- Update modal text to say "Confirm Price" for single candidates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add multi-strategy voting: runs JSON-LD, site-specific, generic CSS,
and AI extraction methods in parallel
- Implement consensus voting to select the correct price when methods agree
- Add AI arbitration when extraction methods disagree
- Add PriceSelectionModal for users to select correct price when ambiguous
- Store preferred extraction method per product for faster re-checks
- Add database columns for preferred_extraction_method and needs_price_review
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add global filter in priceParser to reject monthly/payment plan prices
- Filters: "/mo", "per month", "payments starting", "4 payments", etc.
- Update Best Buy scraper to check each price element for payment terms
- Prevents scraping "$25/mo" instead of actual "$229.99" price
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pure CSS/JS particle animation behind all content
- Multiple layers with different speeds for depth effect
- Theme-aware: white particles on dark mode, purple on light mode
- Low opacity for subtle, non-distracting ambiance
- Uses box-shadow technique for performance
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add notifications_cleared_at column to users table
- Clear button marks notifications as seen without deleting history
- Badge and dropdown only show notifications after last clear
- History page still shows all notifications
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PostgreSQL DECIMAL fields are returned as strings by node-postgres.
Convert to numbers before calling toFixed() to prevent TypeError.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Relocate PriceGhost version, changelog, and GitHub links from bottom
of page to underneath the left navigation buttons
- Update sidebar CSS to use flexbox for proper layout
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add notification_history database table for logging all triggered notifications
- Create API endpoints for fetching recent and historical notifications
- Add NotificationBell component in navbar with badge showing recent count
- Dropdown shows 5 most recent notifications with links to products
- Create full NotificationHistory page with filtering by notification type
- Log notifications when sent: price drops, target prices, back-in-stock
- Track which channels (telegram, discord, pushover, ntfy) received each notification
- Update sendNotifications to return which channels succeeded
- Bump version to 1.0.3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove overly generic pre-order phrases that caused false positives
("available in", "coming in", "arriving in" matched normal text)
- Add in-stock phrase priority check - "in stock", "add to cart",
"add to basket" now take precedence over pre-order detection
- Add Magento 2 stock status detection using stock classes and
add-to-cart buttons
- Bump version to 1.0.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CI/CD now only rebuilds images when backend/ or frontend/ changes
- Uses dorny/paths-filter to detect which components changed
- README, docs, and asset changes no longer trigger builds
- Updated CHANGELOG with all recent changes
- Bumped version to 1.0.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Removed space between Price and Ghost (now one word)
- Ghost gradient starts at 85% opacity for smoother transition
- Price text remains fully prominent
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Combined icon + PriceGhost text in single SVG header
- Ghost text has gradient fade effect (solid to transparent)
- Subtle glow filter for ethereal look
- Replaces separate icon and h1 in README
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- If no price found in static HTML, automatically try headless browser
- Re-runs all extraction methods on browser-rendered HTML
- Fixes price extraction for Magento, React, Vue, and other JS-heavy sites
- AI extraction now also benefits from rendered HTML
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- AI verification now checks if product is purchasable RIGHT NOW
- AI returns stockStatus field for pre-order/coming soon detection
- Enhanced generic stock status detection with pre-order phrases:
- Coming soon, available soon, releases on, pre-order, etc.
- Notify me when available, join waitlist, etc.
- Pre-order buttons no longer count as Add to Cart
- Fixes issue where unreleased products showed as in stock
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Ghost text fades from solid to transparent (left to right)
- Soft ethereal glow effect via text-shadow
- Enhanced glow on hover
- Works in both light and dark modes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace ghost emoji with SVG icon in navbar
- Replace ghost emoji with SVG icon on login/register page
- Consistent branding throughout the app
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Backend now creates all required tables if they do not exist
- Migrations run BEFORE server accepts connections (prevents race condition)
- Server exits if migrations fail instead of running with broken DB
- Fixes registration failure on fresh Docker installs without init.sql
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create CHANGELOG.md documenting all features
- Add version.json for version tracking
- Display version in Settings page footer with links to Changelog and GitHub
- Tag release as v1.0.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ai_status column to price_history table (verified/corrected/null)
- Track AI verification status through scraper and scheduler
- Display badges next to prices:
- ✓ AI (green): AI verified the price is correct
- ⚡ AI (orange): AI corrected an incorrect price
- Show badges on Dashboard product cards and ProductDetail page
- Add legend explaining badges in Settings when AI Verification is enabled
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The GET and PUT /api/settings/ai endpoints were missing
ai_verification_enabled in the request/response handling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename section to "Strongly Recommended: Enable AI Features"
- Document AI Extraction (fallback) and AI Verification separately
- Add Ollama as a provider option throughout
- Add AI price verification to features list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When enabled, AI verifies every scraped price to ensure accuracy.
This catches issues like scraped "savings" amounts instead of actual prices.
- Add ai_verification_enabled column to users table
- Create verification prompt and functions for Anthropic, OpenAI, Ollama
- Integrate verification step into scraper after traditional scraping
- Add verification toggle to Settings page (separate from AI extraction)
- AI verification is independent of AI extraction fallback
Flow: Traditional scraping -> AI verification (if enabled) -> AI extraction fallback (if no price found)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PriceGhost logo at top of README
- Center header with icon and description
- Add ntfy.sh to notification options and setup guide
- Add Ollama as local AI extraction option
- Add ntfy test endpoint to API reference
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add helper to detect savings/combo/bundle containers
- Prioritize JSON-LD data as primary price source (most reliable)
- Skip price elements inside savings containers
- Add minimum price threshold to filter out discount amounts
Fixes issue where $189.99 bundle savings was extracted instead of
actual $675.59 product price for items like AMD Ryzen 9 9950X3D.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create ghost icon with gradient background and price tag
- Add manifest.json with app metadata and icon references
- Implement service worker with network-first caching strategy
- Update index.html with PWA meta tags and SW registration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ntfy_topic and ntfy_enabled columns to database
- Add sendNtfyNotification function with emoji tags
- Add /settings/notifications/test/ntfy endpoint
- Add ntfy section in Settings UI with topic input
- Show ntfy badge in ProductDetail notification status
ntfy.sh is a free, simple notification service - no account needed.
Users just pick a topic name and subscribe in the ntfy app.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Update /settings/notifications to return actual tokens/keys
- Update /settings/ai to return actual API keys
Frontend:
- Update NotificationSettings and AISettings types
- Populate form fields with actual saved values on load
- Eye toggle now reveals actual stored values
- Always show toggle button for consistent UX
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change confusing placeholder from bullets to "Saved - enter new value to replace"
- Only show eye toggle when field has actual content to reveal
- Add z-index and improved click handling for toggle button
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create reusable PasswordInput component with eye icon toggle
- Apply to Telegram bot token, Discord webhook, Pushover keys
- Apply to Anthropic and OpenAI API keys
- Toggle switches between masked and visible text
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add database migration for ollama_base_url and ollama_model columns
- Update backend models and queries for Ollama settings
- Add extractWithOllama function using Ollama's /api/chat endpoint
- Add /api/settings/ai/test-ollama endpoint to test connection and list models
- Update frontend Settings page with Ollama configuration UI
- Support model selection from dropdown after testing connection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>