txvotes.app — A personalized AI voting guide for US elections. Walks any voter through a quick interview about their values, looks up their specific ballot, researches every candidate, and generates personalized recommendations with a printable cheat sheet.
- Interview (2 minutes) — Tap through questions about your top issues, political approach, policy views, candidate qualities, and which primary you're voting in
- Address — Enter your home address so we can find your exact districts and ballot
- AI Research — Claude researches every candidate on your ballot and matches them to your stated values
- Your Guide — Browse personalized recommendations with pros, cons, strategic notes, and honest caveats
- Cheat Sheet — A printable one-page summary to take to the polls
Available in English and Spanish.
A single Cloudflare Worker serves the entire app — landing page, PWA, API routes, and daily election data updates. No build step, no bundler, no framework. Everything is inline JavaScript and CSS.
- Cloudflare Worker — serves HTML, handles API routes, runs scheduled updates
- Claude API — powers voter profile analysis and candidate recommendations (server-side, secrets never reach the client)
- KV Storage — caches election ballot data, guide responses, and ballot descriptions
- Census Geocoder — looks up congressional/state districts from street address
- Local-first — all voter data stored in
localStorage, nothing on our servers
worker/src/
├── index.js # Router, landing page, static pages, API endpoints
├── pwa.js # PWA single-page app (HTML/CSS/JS inline, ~3800 lines)
├── pwa-guide.js # Server-side Claude API calls for guide + summary
├── county-seeder.js # Data population pipeline for county races via Claude + web_search
├── updater.js # Daily cron job to refresh election data in KV
├── audit-runner.js # AI audit runner (ChatGPT, Gemini, Claude, Grok bias scoring)
├── balance-check.js # API balance/quota checker
├── rate-limit.js # Rate limiting
└── usage-logger.js # Usage logging
worker/tests/
├── 19 test files # 1629+ tests (vitest + happy-dom)
worker/public/
├── headshots/ # Candidate headshot images
├── og-image*.png/svg # Open Graph social sharing images
└── favicon*/apple-* # Favicons and app icons
Primary deployment target is txvotes.app:
cd worker && npx wrangler deploy -c wrangler.txvotes.toml| Site | Worker | Config |
|---|---|---|
| txvotes.app (primary) | usvotes-api |
wrangler.txvotes.toml |
| atxvotes.app (legacy) | atxvotes-api |
wrangler.toml |
Both workers share the same ELECTION_DATA KV namespace. Daily cron runs on usvotes-api; atxvotes-api only handles redirects.
cd worker
npx wrangler devVisit http://localhost:8787/app for the PWA, or http://localhost:8787/ for the landing page.
Requires secrets configured via Wrangler:
npx wrangler secret put ANTHROPIC_API_KEY -c wrangler.txvotes.toml
npx wrangler secret put ADMIN_SECRET -c wrangler.txvotes.tomlBranch protection is enabled on main. All changes require a pull request with passing CI and at least one approving review.
Workflow:
- Create a feature branch:
git checkout -b my-feature - Make changes and run tests locally:
cd worker && npx vitest run - Push and open a PR:
git push -u origin my-feature && gh pr create - CI runs automatically — tests must pass before merging
- Get a review, then merge — auto-deploy to txvotes.app on merge
Automation:
- CI — tests run on every PR and push to main (
.github/workflows/test.yml) - Auto-deploy — merges to main deploy to txvotes.app automatically (
.github/workflows/deploy.yml) - Auto-merge — PRs merge automatically once CI passes and review is approved
- Auto-delete branches — head branches are cleaned up after merge
cd worker && npx vitest run1629+ tests across 19 test files covering interview flows, guide generation, routing, bias detection, token budgets, audit scoring, rate limiting, SSE streaming, public stats, and more.
- Interview flow — 8-phase guided interview (tone, issues, spectrum, deep dives, qualities, freeform, address, building)
- Bilingual — Full English/Spanish support via
TRdictionary witht(key)function - Smart caching — SHA-256 hashed guide responses (1-hour TTL), ballot description caching
- Truncation repair — Auto-retry with doubled token budget on truncation, partial JSON recovery
- AI audit system — Automated bias scoring across 4 AI providers (ChatGPT, Gemini, Claude, Grok)
- County seeder — Batch data enrichment pipeline for all 254 Texas counties
- Easter eggs — Texas Cowboy mode (reading level 7), secret menu, vanity URLs
Created by Joshua Baer, Austin TX — 2025 Powered by Claude (Anthropic)