Each of the 17 product-law features has a TypeScript shape (including an empty value), a UI component, and a data-access path. Empty data still renders.
Competitive gap
Pinball Map, Insert Coin, Maps, and Yelp each cover a slice. None combine a 40k+ establishment graph, machine where-to-play, classic/modern/combo character, establishment dossiers, last-year review digests, and a machine compendium in one low-friction UI. That combination is the product.
Notes live in docs/COMPETITIVE-RESEARCH.md and docs/FRAMEWORK-17.md.
Typed empty contract is 0 venues / 0 titles. The same DirectoryGraph fills from directory_stats.
Live queries, not fixtures: 1515 dossier · Medieval Madness where-to-play. Cabinet photos come from OPDB URLs already on the catalog. Wikipedia specs, facts, and review digests stay empty until those tables fill.
01
directory_stats stays at zero until rows exist. Home never hardcodes a graph size.
02
Dossier shows “Machine lineup not listed yet” — never a fake cabinet wall.
03
Where-to-play stays visible with an honest empty when no xrefs exist.
04
Unknown is unlabeled on cards; detail says “Character not classified.”
05
Every dossier section renders a dashed empty — sections are never hidden.
06
“No review digest for the last year” until venue_review_digests has a row.
07
Provenance lists only fields that exist. No fabricated sources.
08
Neutral cabinet placeholder. Venue interiors are never generated.
09
“Logo pending” tile when manufacturer_logo_url is empty.
10
Overview says specs/summary are not filled yet.
11
Facts, topics, and reading list each have their own empty copy.
12
Both entries stay on home at equal weight, even with zero results.
13
Near me denied/unavailable is stated. Distances appear only from real coordinates.
14
No matches: “No titles match that search” — no suggested fake hits.
15
Map and list share one query. Empty filters reset together.
16
No neon/pixel marketing IA. Shareable query-string URLs.
17
The rule itself: placeholders and dashed sections, never invented interiors or labels.