The docs drifted as the project moved fast. Fixed: - Counts to the validator (canonical): 105,743 records, Jurisdiction 29,905 (README had 105,746/29,908 — the exact-GEOID backfill dropped 3 city nodes and only the commit message was updated, not the docs). - sources.md: officeholders-v2 → v3 (13,329); added the inputs that landed since — municipal GEOID backfill, place/district crosswalks, the complete U.S. Code corpus, the executive offices, and the authority edges. - board.md: it described income/population/poverty only; now names the partisan-lean lens, zoom/pan, and the district+representative drill-down. - data-model.md: stale '17,506 files' → 105,743. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.7 KiB
The Board
viz/board.html is the Board — a rebuilt view of the canonical tree, never a
source. It is a nationwide county choropleth with four lenses — income,
population, poverty, and partisan lean (the head-count D/R balance of each
county's covering state + federal representatives) — that is zoomable and
pannable (scroll to zoom 1×–16× toward the cursor, drag to pan, double-click to
reset). Any county opens a drill-down of its officeholders, its demographics, and
the districts + representatives that cover it (congressional, state senate,
and state house, each with the share of the county it covers).
Pipeline
data/officeholders-v3.jsonl ─┐
data/acs_county.jsonl ├─ scripts/build_viz.py ─> viz/board.html (inlined)
data/place_county_crosswalk ┤ └> viz/county_*.json (companions)
data/fec_candidates, acs_cd ─┘
build_viz.py resolves each official to a county with the same
build.place_resolver + county_slug the tree uses, so the Board and the tree
agree by construction. It then does two things:
- Writes
viz/county_data.jsonandviz/county_detail.json— human-readable, diffable companions. - Injects the fresh data straight into
board.html, rewriting three marked lines:const D(per-county summary),const CDETAIL(per-county rosters), andconst TOTALS(the header counts).
Why the data is inlined
The Board is deployed as a self-contained Artifact, and the Artifact CSP
blocks every external request — no fetch, no external scripts, styles, or
fonts. So the county data cannot be loaded at runtime; it must live inside
board.html. That is why build_viz.py writes into the file rather than letting
the page read the JSON companions (nothing reads them — they exist for diffs).
The header totals (officeholders, candidates, counties, districts) read from the
injected const TOTALS object — never hardcoded — so they cannot drift out of
sync on the next rebuild.
Rebuild
make board # regenerate board.html + the JSON companions from the tree
board.html is deterministic: two runs are byte-identical.
Redeploy the Artifact
Editing board.html in the repo does not update a live Artifact — the
deployed copy is a snapshot. After make board, the Board must be republished
to its existing Artifact URL for the change to appear on claude.ai.
Republishing to the same URL requires passing that URL back to the publish step
(Artifact url=<existing-url>); publishing without it mints a new URL. Keep the
current Board Artifact URL in the team's deployment record so redeploys stay in
place instead of scattering new links.