first commit
This commit is contained in:
commit
004aef2020
154
README.md
Normal file
154
README.md
Normal file
@ -0,0 +1,154 @@
|
||||
# Voting App
|
||||
|
||||
U.S. Congress legislator voting history viewer with AI-generated bill summaries.
|
||||
|
||||
## Features
|
||||
|
||||
- **Search legislators** by name with autocomplete suggestions (full name, state, party)
|
||||
- **View voting records** with endless scroll through a legislator's entire career
|
||||
- **AI-generated summaries** using a local GPT-OSS model for impartial bill analysis
|
||||
- **Local caching** with SQLite to avoid repeated API calls and survive outages
|
||||
- **Rate-limit aware** with exponential back-off (stays well under 1000 req/hr limit)
|
||||
- **Privacy-safe** error handling that never exposes API keys
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
User → React Frontend → Flask Backend → LegiScan API
|
||||
↕
|
||||
SQLite Cache
|
||||
↕
|
||||
Local GPT-OSS
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker and Docker Compose
|
||||
- LegiScan API key (sign up at https://legiscan.com)
|
||||
- Local GPT-OSS server running (e.g., LM Studio, Ollama, vLLM)
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
Copy `.env.example` to `.env` and fill in your values:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Required variables:
|
||||
|
||||
| Variable | Description | Default |
|
||||
|---|---|---|
|
||||
| `CONGRESS_API_KEY` | LegiScan API key | _(required)_ |
|
||||
| `CONGRESS_API_BASE_URL` | LegiScan API base URL | `https://api.legiscan.com` |
|
||||
| `GPT_OSS_BASE_URL` | Local GPT-OSS endpoint | `http://home.ms:4000/v1` |
|
||||
| `GPT_OSS_API_KEY` | GPT-OSS API key (if required) | _(optional)_ |
|
||||
| `BACKEND_PORT` | Host port for backend | `8001` |
|
||||
| `VITE_FRONTEND_PORT` | Host port for frontend | `5174` |
|
||||
| `VITE_API_URL` | Backend URL for frontend | `http://localhost:8001` |
|
||||
|
||||
Ports 8001 and 5174 are used to avoid conflicts with other services. Change them in `.env` as needed.
|
||||
|
||||
## Running
|
||||
|
||||
### Docker (recommended)
|
||||
|
||||
```bash
|
||||
# Start all services (backend + frontend)
|
||||
cd docker
|
||||
docker compose up -d --build
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Rebuild a single service
|
||||
docker compose down <service>
|
||||
docker compose up -d <service> --build
|
||||
|
||||
# Stop all services
|
||||
docker compose down
|
||||
```
|
||||
|
||||
Once running:
|
||||
- Frontend: `http://localhost:5174`
|
||||
- Backend API: `http://localhost:8001`
|
||||
|
||||
### Development (without Docker)
|
||||
|
||||
**Backend:**
|
||||
```bash
|
||||
uv sync
|
||||
uv run python -m src.main --port 8001
|
||||
```
|
||||
|
||||
**Frontend:**
|
||||
```bash
|
||||
cd frontend
|
||||
pnpm install
|
||||
VITE_API_URL=http://localhost:8001 pnpm dev
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
voting-app/
|
||||
├── .env # Environment variables (not committed)
|
||||
├── .env.example # Template for required variables
|
||||
├── pyproject.toml # Python dependencies (managed by UV)
|
||||
├── uv.lock # Locked Python dependencies
|
||||
├── src/ # Backend Python code
|
||||
│ ├── models.py # Data models (Legislator, Bill, Vote, Summary)
|
||||
│ ├── api_client.py # LegiScan API client (pagination, back-off)
|
||||
│ ├── gpt_oss_client.py # GPT-OSS client for impartial bill summaries
|
||||
│ ├── cache.py # SQLite cache layer
|
||||
│ ├── app.py # Flask REST API
|
||||
│ └── main.py # CLI entry point
|
||||
├── frontend/ # React TypeScript frontend
|
||||
│ ├── package.json # Frontend dependencies (managed by pnpm)
|
||||
│ ├── pnpm-lock.yaml # Locked frontend dependencies
|
||||
│ ├── vite.config.ts # Vite build configuration
|
||||
│ ├── src/
|
||||
│ │ ├── App.tsx # Main app with routing
|
||||
│ │ ├── components/ # UI components (Button, Input, Spinner, VoteCard, etc.)
|
||||
│ │ ├── pages/ # Page components (Home, LegislatorDetail)
|
||||
│ │ ├── store/ # Zustand state management
|
||||
│ │ ├── services/ # API client for backend
|
||||
│ │ ├── hooks/ # Custom React hooks
|
||||
│ │ └── types/ # TypeScript definitions
|
||||
├── tests/ # Test suites
|
||||
│ ├── unit/ # Python unit tests
|
||||
│ ├── integration/ # Integration tests
|
||||
│ └── e2e/ # End-to-end tests
|
||||
├── docker/ # Docker configuration
|
||||
│ ├── docker-compose.yml # Service orchestration
|
||||
│ ├── Dockerfile.backend # Python container
|
||||
│ └── Dockerfile.frontend # Node.js container
|
||||
└── data/ # Runtime data (SQLite DB, not committed)
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|---|---|---|
|
||||
| GET | `/health` | Health check |
|
||||
| GET | `/api/search?q=<query>` | Search legislators |
|
||||
| GET | `/api/legislators/<id>` | Legislator details |
|
||||
| GET | `/api/legislators/<id>/votes?limit=N&offset=M` | Voting record with summaries |
|
||||
| GET | `/api/bills/<id>/summary` | AI-generated bill summary |
|
||||
| GET | `/api/bills/<id>/text` | Full bill text |
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run Python tests
|
||||
uv run pytest tests/
|
||||
|
||||
# Run frontend linting
|
||||
cd frontend && pnpm lint
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Loading…
x
Reference in New Issue
Block a user