How this works
Built and written entirely by AI (Claude). ← Back to the live listings
A pipeline that scrapes second-hand and discounted kitesurf/wing-foil kit from ~15 UK
(and one NL) shops twice a week, normalises it, and publishes it here and by email.
Pipeline
- Scrape. Each shop's second-hand/sale pages are fetched every run. Shopify and
WooCommerce shops share a generic adapter each; four other shops run bespoke parsers built for
their specific site structure.
- Extract. Raw listing text (title, description, price, size string) is sent
to Claude, which returns structured fields: brand, model, size, condition (New / Used / Ex Demo),
year, price. This is what turns a raw variant string like
C55black/sand / 5'9'' - 80L into a clean size of 5'9".
- Filter by discount. Anything explicitly used/second-hand/ex-demo is always
kept. Anything else (new stock on a "sale" page) is kept only if discounted 30%+ off; otherwise
it's treated as full price and dropped.
- Categorise. Each item is classified into Kite, Trainer Kite, Foil Kite,
Board (Twintip/Foilboard/Surfboard), Bar, Bindings, Package, Foil Gear, Wing, Harness, or
Accessory. Which categories actually ship is a hard on/off switch in the code — Trainer/Foil
Kites, Foilboards/Surfboards, Packages, Foil Gear, Wings and Harnesses are currently off.
- Diff against the last run. Each listing has a stable key (shop + shop's own
product ID). This run's key set is compared against the previous run's saved set: not-seen-before
= new, seen-last-time-but-gone-now = delisted/sold. Only new listings go in the email; delisted
ones drop off the live site.
- Deliver. The email goes to every subscriber, filtered by whatever
category/brand/price preferences they've saved. The site always shows the full current
inventory, filterable and sortable by the same criteria, no login required.
Infrastructure
- Scrape + parse + email: GitHub Actions, Wed evening + Sat morning UK time, no server.
- Site + serverless endpoints (subscribe, preferences, admin actions): Cloudflare Pages
+ Pages Functions.
- Subscriber list + email delivery: Resend.
- Per-subscriber category/brand/price preferences: Cloudflare Workers KV.
Known limitations
- Only sees what a shop's own site exposes — a broken or hidden listing on their end is invisible here too.
- A shop changing its site layout can silently break that shop's scraper until noticed.
- AI extraction is generally accurate but not infallible — brand/size/price misreads happen occasionally.
- Duotone was sold as "North Kiteboarding" pre-2018; "North" has since relaunched as an unrelated brand. Old North-era model names (Evo, Neo, Mono, Juice, Rebel, Dice, etc.) are relabelled "Duotone (North)" to avoid conflating the two — edge cases may still slip through.
← Back to the live listings