commit 004aef2020b73eeced95c70d525495483a6a962d Author: jarianc Date: Fri May 15 15:15:07 2026 -0500 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..8106bc3 --- /dev/null +++ b/README.md @@ -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 +docker compose up -d --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=` | Search legislators | +| GET | `/api/legislators/` | Legislator details | +| GET | `/api/legislators//votes?limit=N&offset=M` | Voting record with summaries | +| GET | `/api/bills//summary` | AI-generated bill summary | +| GET | `/api/bills//text` | Full bill text | + +## Testing + +```bash +# Run Python tests +uv run pytest tests/ + +# Run frontend linting +cd frontend && pnpm lint +``` + +## License + +MIT \ No newline at end of file