agent.gf.cx scope expansion — user-added URLs + multi-source deal aggregation (parked 2026-05-26)

DARE.CO.UK · PARKED SKETCH · 2026-05-26

Mirrored from ~/.claude/.../memory/parked_sketch_agent_gfcx_scope_expansion_2026-05-26.md. This is a design sketch parked for future build — read for context, not as a current deliverable.

Two adjacent expansion sketches for agent.gf.cx surfaced right after the first deploy landed. (1) Let the operator add new URLs to watch without code changes — a registry of targets stored in KV or git, picked up on next cron. (2) Add more deal-source scrapers per target — B&H, Newegg, MacRumors deals, slickdeals.net — so cross-retailer price floors get caught. Both fit module #1.x territory (extending the Mac mini watcher) before module #2 work (a fully different watch domain).


Dan, 2026-05-26 (right after agent.gf.cx custom-domain went operational): - “Having the possibility to suggest/add more URLs might be awesome.” - “Look in more places for deals, etc.”

Two complementary directions, neither blocking today’s deploy. Both go into module #1.x — extensions to the Mac mini watcher — rather than module #2 which would be a fully different watch domain (ETF prices, weather, GSC delta, etc.).

Sketch A — user-added URLs / watch registry

Shape: a targets collection (KV-stored or git-checked-in) defining each thing-to-watch:

�STASH2�

Three implementation paths, ranked by friction:

  1. Git-checked-in registry (src/targets.ts): targets live in source. Adding one = PR (or for Dan, a 1-line commit). Zero auth surface; deploys via wrangler-deploy. Lowest friction, recommended for v0.x.
  2. KV-stored registry with a write API behind CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Access: targets live in HISTORY (or a new TARGETS KV). Adding one = POST to /api/targets from the dashboard. Adds an admin form to the dashboard.
  3. Memory-fed registry for Claude Code sessions: Dan tells Claude “add this URL”, Claude commits to src/targets.ts, deploys. Wraps path 1 in a conversational interface.

Resume condition: when Dan finds a 2nd thing to watch and wants to add it without me hand-writing a new scraper. Or when adding a 5th item makes hand-editing tedious.

Sketch B — multi-source deal aggregation per target

Shape: for a given Target (e.g. Mac mini M4 24GB/1TB), check N retailers and return the floor:

Source Scraper notes Anti-bot
Apple Refurbished HTMLRewriter, current implementation low — serves to UA-spoofed CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF
B&H Photo HTMLRewriter against product page low — historically polite to scrapers
Newegg HTMLRewriter; product page or category moderate — has rate-limit headers
MacRumors deals RSS feed (no scraping required) none — they offer RSS
Slickdeals JSON API (community-vetted threads) requires keyword-match logic
eBay (Buy-It-Now floor) sanctioned API — eBay Browse API low; requires app credentials

Per memory feedback_no_unsanctioned_rpa_on_vendor_accounts.md — RPA on vendor inventory feeds is fine; RPA against vendor account surfaces is not. All of the above scrape public product pages — sanctioned.

Implementation pattern (already in code): each scraper is an independent function in src/sources.ts returning Promise<PriceResult[]>. Adding one = ~30 lines per source. The pickCheapest logic in index.ts handles the floor automatically.

Resume condition: when Apple’s M4 24GB/1TB refurb shows up at $1,099 but B&H has the same SKU at $1,049 — and we missed it. Drives the build.

Implementation order if both are taken on

  1. Start with B (multi-source for current target) — adds value to the live module without architectural change. Add B&H first since their HTML is the most stable of the third-party options.
  2. Once 3+ sources are checked, A becomes worthwhile — a target-registry that says “for this Mac mini config, check these 3 sources” lets us add a 2nd target (e.g. Mac Studio M4 32GB/1TB) without copy-pasting the per-source plumbing.

Cross-refs

Source: parked_sketch_agent_gfcx_scope_expansion_2026-05-26.md · Rendered 2026-05-26 17:10