The generated household
Sixteen invented devices, and the stories each page was given something to tell.
Sixteen invented devices with the names somebody would actually give them, resolving the domains those devices actually resolve, at the hours they are actually awake.
Why it is not random#
A demo dataset made of device-01 through device-16 resolving example-domain-4.com proves the charts render and nothing else. The product’s whole claim is that it turns a log into things you recognise as belonging to your home, and a fixture that cannot be recognised cannot demonstrate that claim.
The household#
Living room Apple TV Kitchen Echo Show Hunter's MacBook Pro Hunter's iPhone
Nintendo Switch Bedroom Samsung TV Front door Ring Hue bridge
Roborock S8 PlayStation 5 Kitchen Sonos Pixel 8 (guest)
Brother printer Synology NAS Work ThinkPad Model 3Each has an hourly rhythm curve and its own domain mix. The work laptop goes quiet at weekends; the console does the opposite; the doorbell never sleeps.
The stories it was given#
| Set piece | Which page it makes work |
|---|---|
| The bedroom TV hammers its ad endpoint every evening, refused every time | Friction |
| The doorbell retries a blocked metrics host in short, frequent bursts | Friction, as a recurring shape rather than a loop |
| The guest Pixel looks up dns.google and the Firefox canary | Anomalies |
| The Model 3 stopped resolving three days ago | Anomalies, gone silent |
| The Pixel first appeared three days ago | Anomalies, new device |
| Four domains first appear in the last two days | Domains |
| One upstream is deliberately slower than the other two | Health |
| Endpoints pinned to real cities across five continents | DestinationsDestinations — which a real Pi-hole install does not have |
That last row is the one place the fixture is more generous than your install would be. It carries answer addresses because it was generated to exercise every page; FTL does not report them, so on Pi-hole the destinations map, the country columns and the city labels are absent rather than sparse. What is different here says the same thing about the demo as a whole.
How it is built#
npm run demo:generate # ~417k queries → real rollups → prune to 7 days of detail
npm run demo:snapshot # extract the client JSON (stream, search, explorer)
npm run build # prerender ~435 pages against the fixture, emit out/Traffic is generated per device, per hour, against that device’s curve, with a weekend multiplier and jitter. Blocked verdicts come from a per-domain policy: some names are never blocked, some always, and a few are blocked most of the time but not all of it, because that middle is where a filtering resolver actually lives.
Then the product’s own runRollups() aggregates it hour by hour, and detail older than seven days is deleted. Seeded throughout, so the same commit produces the same database.