# Farm Market Prices (PoC)
Minimal Next.js app that scrapes daily fresh produce prices from South African
fresh produce markets, stores them in SQLite, and renders them with a
price-history chart. Proof of concept for a larger multi-market aggregator.
Markets:
- **Cape Town Market** (`ctmarket`) —
ctmarket.co.za,
server-rendered wpDataTables table, full list in one fetch. The only market
wired for straightforward automated fetching.
- **Tshwane Market** (`tshwane`) — tfpm.tshwane.gov.za,
ASP.NET WebForms with a three-level drill-down (search → product → item →
price detail), driven via headless Chromium (Playwright). A raw fetch of the
*search* works, but the follow-up "Select" postbacks are blocked by the site's
WAF (HTTP 403), so a real browser is required. Notes: the search matches
**singular** product names (search "potato", not "potatoes"); the daily data
is **published once per day** (before that run every search returns "No
Results"); and because each price needs its own page load, this adapter is
bounded — it scrapes the primary product per commodity, capped per commodity,
so a run takes a few minutes. Province is folded into the container field.
- **Joburg Market** (`joburg`) — joburgmarket.co.za,
driven via headless Chromium (Playwright) because the site has intermittent
bot protection (HTTP 409). Loops the 8 commodities and reads each one's
`containerall=2` drill-down. Publishes Average + Highest price but **no
Lowest**, so `priceLow` is null for this market.
- **East London / Buffalo City Market** (`eastlondon`) —
buffalocity.gov.za,
per-product search that POSTs to `prices.php`; results are an add-to-cart
listing rather than a table.
- **Durban Market** (`durban`) — durbanmarkets.durban.gov.za,
a plain fetch: the landing page renders the full daily table (all commodities,
~800 rows) server-side, so one request gets everything. Includes a Province
column, which is folded into the container field to keep same-pack rows fro …