Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ac807f1
Merge pull request #1 from chihacknight/main
frankies2727 Jul 5, 2026
6c8b3f6
feat: add filterable legislation dashboard to GitHub Pages docs
claude Jul 5, 2026
5946e38
Merge pull request #2 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
8b3cbbd
feat: build dashboard data from all govbot-openstates-scrapers repos …
claude Jul 5, 2026
44128f5
Merge pull request #3 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
7844f21
fix: make dashboard data aggregation layout-agnostic
claude Jul 5, 2026
bd1eba8
Merge pull request #4 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
057e2eb
feat: read raw OpenStates scraper output for dashboard data
claude Jul 5, 2026
24124c9
Merge pull request #5 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
3428c75
perf: slim dashboard data payload for 140k+ bills
claude Jul 5, 2026
c1f50c4
Merge pull request #6 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
3af0d10
feat: show 'Data as of <date>' freshness badge on dashboard
claude Jul 5, 2026
cb06faf
feat: flag jurisdictions with no scraped data yet
claude Jul 5, 2026
44be8fe
Merge pull request #7 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
4c977fa
style: move 'Data as of' badge up beside the dashboard title
claude Jul 5, 2026
20dcdd3
Merge pull request #8 from frankies2727/claude/github-pages-dashboard…
frankies2727 Jul 5, 2026
1f84c25
fix(dashboard): label every bar in Activity by month chart
claude Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Deploy docs to GitHub Pages
name: Deploy docs & dashboard to GitHub Pages

on:
push:
Expand All @@ -7,6 +7,9 @@ on:
paths:
- "docs/**"
- ".github/workflows/deploy-docs.yml"
schedule:
# Refresh dashboard data daily, after the 6am UTC scrapes
- cron: "0 8 * * *"
workflow_dispatch:

permissions:
Expand All @@ -29,6 +32,40 @@ jobs:
with:
mdbook-version: 'latest'

# Fetch live legislation data and rebuild the dashboard's data.json
# before mdbook runs, so the fresh file is copied into the book.
# Failures fall back to the committed sample data instead of
# breaking the docs deploy.
- name: Build dashboard data from legislation repos
env:
GH_TOKEN: ${{ github.token }}
DATA_ORG: govbot-openstates-scrapers
run: |
set -uo pipefail
mkdir -p /tmp/govbot-data/repos
repos=$(gh repo list "$DATA_ORG" --limit 200 --json name --jq '.[].name' | grep -- '-legislation$') || true
if [ -z "${repos:-}" ]; then
echo "::warning::no *-legislation repos found in $DATA_ORG; keeping committed sample data"
else
echo "cloning $(echo "$repos" | wc -l) repos from $DATA_ORG"
for r in $repos; do
git clone --quiet --depth 1 "https://github.com/$DATA_ORG/$r.git" "/tmp/govbot-data/repos/$r" \
|| echo "::warning::failed to clone $DATA_ORG/$r"
done
python3 scripts/build_dashboard_data.py \
--govbot-dir /tmp/govbot-data \
--tags-config scripts/dashboard_tags.json \
--source-label "github.com/$DATA_ORG" \
--output docs/src/dashboard/data.json \
|| {
echo "::warning::dashboard data build failed; keeping committed sample data"
echo "::group::repo layout sample (for debugging)"
find /tmp/govbot-data/repos -mindepth 1 -maxdepth 5 -not -path '*/.git*' | sort | head -300 || true
echo "::endgroup::"
}
fi
ls -lh docs/src/dashboard/data.json

- name: Build docs
run: mdbook build docs

Expand Down
4 changes: 4 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

[Introduction](./readme.md)

# Dashboard

- [Legislation Dashboard](./dashboard-guide.md)

# Current Effort

- [2025 - Decentralize](./2025-Decentralize/readme.md)
Expand Down
64 changes: 64 additions & 0 deletions docs/src/dashboard-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Legislation Dashboard

**[Open the dashboard →](./dashboard/index.html)**

A static, client-side dashboard over bill data from every tracked jurisdiction,
filterable by state/territory, session, chamber, topic tag, and free-text search.
It is plain HTML/JS with no external dependencies, deployed as part of this docs
site by the existing GitHub Pages workflow.

## What it shows

- **Stat tiles** — bill count, jurisdictions, sessions, and share of bills with topic tags
- **Bills by jurisdiction** and **bills by topic** bar charts (click a bar to filter)
- **Activity by month** — bills by the month of their most recent recorded action
- **Bills table** — sortable, with topic chips and links to each bill's official source

All charts, tiles, and the table re-render against the same filtered slice, so the
numbers always agree. A "Data as of" badge under the title shows when the snapshot
was built.

Jurisdictions whose upstream scraper repo cloned but published no bills yet are
listed as pending under the jurisdiction chart (rather than silently omitted), and
appear automatically once their `*-legislation` repo starts carrying data.

## Where the data comes from

The page reads a single `data.json` produced by
[`scripts/build_dashboard_data.py`](https://github.com/chihacknight/govbot/blob/main/scripts/build_dashboard_data.py),
which scans cloned govbot dataset repos for bills in either format — govbot's
OCD-files layout (`**/bills/<ID>/metadata.json`) or raw OpenStates scraper
output (`_data/<locale>/bill_<uuid>.json`) — and joins topic tags from
`govbot tag` output (`tags/*.tag.json`).

On every Pages deploy (and on a daily 8am UTC schedule), the workflow shallow-clones
every `*-legislation` repo from the
[govbot-openstates-scrapers](https://github.com/govbot-openstates-scrapers)
organization and rebuilds `data.json` from all of them, so the published dashboard
covers every tracked jurisdiction. If that step fails, the deploy falls back to the
committed sample data rather than breaking the docs site.

The committed sample data is built from the offline mocks
(`actions/govbot/mocks/.govbot` — Wyoming and Guam), with demo topics derived from
the keyword definitions in `scripts/dashboard_tags.json` (the same shape as the
`tags:` section of `govbot.yml`, keyword-only mode):

```bash
python3 scripts/build_dashboard_data.py \
--govbot-dir actions/govbot/mocks/.govbot \
--tags-config scripts/dashboard_tags.json \
--output docs/src/dashboard/data.json
```

## Regenerating locally with real data

```bash
govbot clone all # clone the dataset repos (~/.govbot/repos)
govbot tag # optional: score bills against your govbot.yml tags
python3 scripts/build_dashboard_data.py --output docs/src/dashboard/data.json
```

When real `tags/*.tag.json` files exist for a session, they take precedence over
the keyword fallback; a bill gets a tag when its `final_score` meets the tag's
configured threshold. Commit the regenerated `data.json` and the Pages workflow
publishes it with the rest of the docs.
1 change: 1 addition & 0 deletions docs/src/dashboard/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"generated_at":"2026-07-05T21:15:49Z","source":"actions/govbot/mocks (offline sample)","states":[{"code":"gu","name":"Guam"},{"code":"wy","name":"Wyoming"}],"empty_jurisdictions":[],"tags":[{"name":"budget & taxes","description":"Appropriations, taxation, fees, and public funds"},{"name":"education","description":"Schools, universities, and education policy"},{"name":"environment & wildlife","description":"Natural resources, wildlife, hunting, fishing, and energy"},{"name":"government operations","description":"Permitting, licensing, elections, and agency administration"},{"name":"health care","description":"Health care, public health, and insurance coverage"}],"bills":[{"state":"gu","session":"38th","id":"B 1-38","title":"AN ACT TO AMEND § 26603(d)(5)(B) OF ARTICLE 2, CHAPTER 26, TITLE 11 GUAM CODE ANNOTATED, RELATIVE TO THE ANNUAL APPROPRIATION LEVEL TO THE GUAM CANCER TRUST FUND.","chamber":"legislature","latest_action":null,"latest_action_desc":null,"sponsors":["Telo T. Taitague"],"url":"https://guamlegislature.gov/bills/","tags":["budget & taxes"]},{"state":"gu","session":"38th","id":"B 10-38","title":"AN ACT TO ADD NEW §§ 4131 AND 4131.1 TO ARTICLE 1 OF CHAPTER 4, TITLE 4, GUAM CODE ANNOTATED, RELATIVE TO ESTABLISHING THE GOVERNMENT OF GUAM PUBLIC SAFETY AND LAW ENFORCEMENT OFFICERS’ LINE OF DUTY DEATH BENEFIT, AND TO REQUIRE THE DEVELOPMENT OF ADMINISTRATIVE RULES AND REGULATIONS.","chamber":"legislature","latest_action":null,"latest_action_desc":null,"sponsors":["Eulogio Shawn Gumataotao"],"url":"https://guamlegislature.gov/bills/","tags":[]},{"state":"gu","session":"38th","id":"B 100-38","title":"AN ACT TO AMEND § 1102, CHAPTER 1, DIVISION 1; TO AMEND § 2407(f) OF ARTICLE 4, CHAPTER 2, DIVISION 1; AMEND ARTICLE 1, CHAPTER 12; ADD A NEW § 12101.1 OF ARTICLE 1, CHAPTER 12; ADD A NEW § 80110 (c)(11) TO CHAPTER 80, DIVISION 4; ADD A NEW § 86105 (e) TO CHAPTER 86, ALL OF TITLE 10, GUAM CODE ANNOT","chamber":"legislature","latest_action":null,"latest_action_desc":null,"sponsors":["Sabina Flores Perez"],"url":"https://guamlegislature.gov/bills/","tags":["education"]},{"state":"gu","session":"38th","id":"B 11-38","title":"AN ACT TO AMEND § 26202(a), § 26202(c), § 26202(d), § 26202(e), § 26202(f), § 26202(g), § 26202(h), § 26202(i), AND § 26202(j), ALL OF ARTICLE 2, CHAPTER 26, TITLE 11, GUAM CODE ANNOTATED, RELATIVE TO DELIVERING FINANCIAL RELIEF TO GUAM FAMILIES AND BUSINESSES IN THE FACE OF HIGHER COSTS OF LIVING, ","chamber":"legislature","latest_action":null,"latest_action_desc":null,"sponsors":["Eulogio Shawn Gumataotao"],"url":"https://guamlegislature.gov/bills/","tags":["budget & taxes"]},{"state":"gu","session":"38th","id":"B 12-38","title":"AN ACT TO RESERVE LOT NO. 2417-1-R7, THE FORMER DEPARTMENT OF PUBLIC HEALTH AND SOCIAL SERVICES MAIN BUILDING IN MANGILAO, FOR IMMEDIATE USE BY THE DEPARTMENT OF PUBLIC HEALTH AND SOCIAL SERVICES AND TO AUTHORIZE ITS USE FOR THE GUAM COMMUNITY COLLEGE NURSING PROGRAM.","chamber":"legislature","latest_action":null,"latest_action_desc":null,"sponsors":["Therese M. Terlaje"],"url":"https://guamlegislature.gov/bills/","tags":["government operations","health care"]},{"state":"wy","session":"2025","id":"HB0001","title":"General government appropriations-2.","chamber":"lower","latest_action":"2025-03-06","latest_action_desc":"H See Mirror Bill SF0001","sponsors":["Appropriations"],"url":"https://wyoleg.gov/Legislation/2025/HB0001","tags":["budget & taxes"]},{"state":"wy","session":"2025","id":"HB0002","title":"Hunting license application fees increase.","chamber":"lower","latest_action":"2025-02-11","latest_action_desc":"H COW:H Did not consider for COW","sponsors":["Travel, Recreation, Wildlife and Cultural Resource"],"url":"https://wyoleg.gov/Legislation/2025/HB0002","tags":["budget & taxes","environment & wildlife","government operations"]},{"state":"wy","session":"2025","id":"HB0003","title":"Animal abuse-predatory animals.","chamber":"lower","latest_action":"2025-03-03","latest_action_desc":"H:Died in Committee Returned Bill Pursuant to HR 5-4","sponsors":["Travel, Recreation, Wildlife and Cultural Resource"],"url":"https://wyoleg.gov/Legislation/2025/HB0003","tags":["environment & wildlife"]},{"state":"wy","session":"2025","id":"HB0004","title":"Snowmobile registration and user fees.","chamber":"lower","latest_action":"2025-02-25","latest_action_desc":"Assigned Chapter Number 38","sponsors":["Travel, Recreation, Wildlife and Cultural Resource"],"url":"https://wyoleg.gov/Legislation/2025/HB0004","tags":["budget & taxes","environment & wildlife","government operations"]},{"state":"wy","session":"2025","id":"HB0005","title":"Fishing outfitters and guides-registration of fishing boats.","chamber":"lower","latest_action":"2025-02-27","latest_action_desc":"Assigned Chapter Number 50","sponsors":["Travel, Recreation, Wildlife and Cultural Resource"],"url":"https://wyoleg.gov/Legislation/2025/HB0005","tags":["environment & wildlife","government operations"]},{"state":"wy","session":"2026","id":"HB0002","title":"Fast Track Permits Act.","chamber":"lower","latest_action":"2025-12-01","latest_action_desc":"Bill Number Assigned","sponsors":["Filer","Geringer","Love"],"url":"https://wyoleg.gov/Legislation/2026/HB0002","tags":["government operations"]},{"state":"wy","session":"2026","id":"HB0003","title":"Wyoming pregnancy centers-autonomy and rights.","chamber":"lower","latest_action":"2025-12-01","latest_action_desc":"Bill Number Assigned","sponsors":["Labor, Health and Social Services"],"url":"https://wyoleg.gov/Legislation/2026/HB0003","tags":["health care"]},{"state":"wy","session":"2026","id":"HB0004","title":"Birthing centers-Medicaid coverage.","chamber":"lower","latest_action":"2025-12-01","latest_action_desc":"Bill Number Assigned","sponsors":["Labor, Health and Social Services"],"url":"https://wyoleg.gov/Legislation/2026/HB0004","tags":["health care"]},{"state":"wy","session":"2026","id":"HB0005","title":"Oil and gas bonding pool-investment and earnings.","chamber":"lower","latest_action":"2025-12-01","latest_action_desc":"Bill Number Assigned","sponsors":["Minerals, Business and Economic Development"],"url":"https://wyoleg.gov/Legislation/2026/HB0005","tags":["budget & taxes","environment & wildlife"]},{"state":"wy","session":"2026","id":"HB0006","title":"Unemployment insurance coverage-period and reporting.","chamber":"lower","latest_action":"2025-12-01","latest_action_desc":"Bill Number Assigned","sponsors":["Labor, Health and Social Services"],"url":"https://wyoleg.gov/Legislation/2026/HB0006","tags":["budget & taxes","health care"]}]}
Loading