Skip to content
jack in the loop

jack in the sandbox

Garage sale day map

A map of every stop on a neighborhood garage sale day, filled by an AI pipeline that reads the organizer's messy list. Built in three days, never shipped, now live as a labeled demo on a sanitized dataset.

West Seattle has a community garage sale day. Hundreds of driveways open at once, and the list of who's selling what is a long post on the neighborhood blog. Flippers plan a route from it on their phones, in the car, at 8am.

So I built the map: every stop as a pin, filters for furniture or tools or a free pile, favorites you can share as a link, and a page per stop with its hours and what's on the table.

The event page: a map of West Seattle with a pin for each stop. The 30 listings shown are modeled seed data, not real sales.

The part that mattered

The map is the easy half. The hard half is turning a list written by hundreds of different households into clean records. That's the AI pipeline. It sends the raw list to Claude, asks for one structured record per stop with a confidence score and the source line it came from, validates every record against a schema, and refuses to invent anything that isn't in the text. A second step geocodes the addresses, slowly and politely, with a cache.

Why it never shipped

The pipeline never ran on the real list. The sandbox it was built in couldn't reach the blog, so the 30 stops on the map are modeled to look like the real format, with real street names and made-up details. It has 364 passing tests, and every one of them runs against data I wrote.

It also got built in June, for a sale that happened in May, so there was never a morning when anyone could have used it. Two lessons, both cheap in hindsight: point the pipeline at the real source on day one, and build for the next date on the calendar. A demo that works on its own fixtures proves the demo works.

The demo, honestly

It's live now as a demo, with a banner on every page that says what it is. Before it went up, the data got sanitized so it can't point at anyone: every house number became its hundred-block, every pin sits on the street centerline mid-block rather than on a house, every name became a neighborhood label, and tests fail the build if a house number or a personal name ever comes back.

The ingest page is built from the real code: a sample of raw input, the plain text the pipeline extracts, the actual prompt, a fixed mock result, and the real schema accepting good records and rejecting a bad one with its reasons listed. It calls no model; it says so.

built withNext.jsTypeScriptLeafletClaude APIZodVitest
next, in room 02 sandboxWhat If I Bought→