BillTrax is the public-facing legislative intelligence platform built by AgoraDMV. It ingests public Congress.gov data, parses bill text into structured sections, tracks funding changes across versions, and surfaces AI-generated summaries and topic tags — giving researchers, advocates, and planning teams a clear view of how bills evolve and what they actually say.
Deployment target: BillTrax.AgoraDMV.org (soft launch in progress)
AgoraDMV maintains two sister projects with a deliberate scope boundary:
| DeltaTrack | BillTrax | |
|---|---|---|
| Audience | Capitol Hill staffers | Public users, researchers, journalists, advocates |
| Input | Two PDFs uploaded by the user | Public Congress.gov bill catalog + uploads |
| External calls | None — zero dependencies by design | Congress.gov API, AI services, public data feeds |
| AI | Out of scope | Core feature — summaries, tagging, classification |
| Data storage | Nothing leaves the device | Server-backed database, user accounts |
| Pre-public drafts | Supported (no data egress) | Not the target — works with public versions |
| Deployment | DeltaTrack.AgoraDMV.org | BillTrax.AgoraDMV.org |
The rule of thumb: if a capability is impossible in DeltaTrack due to its zero-dependency constraint — on-platform AI, bill status tracking, notifications, analytics, cross-bill comparisons — it belongs in BillTrax.
| Stakeholder | Typical use |
|---|---|
| Local governments | Grants, formula funds, pass-through timing, eligibility, and reporting burdens |
| Universities | Research agency accounts, student aid, facilities, and multi-year funding assumptions |
| Industry | Procurement posture, program offices, set-asides, and policy direction |
| Researchers / journalists | Longitudinal funding trends, section-level diffs between bill versions |
| Advocates | Issue tracking, intent analysis, and version-to-version change alerts |
| Tool | Notes |
|---|---|
| Docker Desktop | The only required host dependency |
| Git | For cloning the repo |
| A text editor | VS Code recommended |
Everything else—Node.js, MySQL, dependencies—runs inside Docker.
git clone <repo-url>
cd BillTrax
cp .env.example .env.local
cp docker-compose.yml.example docker-compose.yml.env.example and docker-compose.yml.example are committed templates. Copy each to its local counterpart and customize — never commit .env.local or docker-compose.yml (both are gitignored).
DeltaTrack's diff engine is vendored under submodules/DeltaTrack/ (a copied subset, not a git submodule). Sync from the upstream DeltaTrack repo when the algorithm changes.
Windows Docker Desktop: after copying docker-compose.yml, edit the web and diff-worker bind-mount paths from .:/app to your absolute Windows path (e.g. C:/Users/you/Projects/AgoraDMV/BillTrax:/app).
Minimum required in .env.local:
| Variable | Notes |
|---|---|
AUTH_SECRET |
Generate with npx auth secret |
DATABASE_URL |
Defaults in .env.example work for Docker; change host to localhost on a native install |
Recommended:
| Variable | Notes |
|---|---|
CONGRESS_API_KEY |
Free at api.congress.gov/sign-up — falls back to DEMO_KEY (30 req/hr) |
AI_API_KEY |
Needed for summaries and topic tagging (AI_PROVIDER / AI_MODEL are pre-set) |
APP_URL |
Set to your public HTTPS URL in production (used in password-reset and alert emails) |
See .env.example for the full variable list, including optional SMTP and diff-worker tuning.
BillTrax uses its own SMTP relay for transactional email (password reset, version alerts). No external email service is required — just an SMTP host.
Leave SMTP_HOST blank during development. Emails are printed to the container log instead of sent:
docker compose logs -f web # watch for [email:log] linesTo wire up a real provider, set these variables in .env.local:
SMTP_HOST=smtp.mailgun.org # or smtp.postmarkapp.com, email-smtp.us-east-1.amazonaws.com, etc.
SMTP_PORT=587
SMTP_SECURE=false # true only for port 465
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
SMTP_FROM="BillTrax <no-reply@yourdomain.com>"
APP_URL=https://your-public-host # used to build reset links in emailsAny standard SMTP relay (Mailgun, Postmark, Amazon SES, a self-hosted Postfix instance) works without code changes.
docker compose up -dThis starts four services:
| Service | Port | Role |
|---|---|---|
web |
3002 | Next.js app (dev server with hot reload) |
node-backend |
3001 | Standalone Congress.gov compare API (optional; main app calls Congress.gov directly) |
diff-worker |
(internal) | Background diff job consumer (DeltaTrack/Python) |
mysql |
(internal) | MySQL 8.4 database |
Database migrations run automatically on first startup. The schema is fully managed — no manual SQL setup required.
Open http://localhost:3002 to see the app.
- Go to http://localhost:3002/register
- Create a username and password
- You'll land on the dashboard — it's empty until you ingest a bill
Pull a bill from Congress.gov into the local database:
# Ingest the House Appropriations bill for the 119th Congress
docker compose run --rm web npm run ingest -- --congress 119 --bill hr-4366The ingest script fetches all available versions of the bill, parses XML into sections, and writes them to the database. After it finishes, refresh the dashboard to see the bill.
To ingest a different bill, find its number on congress.gov and substitute --congress and --bill accordingly.
Bill detail view (/bills/<id>)
- Read the full structured bill text, organized by section
- Switch between versions using the version picker
- View which legislative stage the bill is at
Side-by-side compare (/bills/<id>/compare/<fromCode>/<toCode>)
- Section-level diff between any two versions of a bill powered by DeltaTrack
- Each section is labeled:
added,removed,modified,unchanged, ormoved - Financial changes (dollar amounts added, removed, or changed) are extracted automatically
Dashboard (/dashboard)
- Subscribe to bills to track them
- Your subscribed bills appear on the dashboard with stage badges
- Notes are per-bill and private to your account
AI features (requires AI_API_KEY)
- Topic tagging: scans bill text and suggests structured topic tags
- Summaries: generates a plain-language summary of a bill section or version diff
Press releases
- Sync committee press releases alongside bill data:
docker compose run --rm web npm run sync:press-releases
Background polling (keeps subscribed bills up to date without manual ingest):
# Check Congress.gov for new versions of all bills already in the catalog
docker compose run --rm web npm run poll:congress -- --congress 119Run this on a cron to get version-alert emails automatically (put SMTP_HOST in .env.local first).
Roll call votes
docker compose run --rm web npm run sync:roll-call -- --congress 119 --chamber bothMember bios (adds party/state badges to sponsor display):
docker compose run --rm web npm run sync:membersFor a Linux server running Node directly (e.g. web2@prod):
| Tool | Version |
|---|---|
| Node.js | 24 LTS |
| MySQL | 8.4 (or 8.x) |
| Python 3 | stdlib only — no pip packages needed for diffs |
| Git | For cloning the repo |
git clone <repo-url> BillTrax
cd BillTrax
cp .env.example .env.localEdit .env.local for the server:
AUTH_SECRET=<output of: npx auth secret>
DATABASE_URL=mysql://billtrax:YOUR_PASSWORD@localhost:3306/billtrax
CONGRESS_API_KEY=<your key>
APP_URL=https://billtrax.yourdomain.orgCreate the MySQL database and user (see mysql-init.sql for the schema naming), then:
npm ci
npm run db:migrate
npm run build
PORT=3000 npm start # web app
npm run diff-worker # background diffs — run as a separate process/servicePut nginx or Caddy in front of port 3000 for HTTPS. Run npm run diff-worker under systemd or supervisord alongside the web process.
CLI scripts (ingest, poll:congress, etc.) run directly on the host with npm run <script> — no docker compose wrapper needed.
All commands run inside Docker via docker compose exec:
# Tail logs
docker compose logs -f web
# TypeScript type-check
docker compose exec web npm run typecheck
# Lint (ESLint flat config)
docker compose exec web npm run lint
# Unit tests (Vitest)
docker compose exec web npm test
# Run tests in watch mode
docker compose exec web npm run test:watch
# E2E tests (Playwright, spins up an ephemeral DB)
docker compose -f docker-compose.yml -f docker-compose.test.yml \
run --rm playwright npm run test:e2e
# Production build check
docker compose run --rm web npm run build
# Database migration status
docker compose exec web npm run db:status
# Roll back last migration batch
docker compose exec web npm run db:rollbackThe dev container watches src/ and public/ via Docker Compose Watch. To enable:
docker compose watchChanges to files in src/ sync into the running container immediately without a rebuild. Changes to package.json trigger a rebuild automatically.
BillTrax/
├── src/
│ ├── app/ Next.js App Router
│ │ ├── api/ REST API routes
│ │ │ ├── auth/ NextAuth sign-in / session
│ │ │ ├── bills/ Bill catalog CRUD
│ │ │ ├── catalog/ Congress.gov bill import
│ │ │ ├── congress/ Congress.gov proxy (versions, text)
│ │ │ ├── interest-areas/ User interest area management
│ │ │ ├── notes/ Per-bill notes
│ │ │ ├── press-releases/ Committee press release feed
│ │ │ ├── reports/ Committee report sections
│ │ │ ├── search/ Full-text search across bills
│ │ │ ├── share/ Shareable diff links
│ │ │ ├── subscriptions/ User → bill subscriptions
│ │ │ └── topics/ Topic tag management + AI matching
│ │ ├── bills/ Public bill pages
│ │ │ └── [id]/compare/ Side-by-side version diff
│ │ ├── dashboard/ Auth-gated user dashboard
│ │ ├── login/ Sign-in page
│ │ └── register/ Account creation
│ ├── components/ Shared React components (shadcn/ui)
│ ├── lib/ Business logic
│ │ ├── db.ts MySQL pool, query helpers, migrations
│ │ ├── bills.ts Bill/version query functions
│ │ ├── email.ts Outbound email (own-rolled SMTP)
│ │ ├── notifications.ts Version-alert email queue
│ │ ├── password-reset.ts Token generation + validation
│ │ ├── poll.ts Per-bill Congress.gov polling helper
│ │ ├── members.ts Member bio queries
│ │ ├── roll-call-votes.ts Roll call vote queries
│ │ ├── section-parser.ts XML → structured sections
│ │ ├── section-diff.ts Section-level diff orchestration
│ │ ├── python-diff.ts DeltaTrack subprocess bridge
│ │ ├── financial.ts Dollar-amount extraction
│ │ └── congress-api.ts Congress.gov API client
│ └── types/ Shared TypeScript types
├── migrations/ Knex migration files (run automatically)
├── scripts/
│ ├── ingest.ts Bill ingestion CLI
│ ├── diff_service.py DeltaTrack diff engine (Python subprocess)
│ ├── backfill-deltatrack.ts Re-diff existing pairs through DeltaTrack
│ ├── sync-press-releases.ts Press release sync CLI
│ ├── poll-congress.ts Background version polling (run on cron)
│ ├── sync-roll-call-votes.ts Roll call vote sync from Congress.gov
│ └── sync-members.ts Member bio sync from unitedstates/congress-legislators
├── submodules/
│ └── DeltaTrack/ Vendored diff engine (sync from upstream DeltaTrack)
├── node_backend/ Lightweight fetch/diff service
├── docker-compose.yml.example Dev stack template (copy → docker-compose.yml)
├── docker-compose.prod.yml Production Docker stack
├── Dockerfile Multi-stage image (dev / ci / prod)
├── knexfile.ts Knex migration config
└── auth.ts Auth.js v5 config
| Layer | Choice |
|---|---|
| Framework | Next.js 16 App Router, TypeScript (build pinned to webpack) |
| Styling | Tailwind CSS + shadcn/ui (Radix UI) |
| Auth | Auth.js v5 — Credentials provider, JWT sessions |
| Database | MySQL 8.4 via mysql2/promise |
| Migrations | Knex (migration runner only) |
| AI | Vercel AI SDK — provider-agnostic (Anthropic / OpenAI / DeepSeek) |
| Diff engine | DeltaTrack (Python, vendored copy) via subprocess |
| Testing | Vitest (unit) + Playwright (E2E) |
| Fonts | Fraunces (serif headings) · Inter (sans body) · JetBrains Mono |
| Project | Repo | Description |
|---|---|---|
| BillTrax | AgoraDMV/BillTrax | This project — public legislative intelligence platform |
| DeltaTrack | AgoraDMV/DeltaTrack | Zero-dependency PDF diff tool for Hill staffers |
| aCURE | folkes.tom/aCURE | Open-source bill tracking and issues workstream |
The structural diff algorithm powering BillTrax's section compare is vendored from DeltaTrack and runs server-side as a Python subprocess, giving BillTrax access to the same high-quality structural matching while adding persistent storage, background jobs, and LLM integration that DeltaTrack's zero-dependency constraint prohibits.
The project is in soft-launch / user-testing phase. For access to the AgoraDMV GitHub org, contact the maintainer with your GitHub username. For questions or early collaboration, use the project's issue tracker.
BillTrax — appropriations intelligence for planning across government, academia, and industry.