7a117e7a46
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013gwc3aCiyQxmCWQke8RvEz
49 lines
1.9 KiB
Markdown
49 lines
1.9 KiB
Markdown
# Korting — prijstracker
|
|
|
|
Houdt een lijst productpagina's dagelijks in de gaten en mailt wanneer
|
|
de prijs verandert.
|
|
|
|
## Lokaal draaien
|
|
|
|
```bash
|
|
npm install
|
|
cp .env.example .env # env vars invullen
|
|
npm test
|
|
npm start
|
|
```
|
|
|
|
De app leest `.env` in via `dotenv`. `BASIC_AUTH_USER`, `BASIC_AUTH_PASS`,
|
|
`SMTP_FROM` en `NOTIFY_EMAIL` zijn verplicht; ontbreken ze, dan stopt de
|
|
app bij het opstarten met een melding.
|
|
|
|
De UI staat achter basic auth (`BASIC_AUTH_USER` / `BASIC_AUTH_PASS`) op
|
|
`http://localhost:3000`.
|
|
|
|
## Environment variables
|
|
|
|
| Variabele | Omschrijving |
|
|
|---|---|
|
|
| `PORT` | HTTP-poort (default `3000`) |
|
|
| `DB_PATH` | Pad naar het SQLite-bestand (default `./data/korting.db`) |
|
|
| `BASIC_AUTH_USER` / `BASIC_AUTH_PASS` | Login voor de web-UI |
|
|
| `SMTP_HOST` / `SMTP_PORT` / `SMTP_USER` / `SMTP_PASS` | SMTP-server (Postal op `mail.sjoerd.app`) |
|
|
| `SMTP_FROM` | Afzenderadres van de notificatiemails |
|
|
| `NOTIFY_EMAIL` | Ontvangeradres van de notificatiemails |
|
|
|
|
## Hoe het werkt
|
|
|
|
Elke dag om 08:00 (Europe/Amsterdam) doorloopt de app alle producten,
|
|
haalt de huidige prijs op (JSON-LD → meta tags → regex-fallback), en
|
|
stuurt een email als de prijs is veranderd sinds de vorige geslaagde
|
|
check. Een mislukte poging (pagina onbereikbaar, geen prijs gevonden,
|
|
of de mail kon niet verstuurd worden) verandert de opgeslagen prijs
|
|
niet, zodat de volgende dag opnieuw wordt geprobeerd. Via de "Nu
|
|
controleren"-knop in de UI kan dit ook handmatig getriggerd worden.
|
|
|
|
Als het ophalen van de prijs op de gewone manier mislukt (netwerkfout, of
|
|
geen prijs gevonden in de HTML), probeert de app het één keer opnieuw met
|
|
een echte headless-browser (Playwright/Chromium) — nuttig voor pagina's
|
|
die de prijs pas met JavaScript renderen, of die eenvoudige HTTP-clients
|
|
blokkeren. Geen garantie tegen elke vorm van bot-detectie, maar dekt een
|
|
reëel deel van de gevallen die de gewone aanpak mist.
|