A single-page web app where users enter their address to discover their federal and state elected representatives, complete with contact information, photos, and party affiliation.
- Address Search: Enter your address to find representatives
- Comprehensive Data: Pulls from both 5 Calls API and Open States API
- Rich Contact Information: Phone, email, website, and social media links
- Responsive Design: Works on mobile, tablet, and desktop
- Real-time Feedback: Loading states and error handling
- Runtime: Node.js 18+
- Framework: Next.js 14+ with App Router
- Language: TypeScript (strict mode)
- Styling: Tailwind CSS
- Deployment: Vercel
- External APIs:
- 5 Calls API - Federal and state representatives
- Open States API v3 - State legislators with detailed data
- OpenStreetMap Nominatim - Address geocoding
- Node.js 18 or higher
- npm or yarn
- Clone the repository:
git clone <repository-url>
cd who-are-my-reps- Install dependencies:
npm install- Set up environment variables:
cp .env.local.example .env.local- Edit
.env.localand add your Open States API key:
OPEN_STATES_API_KEY=your_api_key_here
FIVE_CALLS_API_URL=https://api.5calls.org/v1
Get your Open States API key at openstates.org/api.
Start the development server:
npm run devOpen http://localhost:3000 in your browser.
Build for production:
npm run build
npm start- Push your repository to GitHub
- Visit vercel.com
- Click "New Project" and import your repository
- Add environment variables in the Vercel dashboard:
OPEN_STATES_API_KEY: Your Open States API keyFIVE_CALLS_API_URL:https://api.5calls.org/v1
- Deploy
.
├── app/
│ ├── api/
│ │ └── reps/
│ │ └── route.ts # Main API endpoint
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home page
│ └── globals.css # Global styles
├── components/
│ ├── AddressInput.tsx # Address search input
│ ├── RepCard.tsx # Individual representative card
│ └── RepList.tsx # List of representatives
├── lib/
│ ├── types.ts # Shared TypeScript types
│ ├── five-calls.ts # 5 Calls API client
│ ├── open-states.ts # Open States API client
│ ├── merge.ts # Merge and deduplicate logic
│ └── geocode.ts # Address geocoding
├── package.json
├── tsconfig.json
├── tailwind.config.ts
├── postcss.config.js
└── next.config.js
Fetch representatives for an address.
Query Parameters:
address(required): The address to search for
Response:
{
"representatives": [
{
"name": "John Doe",
"photoUrl": "https://...",
"party": "Democratic",
"title": "U.S. Senator",
"district": "CA",
"level": "federal",
"contact": {
"phone": "(202) 224-3121",
"email": "john@senate.gov",
"website": "https://..."
},
"socialMedia": {
"twitter": "johndoe",
"facebook": "johndoe"
}
}
],
"warnings": []
}- 400 Bad Request: Missing or invalid address parameter
- 502 Bad Gateway: Both API sources failed
- Partial Failures: If one API fails, the other's data is still returned with a warning
- All components use React Server Components by default
- Add
"use client"only where needed (event handlers, state) - No database or state management library (pure React hooks)
- TypeScript strict mode is enabled
- All styling uses Tailwind CSS only
Run TypeScript type checking without building:
npx tsc --noEmitISC