diff --git a/PROJECT.md b/PROJECT.md deleted file mode 100644 index 4e8f868..0000000 --- a/PROJECT.md +++ /dev/null @@ -1,32 +0,0 @@ -# UI Stock Tracker — Design Notes & Development History - -Supplementary notes that go beyond the [README](./README.md): the reasoning behind the trickier parts of the scraper and the notable fixes made during development. For setup, architecture, API, and schema, see the README; for deployment see [UNRAID.md](./UNRAID.md). - -## Stock Detection Rationale - -The scraper classifies each product page as `in_stock`, `sold_out`, or `unknown` using case- and whitespace-insensitive substring matching against the page's buttons. Two non-obvious details drove the matching rules: - -**Auth-state difference.** The scraper runs logged out. On a sold-out item, Ubiquiti shows `"Login for Notifications"` to logged-out visitors instead of the logged-in `"Notify me when available"`. Both strings must be in the sold-out list, or logged-out checks would fall through to `unknown`. - -**The `label` attribute exists only on the in-stock button.** The production DOM carries `label="Add to Cart"` on the primary Add-to-Cart button (confirmed in DevTools), but the sold-out "Login for Notifications" button has no `label` attribute. So in-stock has two redundant signals (the attribute *and* the button text) while sold-out relies on text alone — this asymmetry is by design, not an oversight. - -When neither signal matches, the scraper logs a `[Scraper] UNKNOWN debug` payload (page title, button labels, button texts) so a misclassification can be diagnosed from container logs without reproducing locally. - -To avoid reading the page before React finishes rendering, the scraper waits 2.5s plus an active wait for a `