Releases: mikeknight85/PriceStalker
Releases · mikeknight85/PriceStalker
Release list
v1.4.0
Added
- Edit a price watcher's selection after creation (#21). New "Edit Price Selection" button on the product detail page re-scrapes the page and reopens the price picker, so you can correct a wrong price (e.g. a bad CSS match) without deleting the watcher or losing its price history. The corrected price is recorded as a new point.
Fixed
- Broken product images from relative URLs (#22). Image URLs returned as site-relative paths (e.g.
/i/abc123) are now resolved to absolute URLs against the source page, so they render correctly. Existing broken images self-heal on the next price check.
v1.3.1
[1.3.1] - 2026-06-05
Documentation
- README "What's new" table caught up to the 1.3.x line (was stale at
1.1.x). - New Notifications → Custom Webhook config section with the full
placeholder reference table. - Notifications feature blurb now mentions the Custom Webhook provider
and the any-change alert added in 1.2.8.
No code changes — pure docs/version-bump release so :latest users on
prod see the most recent README on the GitHub release page.
v1.3.0
[1.3.0] - 2026-06-05
Added
- Configurable generic webhook notification provider (#4). New
"Custom Webhook" provider alongside the existing 5 (Telegram,
Discord, Pushover, ntfy, Gotify). Configure URL, method (GET / POST
/ PUT / PATCH / DELETE), optional headers (JSON object), and a body
template with placeholders —{title},{type},{url},
{currency},{price},{new_price},{old_price},{threshold},
{target_price},{timestamp}. Routes notifications to anything
that speaks HTTP: Apprise, Home Assistant, n8n, Zapier, custom
backends. - Beta channel (
:betaDocker tag). Tracks every merge tomain.
:latestnow only updates on tagged releases. Demo / staging stacks
pin to:betafor auto-rolling pre-release deployments; prod stacks
stay on:latestuntil the next tag. - BETA pill next to the running-version display in Settings when
the image was built frommain. Makes pre-release deployments
visually distinguishable from prod without checking the image tag. - Themed textareas — global form-group CSS now styles textareas
the same as inputs (was missing the selector, every textarea fell
through to browser defaults). Plus a.code-inputmodifier class
for monospace JSON/code-shaped fields.
Fixed
- Webhook save/test feedback uses toast instead of the top-of-page
alert bar. The webhook form sits at the bottom of a long Settings
page; feedback was previously invisible to anyone scrolled there. - Product card alert badges respect product currency. Price-drop
and target-price badges in the dashboard's product card hardcoded a
$prefix and ignored the product's actual currency. Now use the
sameformatPricehelper as the displayed price next to them.
v1.2.11
[1.2.11] - 2026-06-02
Fixed
- Wrong product images on SPA pages with recommendation widgets
(digitec.ch, etc.).scrapeProductWithVotingread JSON-LD for price
and stock but ignored theimagefield, so the cascade fell to the
generic image scan which picked the first matching element — often
a recommendation card on React-rendered pages, not the actual hero
image. The stored URL pointed at a different product's image.
Same class of bug as the JSON-LD stock-signal drop fixed in v1.2.6.
The voting path now applies the type-aware JSON-LDProduct.image
whenever the page exposes it. - Stored bogus image URLs were permanent. The image self-heal added
in v1.2.9/1.2.10 only triggered whenimage_urlwas NULL, so once
a bad URL was in the DB it stayed forever. Self-heal now also fires
when the scrape returns a different non-null URL — broken products
recover on their next check or the next manual refresh.
v1.2.10
[1.2.10] - 2026-06-02
Fixed
- Manual "Refresh Price now" now also backfills missing
image_url.
Parity with the scheduler's image self-heal added in v1.2.9 — the
manual refresh route was a separate code path that wasn't updated.
Clicking refresh on a product missing a picture now rescues it
immediately instead of waiting up to a full refresh interval.
v1.2.9
[1.2.9] - 2026-06-02
Fixed
- Missing product images that never recovered.
image_urlwas
only written at create-time, so a first-scrape miss became permanent
even when later scrapes would have succeeded. JS-heavy SPAs
(digitec.ch via Puppeteer) hit this when render timing varied.
Scheduler now backfillsimage_urlwhenever the current value is
null and the scrape produced one — existing broken products
self-heal on their next scheduled check. - Lazy-load attribute coverage.
extractGenericImagenow also
readsdata-original,data-lazy,data-lazy-src,data-srcset
andsrcset(picking the first URL out of srcset descriptor lists).
Reduces first-scrape misses on lazy-loaded image elements.
v1.2.8
[1.2.8] - 2026-06-01
Added
- In-app update notification. The backend queries the GitHub
releases API once a day. When a newer PriceStalker release is
available, logged-in users see a dismissible banner with a link to
the release notes. Dismissals are per-version (localStorage), so
a future release re-surfaces it. No telemetry — the only outbound
request is a single HTTPS GET to api.github.com from the backend
(never from the user's browser), withUser-Agent: PriceStalker/<v>.
Opt-out entirely withDISABLE_UPDATE_CHECK=true.
v1.2.7
[1.2.7] - 2026-06-01
Fixed
- Wrong currency in the price-selection modal on stores that emit
canonical schema.org markup (<meta itemprop="price" content="X">
plus<meta itemprop="priceCurrency" content="EUR">). The generic
CSS candidate extractor read the numericcontentattribute, found
no symbol, andparsePrice()defaulted to USD — so the modal
preview showed$even on EUR/GBP/etc. stores. The post-confirm
scrape used a different code path that did find the symbol, so the
saved row was correct, but the modal was misleading. The extractor
now falls back to the companion[itemprop="priceCurrency"], then
OpenGraphproduct:price:currency/og:price:currency, before
accepting the USD default.
v1.2.6
[1.2.6] - 2026-06-01
Fixed
- Shopify restock detection (#2) — three compounding bugs made the
voting scraper mislabel in-stock Shopify products as out-of-stock and
hide the (correctly extracted) price for any OOS product:scrapeProductWithVotingsilently dropped JSON-LD's
offers.availabilitysignal because it called the price-only
candidate extractor but not the full extractor that reads stock.- The generic CSS detector matched Shopify Dawn-family themes' hidden
.price__badge-sold-outelement on in-stock products (Dawn renders
both badge states in the DOM and toggles visibility via CSS rules
Cheerio can't evaluate). - The UI suppressed the price entirely when stock was OOS, leaving
affected users looking at an empty card and concluding detection
itself was broken.
- Wrong currency on generic CSS extractions (#6) — the generic
scraper defaults to USD when it can't detect a symbol or code in the
text. Added a per-product currency override that wins across writes,
notifications and SELECTs (viaCOALESCE), so users can correct it
without waiting for a code fix.
Added
- Shopify-aware extraction. New scraper path that detects a Shopify
storefront by itscdn.shopify.com/Shopify.themesignature and
fetches/products/<handle>.jsfor canonical per-variantavailable
and price. Bypasses theme/localization variation entirely and covers
the full Shopify long tail, not just the reported store. - Localised in-stock phrases in the generic stock detector
(Dutch / German / French / Spanish / Italian / Portuguese), so
non-English Shopify pages produce a positive in-stock signal instead
of falling through to OOS by default. - "Notify on any price change" toggle per product (#5). When
enabled, the scheduler fires aprice_changenotification on every
movement ≥ 0.01 in either direction, replacing the threshold-based
drop notification while it's on (no double-firing). Implemented for
Telegram, Discord (green/red embed by direction), Pushover, ntfy
(up/down trend tags) and Gotify. notify_back_in_stockaccepted onPOST /productsand defaulted
totruewhen adding an OOS product — the typical reason someone
tracks something unbuyable is to know when it returns.- Price now shown alongside the OOS badge on the product card and
detail page (no more "Price unavailable" hiding the last-known price). - "Detected via: ()" hint under the price on the
product detail page (#6). Generic CSS surfaces the actual selector
that matched, so wrong-currency / wrong-price calls are diagnosable. - GitHub Actions runner bump to Node 24-compatible majors
(actions/checkoutv6,dorny/paths-filterv4,docker/*v4/v6/v7),
ahead of the June 2026 deprecation.
PriceStalker 1.2.5 — Puppeteer fix + DEMO_MODE flag
Fixed
- Puppeteer "Failed to launch the browser process" — the
nodejsuser in the backend image was created withuseradd -r(no-m), leaving$HOMEunset at runtime. Chromium's crash handler (chrome_crashpad_handler) derives its--databasepath from$HOME/$XDG_CONFIG_HOME, so it crashed on launch with--database is required, breaking the browser-fallback branch of the voting scraper. Static-HTML sites (Amazon JSON-LD, Digitec JSON-LD, etc.) were unaffected because they never reach Puppeteer. Fix: create a real home directory for thenodejsuser and setHOME=/home/nodejs.
Added
DEMO_MODEenv flag that disables identity-mutating profile operations. WithDEMO_MODE=true,PUT /api/profileandPUT /api/profile/passwordreturn 403. Useful for any deployment where the operator wants to keep a shared or test account stable — public demos, multi-tenant sandboxes, QA environments. Per-user-scoped operations stay open (adding products, configuring your own AI provider, configuring your own notification webhooks). Off by default; existing deployments see no change.
Docker images
ghcr.io/mikeknight85/pricestalker-backend:1.2.5
ghcr.io/mikeknight85/pricestalker-frontend:1.2.5
Multi-arch (amd64 + arm64).