ReviewOS

stacks/smakelo

B5: Real-data seed pipeline (LA / Santa Monica)

#18
Open chris opened this 9 days ago ·
9 days ago

Part of #1. Real data only.

  • app/Commands/ImportPlaces.ts: Foursquare OS Places extract (Santa Monica + LA bounding box; food/coffee/farm categories, Apache 2.0) cross-checked against OSM (hours), emitting database/data/businesses.json
  • Manual curation pass over Santa Monica so the launch neighborhood is hand-polished (~300 listings total)
  • 12 hand-authored partner merchants (7 restaurants, 3 coffee shops, 2 farms): real menu structures with modifiers, rights-cleared photos, hand-written reviews; 8 couriers
  • ~600 historical orders + courier GPS tracks generated along real OSRM routes for believable dashboards/maps
  • Attribution page: Foursquare OS Places, OpenStreetMap contributors, OSM tiles
9 days ago

First cut done in 9bbe173: 35 businesses seeded (23 real listings from OpenStreetMap and Foursquare Open Source Places, 12 invented partners), 30 menu items with 16 modifier groups, 20 hand-written reviews, 211 opening-hour rows.

The invariant that matters holds and is checked: zero reviews attached to a real business. Menus are written rather than generated, because a menu is the thing being demonstrated and faker fills the same columns while proving nothing.

Not done: the FSQ/OSM bulk import command that would take this from 35 curated rows to ~300. The curated set is what a reviewer sees today.

9 days ago

Partial progress on the seed pipeline, from b4b772e.

The 12 partner merchants are complete. Seven of them (the-salted-anchor, nonna-pia, golden-hour-diner, saffron-and-sumac, ember-coffee-roasters, the-slow-pour, two-crows-orchard) had a listing, hours and a table layout but no menu at all - so they appeared to take orders and could not. Menus written for all seven, with modifier groups that ask the questions the kitchen actually needs answered. 73 items across the twelve.

Order history is now seeded through placeOrder(), not written as rows. That matters: a seeded ledger the real path could never produce is worse than no ledger, because it looks like evidence. It caught two bugs on the first run (the missing menus above, and orders that skipped required modifier groups being correctly rejected while the seeder reported success).

24 orders on a fresh database, 8 dispatched to couriers, deterministic via a small LCG so a screenshot keeps matching the database.

Still open here: the bulk FSQ/OSM import to ~300 listings. The 35 curated Santa Monica/LA places remain hand-picked.

9 days ago

The bulk import is done: 280 businesses, of which 12 are the invented partners that can take an order.

buddy import:places pulls restaurants, cafes and food shops from OpenStreetMap for the Santa Monica and Venice box and writes them to a checked-in file. Fetching at seed time would mean a deploy that fails on a Tuesday for reasons nobody can act on, and a demo whose contents shift under it is one where a screenshot stops matching. Curated entries win on a slug collision, since they carry a description somebody wrote and hours somebody checked.

The opening-hours parser handles the common shapes and skips the rest rather than guessing. A half-understood rule produces a business claiming to be open when it is shut; openStatus already treats absent hours as unknown rather than closed, so silence is the honest failure. 68 of the imported places came with parseable hours.

Two bugs this turned up, both invisible:

MAX_LIMIT in the search was 200, below the number of seeded listings. Eighty real places sat in the database reachable by nothing: not the discover page, not the search box, not the API. A cap under the size of the data is not a guard, it is a silent truncation.

The map's centre was scoped inside the map block, so every server-side search threw a ReferenceError into a promise nobody awaited. The page kept working and simply found less: searching "sushi" showed 4 where the API had 14. Now verified live at 14 (4 already on the page, 10 fetched).

The discover page stays light: it renders the sixty nearest and asks the server for anything past them, rather than shipping a megabyte of HTML. Filtering only what happened to be rendered would have meant a search box that quietly could not find most of what the site lists.

Attribution is on every page footer, and these places have agreed to nothing: no reviews, no orders, and a claim form that leads with taking the listing down.

Sign in to comment on this issue.