Show state legislators with photos and contact info on the council page - #139
Closed
HaydenCash716 wants to merge 10 commits into
Closed
Show state legislators with photos and contact info on the council page#139HaydenCash716 wants to merge 10 commits into
HaydenCash716 wants to merge 10 commits into
Conversation
# Conflicts: # webapp/src/components/FindOfficials.vue
# Conflicts: # webapp/src/components/FindOfficials.vue
Author
|
Folding this into #138 — it's really one feature, and a single PR is easier to review. All commits from this branch are there. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on #138 (marked draft until that lands — only the last commit is new here).
#138 gives people links to go find their officials. This goes a step further for the one level of government where open data actually exists: after a search, the card shows your state legislators as people — official photo, name, party, chamber and district, with tap-to-email and tap-to-call. Less friction between "I'm angry about this" and "I sent the email."
Why state and not city council: council data with photos/emails doesn't exist in any open API — Google Civic's representatives endpoint was the only national source and it shut down in April 2025, and the alternatives are paid (Cicero) or stale (Wikidata mayors). Open States is the canonical open source for state legislators and it's good: maintained, official headshots, emails, office phones, queryable by point. I left a thought about the council side over on #136.
How it's wired
OpenStatesClientin the API, same shape as the other upstream clients: env-keyed (OPENSTATES_API_KEY), disk-cached like the Nominatim client (24h, keyed by coordinates — input is city centroids, so repeat cities never hit the upstream and the free-tier rate limit should be a non-issue), errors through the OTel logger. It maps the upstream response down to a slim typed shape rather than passing Open States' full payload through.GET /officials?lat&lng— returns{legislators: [...]}. Without a key configured it just 404s and the frontend silently falls back to the legislator link from Add a local-officials lookup to the council page #138, so merging this changes nothing until you decide to add a key (free, ~2 min at https://open.pluralpolicy.com/accounts/profile/). Same pattern as the other env-gated features.referrerpolicy="no-referrer"and fall back to an icon; attribution line links to openstates.org. The privacy caption now mentions Open States.Verifying
I don't have an Open States key of my own, so the upstream is exercised two ways:
bun test— 6 new tests on the client (response mapping, capitol-office phone preference, missing-field tolerance, request shape, cache behavior, non-OK status), stubbed fetch likeGithubClient.test.ts. Whole api suite: 11 pass.bun --preload, stub not committed) and drove the page in a browser: cards render with photos, no-photo people get the icon fallback, the mailto/tel links carry the right addresses, and restarting without the key drops cleanly back to the Add a local-officials lookup to the council page #138 links.bun run build-onlypasses; type-check unchanged (same pre-existing master failures).If you'd rather not hold an API key at all, the other shape this could take is a baked pipeline like alpr-counts — cron pulls Open States bulk data into a district-keyed JSON on the CDN and the client resolves districts via the Census geocoder. Happy to rework it that way instead if you prefer; the live-proxy version was the smaller diff.