Skip to content

Wayfinder map: Non-profit stats dashboard (V1: BetterVoting + NationBuilder) #18

Description

@ArendPeter

Destination

A locked spec for a /dashboard route (equal-vote.github.io/web-tools/#/dashboard) — V1, staff-only. Two tables, one per source group (BetterVoting, NationBuilder), each row a metric and each column a year, populated by live API calls reusing the credential model already in this app (NationBuilder OAuth cookie, no separate login UI). The spec pins down the exact metric list, its source/computation per metric, and table shape — ready to hand to a build session with no open judgment calls left.

V1 excludes: Mailchimp, manual-spreadsheet metrics, BetterVoting user counts, and any caching/no-credential public viewing — see Out of scope.

Notes

  • Domain: React + TS SPA (web-tools), GitHub Pages, HashRouter, useCookie-persisted credentials, req()/StateReporter pattern in WebTools.tsx. See CLAUDE.md.
  • The Heroku CORS proxy (PROXY_ORIGIN) is a confirmed blind passthrough — forwards to any target URL, no host allow-list. Adding bettervoting.com as a source needs no proxy-side changes, just a client-side fetch path (likely no auth header, unlike the existing mailchimp/nationbuilder branches in req()).
  • BetterVoting table is fully specified already (no ticket needed): rows = headline (Elections Created, Votes Cast) plus one votes/elections row-pair per voting method (star, star_pr, approval, ranked_robin, rcv, choose_one, stv, multi_method) from a single GlobalElectionStats (by_year) call. All rows styled identically — no visual hierarchy for V1. Year columns derived from whatever years the API returns.
  • NationBuilder needs per-cluster research: volunteers/signups, donations/finance, events. Every NationBuilder research ticket must check whether counts/sums can be fetched without pulling full paginated payloads — the org wants counts, not bulk data exports.
  • Keep the future cached/public-viewing idea in mind (see Out of scope) when shaping each metric's fetch: isolate each behind a clean function so a later cached-JSON fallback can slot in without a redesign. Don't design for it now — just don't foreclose it.
  • Consult /research for the NationBuilder tickets below; /grilling and /domain-modeling for any follow-on decision tickets that graduate out of the fog.

Decisions so far

Not yet specified

(empty — every fog patch from the initial charting has now graduated into a ticket)

Out of scope

  • Mailchimp (Email Blasts Sent) — deferred from V1; user chose to focus on BetterVoting + NationBuilder only, which have clearer API stories.
  • Manual-spreadsheet metrics (Coalition Members, Google Form Sign-ups, Presentations Given, Campaigns Run, Number of leaders with titles) — no API story; deferred from V1 alongside Mailchimp.
  • BetterVoting user counts — not present in the GlobalElectionStats output the user is treating as source of truth; dropped from scope rather than deferred.
  • Cached, no-credential public dashboard viewing + daily cron refresh — explicitly named by the user as a future effort (sibling to a similar planned cron for contact exports). Revisit as its own wayfinder map once V1 ships and the NationBuilder fetch shape is known.
  • Recurring-donor tracking ("number of donors with an ongoing recurring donation") — ruled out while resolving Decide donation counting policy for "Number of Donations" & "Funds Raised": the v2 API has no field identifying or grouping recurring charges (no recurring_donation_id, no payment_profile_id), and a matching heuristic was judged too fragile for V1.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions