Skip to content
Back to skills

Ballot Research Guide

ASecurity

Turn a voter's sample ballot (any U.S. state, county or city) into a nonpartisan research guide (web page + PDF) and a one-page fill-in ballot cheat sheet, with state-specific first-time-voter rules and voting windows. Also helps the voter find their sample ballot.

  • 3 stars
  • 0 votes
  • 2 copies
  • 3 views
  • Added October 22, 2026
researchpythongobashperformance

Works with

  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 8 files and shows the line behind each finding

Scanned October 22, 2026

npx -y skills add b0bsl3d/InformedVoter --skill ballot-research-guide --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ballot Research Guide?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ballot Research Guide
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/b0bsl3d-ballot-research-guide/badge)](https://www.skillsdirectory.com/skills/b0bsl3d-ballot-research-guide)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ballot-research-guide
description: Turn a voter's sample ballot (any U.S. state, county or city) into a nonpartisan research guide (web page + PDF) and a one-page fill-in ballot cheat sheet, with state-specific first-time-voter rules and voting windows. Also helps the voter find their sample ballot.
---

# Ballot Research Guide

Produce two deliverables from a voter's sample ballot:

1. **Research guide.** Every contested race in ballot order. Each race is a clearly separated box with a poll strip, candidate facts and links. Published as an artifact and rendered to PDF.
2. **Cheat sheet.** One printable letter page listing **every** contest, contested and uncontested, in exact ballot order, with checkboxes the voter fills in before going to vote.

Both are built from one data file, `ballot.json`, by the scripts in `scripts/`. Gather the facts, write the JSON, run the scripts.

## Ground rules (apply throughout)

- **Strictly nonpartisan.** Never recommend a candidate or a vote on a measure, even if the user shares their own leanings. Give every side the same effort, tone and depth.
- **Verify, don't recall.** Election rules, dates, deadlines and candidate facts change. Look up everything about this election; never fill a gap from memory.
- **No voter-file data.** Never use voter registration or primary-voting history to label anyone.
- **Copyright.** Paraphrase sources. Keep any quote under 15 words, and use at most one quote per source.
- **Flag thin information.** When little is published about a candidate, say so. Never pad with guesses.

## Step 1: Get the ballot

- **If the user attached a sample ballot** (PDF or images), read every page.
- **If not, help them find it.**
  - Ask for state and county. Ask for city, or address or precinct, only if they're comfortable sharing it.
  - Search for the county (or city or town, in states that run elections locally) elections office's sample ballot or "my ballot" lookup.
  - Give them the exact page, plus VOTE411.org and Ballotpedia's sample-ballot lookup as alternatives.
  - Ask them to download and attach the PDF.
  - Never reconstruct a ballot from an address. Ballots vary by precinct.
- **Transcribe into `ballot.json`.** Record every contest in exact order, including uncontested races, write-in lines, retention questions, measures and propositions. Keep the ballot's page or column labels and its section headers (federal, state, county, city, school district, special district, measures).
- **Confirm the transcription.** Count the contests and tell the user the count so they can check it against their ballot.

## Step 2: Ask a few questions

Use **one** AskUserQuestion call with at most 4 questions, asking only what changes the output.

- **Scope.** Research every contested race, or skip races the user has already decided? Default to all, and say why: guides often get shared, for example with a first-time voter.
- **Key local issues.** Which local controversies should each candidate's stance be documented on?
  - First run 2–3 quick news searches on the jurisdictions on this ballot.
  - Offer real issues as options, such as a school-district split, a bond, annexation, a rezoning or a recall.
- **Audience.** Is the guide for the user, or also for someone else? If a first-time voter will use it, include the full "First time voting?" box. Include a short version either way.
- **Party signals.** Should public party signals be noted for nonpartisan candidates?

**If the user isn't around to answer:** include all contested races, add the short voting-rules box, skip the issue section, and say which defaults you chose.

## Step 3: Verify the state and local voting rules

Read `references/state-voting-rules.md`. It lists every rule to verify and the sources to check, in priority order.

- Fill the `voting_info` block in `ballot.json` from this election's official sources: the state election office and the county or city clerk.
- Rules differ sharply by state: photo ID vs. no ID, same-day registration, early-voting dates, vote centers vs. assigned polling places, all-mail states, straight-ticket voting, phones and notes in the booth, ranked-choice voting, and ballot-return deadlines.
- Cite the official source for each item.
- If a rule can't be confirmed, write "Check with [office]" rather than guessing.

## Step 4: Research

For breadth, use a research subagent or extended research. Brief it with the full contest list, the issues from Step 2 and the rules below. Then fill gaps with targeted searches.

**For every contested race:**

- **Office.** One plain-language line on what the office does. Explain anything obscure or misleadingly named, such as a Railroad Commission, a soil and water district, or a coroner.
- **Candidates.**
  - Background, incumbency, and platform or key positions.
  - Notable endorsements from across the spectrum.
  - Money raised, where reported.
  - Documented controversies, from credible outlets only.
  - Links: campaign site, Facebook, Ballotpedia, VOTE411, and local news Q&As.
- **Voter polls.**
  - Use the latest public polls, with pollster, dates and margin of error.
  - Prefer nonpartisan or academic pollsters, and label partisan or internal polls.
  - With no poll, say so. A recent actual result between the same candidates may be shown, labeled as a result.
- **Judges.**
  - Include state and local bar association polls or ratings, with date, response rate and method. Say they are lawyer surveys, not endorsements.
  - Retention elections: include the state's judicial performance evaluation if one exists.
  - Include newspaper endorsements from more than one outlet.
- **Local issue stances** (from Step 2).
  - Gather on-record statements, votes and past roles.
  - Order candidates from most open to least open on the issue only when the record supports it.
  - If no candidate holds a position the user might expect, say so plainly.
- **Party signals** (nonpartisan races only, if requested).
  - Use only public party offices, partisan-group endorsements or recommendations, and candidates' own statements.
  - Write "none found" otherwise, and note that this doesn't mean they have no affiliation.
- **Measures, bonds and propositions.**
  - Give a neutral summary, the sponsor's rationale, and organized support and opposition.
  - Give the fiscal or tax impact with its assumptions, and quote the official ballot language if short.
  - Note supermajority thresholds where they apply.
- **Sources.** Prefer original and local sources: election offices, local and statewide newsrooms, Ballotpedia. Treat partisan-leaning outlets as single-source and label them.

## Step 5: Write ballot.json and build

- The schema and a small worked example are in `assets/example-ballot.json`. Follow it exactly.
- Party values are free text. The scripts map common labels (REP/R/Republican, DEM/D/Democratic, LIB, GRN, IND, nonpartisan) to colors: **Republicans red, Democrats blue, Libertarians gold, Greens green, independents and other parties purple, nonpartisan slate.**

```bash
pip install playwright --break-system-packages -q && python -m playwright install chromium   # once, if missing
python scripts/build_guide.py ballot.json guide.html          # research guide (HTML)
python scripts/build_cheatsheet.py ballot.json cheatsheet.html
python scripts/render_pdf.py guide.html guide.pdf --footer "Ballot Guide"
python scripts/render_pdf.py cheatsheet.html cheatsheet.pdf --one-page
```

**What the guide includes:**
- A header and a voting-rules box.
- A contents list.
- One ruled box per contested race. Each box has a header band, an office line and a **poll strip**: voter poll bars plus, for judges, bar-poll bars. Rating-style bar polls show as stacked bars, and missing data says so.
- Side-by-side candidate cards.
- Optional issue sections placed before the related races, with a timeline and a stance table that includes a party-signal column.
- A measures table, resources and caveats.

**What the cheat sheet includes:**
- Every contest, numbered, with divider bars at each ballot page or section change.
- A checkbox per choice; "unopposed" tags; write-in lines; For/Against or Yes/No boxes on measures.
- Ranked-choice contests get a rank grid. The voting-rules reminder sits at the top.
- `--one-page` shrinks the type until it fits one letter page. **If it still won't fit** (very long ballots), set `"cheatsheet_two_sided": true` and print double-sided.

**Before publishing:**
- Render two or three guide pages and the cheat sheet to PNG with `pdftoppm` and look at them once.
- Fix anything clipped or overlapping.
- The cheat-sheet order must match the ballot exactly.

## Step 6: Deliver

- Before publishing, load the `artifact-design` skill. Then publish `guide.html` as an artifact and send both PDFs.
- Tell the user, in one line each:
  - The artifact is private until they share it from the page's Share menu.
  - The cheat sheet is for marking in pen and bringing to vote, where phones may be restricted (say what this state's rule is).
- Offer one next step at most: a scheduled recheck of polls and late news a few days before Election Day, or before the last day of early voting if the state has one. If they accept, create it as a scheduled task that updates the same artifact.

Files in this skill

  • README.md2.3 KB
  • SKILL.md9.1 KB
  • assets/example-ballot.json6.5 KB
  • references/state-voting-rules.md3.8 KB
  • scripts/build_cheatsheet.py5.9 KB
  • scripts/build_guide.py19 KB
  • scripts/common.py1.6 KB
  • scripts/render_pdf.py2.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.