Track US state and federal legislation. Follow bills, get email alerts when their status changes, and search across all 50 states and Congress via the LegiScan API.
Features:
- Search bills by keyword and state/jurisdiction
- Follow bills and pin the ones you care about most
- Dashboard with followed bills and a 7-day status digest
- Email notifications when a bill's status changes
- Onboarding to set your default state, with settings to change it later
flowchart LR
User([User])
Admin([Admin])
Cron([node-cron])
subgraph BillBoard
RegisterLogin([Register / Login])
SearchBills([Search Bills])
FollowBill([Follow / Unfollow Bill])
PinBill([Pin / Unpin Bill])
ViewDashboard([View Dashboard])
ViewBillDetail([View Bill Detail])
UpdateSettings([Update Settings])
ReceiveEmail([Receive Email Notification])
SyncBills([Sync Bills])
end
User --- RegisterLogin
User --- SearchBills
User --- FollowBill
User --- PinBill
User --- ViewDashboard
User --- ViewBillDetail
User --- UpdateSettings
User --- ReceiveEmail
Admin --- SyncBills
Cron --- SyncBills
sequenceDiagram
actor User
participant Frontend
participant Backend
participant Database
User->>Frontend: search for a bill
Frontend->>Backend: GET /api/bills/search?q=...
Backend->>Database: query bills table
Database-->>Backend: matching bills
Backend-->>Frontend: bill list
Frontend-->>User: display results
User->>Frontend: click Follow
Frontend->>Backend: POST /api/bills/:id/follow
Backend->>Database: INSERT INTO follows
Database-->>Backend: ok
Backend-->>Frontend: 200 OK
Frontend-->>User: bill added to dashboard
erDiagram
users {
serial id PK
text email UK
text password_hash
text state
boolean email_notifications
text unsubscribe_token
timestamptz created_at
}
bills {
serial id PK
int legiscan_bill_id UK
text bill_number
text title
text description
text state
text status
date status_date
text change_hash
timestamp last_synced_at
jsonb raw_data
text subjects
}
follows {
serial id PK
int user_id FK
int bill_id FK
timestamp followed_at
boolean pinned
}
bill_status_history {
serial id PK
int bill_id FK
text status
date status_date
timestamp recorded_at
}
users ||--o{ follows : "creates"
bills ||--o{ follows : "tracked in"
bills ||--o{ bill_status_history : "has history"
-
Copy env and fill in the values:
cp billboard/server/.env.example billboard/server/.env
Variable Where to get it DATABASE_URLYour Supabase project's connection string JWT_SECRETAny random string (e.g. openssl rand -hex 32)LEGISCAN_API_KEYYour LegiScan API key -
Install dependencies:
cd billboard/server && npm install cd ../client && npm install
Start both terminals before opening the app. Make sure to start the server before starting the client.
Terminal 1 - backend:
cd billboard/server
npm run devTerminal 2 - frontend:
cd billboard/client
npm run devOpen http://localhost:5173. The frontend proxies /api/* to localhost:3001.
- Frontend: React + Vite + Tailwind CSS
- Backend: Express (Node.js)
- Database: PostgreSQL (Supabase)
- Auth: JWT + bcrypt
- Email: Resend