The filter shows WHERE the gap is; it could not say which part of it is biggest. The 3,444 groups with nothing were reachable only by tapping dots until a large one turned up, which is not how anyone chooses a field. "See the 40 largest" now opens a ranked list in the sheet — the slot the country and group views already use, so no new geometry and no new collision with the control rail. Sorted by population, because choosing where to go is choosing how many people are behind the decision. Tapping a row flies there and opens that group. Fly first, THEN open: opening sets `selected`, which swaps the sheet away from the list, so the other order loses the map movement behind a re-render. THE LIST EXPOSED A REAL DEFECT. The largest gaps are exactly the groups with no entry in any pool, so they had no record to carry a language name and the sheet rendered "Language: (blank) cjy" for a 60-million-speaker group. Every language is now named from the people-group dataset, creating the entry where no pool has one: 2,251 codes are named-only — the language is known, nothing was found for it anywhere. That makes "has a code entry" ~100% by construction, so it is relabelled in the build output as naming and NOT coverage. Coverage is the line under it and still reads 8,935 of 12,379, 72.2%. A metric that reaches 100% because its meaning changed is worse than no metric. Verified on the served tree: 40 rows, populations strictly descending 60,310,000 -> 974,000 so "largest" is not a claim taken on trust; tapping row 1 moves zoom 1.3 -> 4.2 and opens Han Chinese Jinyu, whose scripture_url and film_url are empty and whose Door43 list is empty — so the list is not mislabelling groups that have something. 200 sampled zero-resource groups all name their language, where the screenshot before this change shows that field blank. Pins, table, deep-link and filter probes all still pass, and the full a11y sweep passes 810 of 810 buttons across 21 leaf pages. |
||
|---|---|---|
| .. | ||
| external-bundles | ||
| people-groups | ||
| posters | ||
| tables | ||
| vendor | ||
| README.md | ||
data/ — the bundler's source-of-truth data
The law: data lives here; public/ is generated. Every folder in data/ is copied into the
served web-root by the build (internal/generate-tree.mjs), exactly like the per-profile data in
plugin-designs/*/data/. You should be able to rm -rf public/ and get it all back with bun run build.
| Folder | Served at | What it is |
|---|---|---|
people-groups/ |
/assets/people-groups/ |
People-group datasets (CSV/JSON) the maps read at runtime |
vendor/ |
/assets/vendor/ |
Third-party runtime assets (e.g. table libraries) |
posters/ |
/assets/posters/ |
Rendered poster webp set (heavy pipeline output; poster walls fetch these) |
tables/ |
/assets/tables/ |
The MERGED served table set (its index.json is the merge; per-profile plugin-designs/*/data/tables are build-time sources) |
external-bundles/ |
not served | Prebuilt map IIFEs vendored from sibling projects (not built here); only the optional layouts/ shell mounted them, so the build no longer copies them into public/ |
Don't edit anything under public/ by hand — change it here (or in plugin-designs/*/data/,
layouts/*/assets/) and rebuild.