# Project export: Replicant

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2025
- Tagline: Create dynamic, data-driven constituent personas that let policymakers engage with representative models of their entire district—advancing inclusive governance.
- Devpost: https://devpost.com/software/replicant
- GitHub: https://github.com/syedahibahasan/civic-twin
- Video: https://www.youtube.com/embed/Pj5Rhk81Fs4?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — Nathan Liu (24 commits), Hiba Hasan (10 commits), saahithi (8 commits)

## Devpost submission (written by the team)

### Inspiration

Every. Single. Individual. Is impacted by policy—yet fewer than 0.1% of constituents in the U.S. provide feedback on the very legislation that shapes every aspect of our lives. Our team brings experience across local, state, and federal policymaking, and we've seen firsthand how the current system perpetuates a cycle of bias and inaccessibility. Those who do reach out to lawmakers are often those with the most extreme viewpoints, creating a feedback loop that reflects only a narrow slice of public opinion. This is a textbook case of self-selection bias—and it’s not limited to direct outreach. The same pattern shows up in surveys, public comment periods, and other engagement attempts. As a result, a small, unrepresentative group ends up having a disproportionate influence on the laws and policies that govern us all.

### What it does

At its core, Replicant is a digital, AI-powered platform that generates constituent personas using live data from the U.S. Census Bureau. These personas are designed to reflect the 99.9% of the population and help drive more equitable and inclusive policy making. Users can interact with each persona through an integrated chat feature, allowing for deeper exploration and iterative feedback based on evolving policy questions.

### How we built it

We developed the frontend using React, enabling a smooth and responsive user experience. The backend is powered by Node.js with Express, and we use Supabase to manage authentication, and data storage. For AI integration, we relied on two key models: Claude and Groq. Claude was chosen for its advanced reasoning capabilities, which we use to generate rich and logically consistent constituent profiles that reference census data. This reasoning is crucial to ensuring each persona accurately reflects the complex identities and needs of real constituents. To power the live chat experience, we integrated Groq, which offers up to 10x faster response times for large language models. This speed enhancement makes real-time interaction with constituent personas seamless and scalable. Together, this tech stack allows Replicant to deliver a meaningful, data-informed, and dynamic experience that can bring underrepresented voices into the heart of policymaking.

### Accomplishments we're proud of

We’re proud that we built something both functional and impactful in a short amount of time. The creativity behind Replicant—from concept to execution—reflects our team’s passion for solving meaningful problems with technology. We took on a complex challenge and delivered a product that has the potential to reshape how policymakers understand and engage with their communities.

### What we learned

We learned the importance of thinking beyond surface-level functionality. It’s not enough for a product to seem like it works, rather real functionality means accounting for edge cases and avoiding hard coded shortcuts. By building with real users in mind, we were pushed to write cleaner, more adaptable code. Challenges Faced One of the main challenges we faced was ensuring that each constituent profile was grounded in real Census data rather than being entirely hallucinated by the AI—we were committed to preserving the integrity and authenticity of every persona

### What's next

We’re just getting started. Our next major goal is to expand Replicant beyond the United States and begin supporting international regions. Policy challenges—like inequality, climate change, and health disparities—are global in scope, and the need for representative, data-informed decision-making exists in every country. We're exploring integrations with global data sources such as the United Nations, Eurostat, and national statistical agencies to generate accurate constituent personas across different geopolitical contexts. In addition, we plan to enhance the platform’s flexibility by allowing users to upload custom datasets. This feature will empower organizations—whether NGOs, governments, or academic institutions—to generate personas based on their own localized or issue-specific data. By broadening our data inputs and geographic reach, Replicant will become a truly global tool for inclusive policymaking. Ultimately, our mission is to help every policymaker in the world understand and engage with the full spectrum of people their policies affect—not just the loudest voices.

## README (from the GitHub repository)

# Replicant 🏛️

**AI-powered policy impact analysis for congressmen and legislative staff**

Replicant uses artificial intelligence and Census data to simulate how policies affect real constituents. Upload a bill, meet digital twins, and get actionable feedback before implementation.

## ✨ Features

- **🔐 Secure Authentication** - JWT-based authentication with Supabase backend
- **📄 Policy Upload & Analysis** - Upload documents or paste text for AI analysis
- **👥 Digital Twin Generation** - Create realistic constituents based on Census data
- **💬 Interactive Chat** - Talk with digital twins about policy impact
- **📊 Impact Analysis** - Get detailed reports and improvement suggestions
- **🏛️ Personalized Dashboard** - District-specific insights and quick actions

## 🚀 Quick Start

### Prerequisites
- Node.js 18+ 
- npm or yarn
- Supabase account and project

### Installation

1. **Clone the repository**
   ```bash
   git clone https://github.com/syedahibahasan/civic-twin.git
   cd civic-twin
   ```

2. **Frontend Setup**
   ```bash
   # Install dependencies
   npm install

   # Set up environment variables
   cp .env.example .env
   ```
   
   Add your API configuration to `.env`:
   ```env
   VITE_API_URL=http://localhost:3001/api
   VITE_OPENAI_API_KEY=your_openai_api_key_here
   ```

3. **Backend Setup**
   ```bash
   # Navigate to backend directory
   cd backend
   
   # Run setup script (Linux/Mac)
   chmod +x setup.sh
   ./setup.sh
   
   # Or manually install dependencies
   npm install
   
   # Configure environment variables
   cp env.example .env
   ```
   
   Edit `backend/.env` with your Supabase credentials:
   ```env
   SUPABASE_URL=your_supabase_project_url
   SUPABASE_ANON_KEY=your_supabase_anon_key
   SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
   JWT_SECRET=your_jwt_secret_key_here
   PORT=3001
   NODE_ENV=development
   CORS_ORIGIN=http://localhost:5173
   ```

4. **Database Setup**
   
   Create a `users` table in your Supabase database:
   ```sql
   CREATE TABLE users (
     id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
     email VARCHAR(255) UNIQUE NOT NULL,
     password_hash VARCHAR(255) NOT NULL,
     name VARCHAR(255) NOT NULL,
     state VARCHAR(100),
     district VARCHAR(50),
     party VARCHAR(100),
     phone VARCHAR(50),
     committee TEXT,
     avatar TEXT,
     term_start DATE,
     created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
     updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
   );
   
   CREATE INDEX idx_users_email ON users(email);
   ALTER TABLE users ENABLE ROW LEVEL SECURITY;
   ```

5. **Start the Servers**
   ```bash
   # Terminal 1: Start backend
   cd backend
   npm run dev
   
   # Terminal 2: Start frontend
   cd ..
   npm run dev
   ```

6. **Open your browser**
   Navigate to `http://localhost:5173`

## 🔑 Authentication

The application now uses secure JWT-based authentication with Supabase:

- **Registration**: Create new accounts with email, password, and profile information
- **Login**: Authenticate with email and password
- **Profile Management**: Update personal information and change passwords
- **Secure Routes**: Protected pages require authentication
- **Token Persistence**: Automatic login with stored tokens

## 🏗️ Architecture

### Frontend
- **React 18** with TypeScript
- **Vite** for fast development and building
- **Tailwind CSS** for styling
- **React Router** for navigation
- **Context API** for state management

### Backend
- **Node.js** with Express
- **Supabase** for database and authentication
- **JWT** for secure token-based authentication
- **bcrypt** for password hashing
- **CORS** and security middleware

### AI Integration
- **OpenAI GPT-3.5-turbo** for policy analysis
- **Fallback analysis** when API is unavailable
- **Rate limiting protection** with exponential backoff

### Key Components
- `AuthContext` - Authentication state management
- `authService` - Backend API integration
- `AppContext` - Application state management
- `aiService` - AI-powered analysis functions
- `censusApi` - Demographic data integration

## 📁 Project Structure

```
civic-twin/
├── src/                    # Frontend source code
│   ├── components/         # React components
│   ├── context/           # React context providers
│   ├── pages/             # Page components
│   ├── services/          # API services
│   └── types/             # TypeScript type definitions
├── backend/               # Backend API
│   ├── src/
│   │   ├── config/        # Configuration files
│   │   ├── middleware/    # Express middleware
│   │   ├── routes/        # API routes
│   │   └── index.js       # Main server file
│   ├── package.json       # Backend dependencies
│   └── README.md          # Backend documentation
├── package.json           # Frontend dependencies
└── README.md              # This file
```

## 🔧 Development

### Available Scripts

#### Frontend
- `npm run dev` - Start development server
- `npm run build` - Build for production
- `npm run preview` - Preview production build
- `npm run lint` - Run ESLint

#### Backend
- `cd backend && npm run dev` - Start backend with auto-restart
- `cd backend && npm start` - Start production backend

### API Endpoints

- `POST /api/auth/register` - Register new user
- `POST /api/auth/login` - Login user
- `GET /api/auth/profile` - Get user profile
- `PUT /api/auth/profile` - Update user profile
- `PUT /api/auth/change-password` - Change password
- `POST /api/auth/logout` - Logout user
- `GET /health` - Server status

For detailed API documentation, see [backend/README.md](backend/README.md)

### Adding New Features

1. **New Pages**: Add to `src/pages/` and update routing in `App.tsx`
2. **New Components**: Add to `src/components/` for reusable UI
3. **New Services**: Add to `src/services/` for external integrations
4. **New API Routes**: Add to `backend/src/routes/` for backend endpoints
5. **New Types**: Add to `src/types/index.ts` for TypeScript definitions

## 🔒 Security Features

- **Password Hashing**: All passwords are hashed using bcrypt with 12 salt rounds
- **JWT Tokens**: Secure token-based authentication with 7-day expiration
- **CORS Protection**: Configured to allow only specified origins
- **Rate Limiting**: 100 requests per 15 minutes per IP
- **Security Headers**: Helmet middleware for protection against common vulnerabilities
- **Input Validation**: Request body validation for all endpoints

## 🚀 Deployment

### Frontend Deployment

The frontend can be deployed to any static hosting service:
- Vercel
- Netlify
- GitHub Pages
- AWS S3 + CloudFront

### Backend Deployment

The backend can be deployed to:
- Heroku
- Railway
- DigitalOcean App Platform
- AWS EC2
- Google Cloud Run

Remember to:
1. Set `NODE_ENV=production`
2. Configure all environment variables
3. Set up proper CORS origins
4. Use a process manager like PM2 for production

## 🤝 Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgments

- **OpenAI** for AI capabilities
- **Supabase** for database and authentication
- **US Census Bureau** for demographic data
- **React Team** for the amazing framework
- **Tailwind CSS** for the utility-first CSS framework

## 📞 Support

For support, email support@civictwin.com or open an issue on GitHub.

---

**Built with ❤️ for better policy making**


## Detected evidence (automated analysis)

Indexed codebase: 57 recognized source files, 341 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- OpenAI (technology) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Supabase (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (68 of 68)

```
.bolt/config.json
.bolt/prompt
.gitignore
backend/clear-constituent-cache.sql
backend/data/zccd.csv
backend/env.example
backend/migrate-political-policies.sql
backend/package.json
backend/README.md
backend/setup.sh
backend/src/config/supabase.js
backend/src/index.js
backend/src/middleware/auth.js
backend/src/routes/ai.js
backend/src/routes/auth.js
backend/src/routes/cache.js
backend/src/routes/districts.js
backend/supabase-cache-setup.sql
backend/supabase-setup-simple.sql
backend/supabase-setup.sql
backend/test-census.js
backend/test-supabase.js
CENSUS_SETUP.md
eslint.config.js
index.html
package.json
postcss.config.js
README.md
src/App.tsx
src/components/ChatModal.tsx
src/components/ConstituentChat.tsx
src/components/ConstituentList.tsx
src/components/Layout.tsx
src/components/LoadingSpinner.tsx
src/context/AppContext.tsx
src/context/AuthContext.tsx
src/data/zccd.csv
src/hooks/useConstituents.ts
src/index.css
src/main.tsx
src/pages/Analysis.tsx
src/pages/Dashboard.tsx
src/pages/Landing.tsx
src/pages/Login.tsx
src/pages/Profile.tsx
src/pages/Register.tsx
src/pages/Upload.tsx
src/services/aiService.ts
src/services/authService.ts
src/services/censusApi.ts
src/services/constituentService.ts
src/services/districtMapper.ts
src/services/groqService.ts
src/test-cache-invalidation.js
src/test-constituents.js
src/test-district-mapper.js
src/test-political-policies.js
src/types/congressional-districts.d.ts
src/types/index.ts
src/vite-env.d.ts
tailwind.config.js
test-census-api.js
test-district-debug.js
test-district-mapper.js
tsconfig.app.json
tsconfig.json
tsconfig.node.json
vite.config.ts
```

### Dependencies

- backend/package.json: @anthropic-ai/sdk@^0.54.0, @supabase/supabase-js@^2.39.0, bcryptjs@^2.4.3, cors@^2.8.5, csv-parser@^3.2.0, dotenv@^16.3.1, express@^4.18.2, express-rate-limit@^7.1.5, helmet@^7.1.0, jsonwebtoken@^9.0.2, nodemon@^3.0.2
- package.json: @eslint/js@^9.9.1, @types/react@^18.3.5, @types/react-dom@^18.3.0, @vitejs/plugin-react@^4.3.1, autoprefixer@^10.4.18, chart.js@^4.5.0, congressional-districts@^1.0.4, eslint@^9.9.1, eslint-plugin-react-hooks@^5.1.0-rc.0, eslint-plugin-react-refresh@^0.4.11, globals@^15.9.0, isomorphic-unfetch@^4.0.2, lucide-react@^0.344.0, openai@^5.6.0, postcss@^8.4.35, react@^18.3.1, react-chartjs-2@^5.3.0, react-dom@^18.3.1, react-router-dom@^6.21.0, tailwindcss@^3.4.1, typescript@^5.5.3, typescript-eslint@^8.3.0, unfetch@^5.0.0, vite@^5.4.2

### Recent commits (newest first)

- 3 bullet point viewpoint
- cache invalidation + beginnings of 3 bp policy
- fix chat
- fix chat
- GOOD CHECKPOINT
- fix the document analysis
- N/A for fields that aren't populated
- switch to anthropic
- change name to replicant
- shivani
- remove profile pictures
- remove constituents from dashboard
- make the sidebar anchored on scroll
- NaN
- Integrate Groq API for constituent chat with personality injection in ChatModal and ConstituentChat
- constituents
- better constituent representation and census data
- Fix chat functionality: update useEffect dependencies and ensure proper policy context
- Remove policy impact from constituent cards and ensure chat functionality works properly
- Enhanced policy impact analysis: generate unique policy impacts for each digital twin based on their characteristics and policy content

## Key source files (fetched from GitHub, selected and truncated for size)

### CENSUS_SETUP.md

```markdown
# Census API Setup Guide

## ✅ Successfully Using Free Census Bureau ACS API

Great news! We're now using the **free U.S. Census Bureau ACS (American Community Survey) API** which requires **no credentials or signup**.

### What We're Using
- **API Endpoint**: `https://api.census.gov/data/2021/acs/acs5`
- **Data Source**: 2021 American Community Survey 5-Year Estimates
- **Authentication**: None required - completely free and public
- **Rate Limits**: Generous limits for public use

### Data Available
- Total population by ZIP code
- Racial demographics (White, Black, Asian, Native American, Pacific Islander)
- Hispanic/Latino population
- Median household income
- Education levels (Bachelor's, Master's, Professional, Doctorate degrees)
- Geographic boundaries
- No personal information (aggregated data only)

### How It Works
The API returns data in this format:
```json
[
  ["B01003_001E", "B03002_003E", "B03002_004E", "B03002_005E", "B03002_006E", "B03002_007E", "B03002_012E", "B19013_001E", "zip code tabulation area"],
  ["26966", "14480", "2013", "18", "4527", "50", "4973", "101409", "10001"]
]
```

Where:
- `B01003_001E` = Total population
- `B03002_003E` = White alone
- `B03002_004E` = Black or African American alone
- `B03002_005E` = American Indian and Alaska Native alone
- `B03002_006E` = Asian alone
- `B03002_007E` = Native Hawaiian and Other Pacific Islander alone
- `B03002_012E` = Hispanic or Latino
- `B19013_001E` = Median household income

### Testing Results ✅
Our test with ZIP code 10001 returned:
- **Total population**: 26,966
- **White population**: 14,480
- **Black population**: 2,013
- **Hispanic population**: 4,973
- **Median income**: $101,409

### Testing
Run the test script to verify it's working:
```bash
node test-census-api.js
```

### No Setup Required!
Since this is the official U.S. Census Bureau API, there's no need for:
- API keys
- Email signups
- Account creation
- Rate limit concerns

Just start using it immediately! 🎉

### Advantages of ACS API
- **More recent data** (2021 vs 2020)
- **More comprehensive** (includes income, education)
- **Better ZIP code coverage**
- **No authentication required**
- **Reliable and stable** 
```

### package.json

```
{
  "name": "civictwin",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "chart.js": "^4.5.0",
    "congressional-districts": "^1.0.4",
    "isomorphic-unfetch": "^4.0.2",
    "lucide-react": "^0.344.0",
    "openai": "^5.6.0",
    "react": "^18.3.1",
    "react-chartjs-2": "^5.3.0",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.21.0",
    "unfetch": "^5.0.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.9.1",
    "@types/react": "^18.3.5",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.1",
    "autoprefixer": "^10.4.18",
    "eslint": "^9.9.1",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.11",
    "globals": "^15.9.0",
    "postcss": "^8.4.35",
    "tailwindcss": "^3.4.1",
    "typescript": "^5.5.3",
    "typescript-eslint": "^8.3.0",
    "vite": "^5.4.2"
  }
}

```

### backend/package.json

```
{
  "name": "civic-twin-backend",
  "version": "1.0.0",
  "description": "Backend API for Replicant with Supabase authentication",
  "main": "src/index.js",
  "type": "module",
  "scripts": {
    "start": "node src/index.js",
    "dev": "nodemon src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "@anthropic-ai/sdk": "^0.54.0",
    "@supabase/supabase-js": "^2.39.0",
    "bcryptjs": "^2.4.3",
    "cors": "^2.8.5",
    "csv-parser": "^3.2.0",
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "express-rate-limit": "^7.1.5",
    "helmet": "^7.1.0",
    "jsonwebtoken": "^9.0.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  },
  "keywords": [
    "supabase",
    "authentication",
    "express",
    "api"
  ],
  "author": "",
  "license": "MIT"
}

```

### src/main.tsx

```typescript
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import './index.css';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>
);

```

### src/App.tsx

```typescript
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { AppProvider } from './context/AppContext';
import { AuthProvider, useAuth } from './context/AuthContext';
import Landing from './pages/Landing';
import Login from './pages/Login';
import Register from './pages/Register';
import Dashboard from './pages/Dashboard';

// Protected Route Component
const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const { isAuthenticated } = useAuth();
  
  if (!isAuthenticated()) {
    return <Navigate to="/login" replace />;
  }
  
  return <>{children}</>;
};

function AppRoutes() {
  return (
    <Routes>
      <Route path="/" element={<Landing />} />
      <Route path="/login" element={<Login />} />
      <Route path="/register" element={<Register />} />
      <Route path="/dashboard/*" element={
        <ProtectedRoute>
          <Dashboard />
        </ProtectedRoute>
      } />
      <Route path="/upload" element={<Navigate to="/dashboard/upload" replace />} />
      <Route path="/analysis" element={<Navigate to="/dashboard/analysis" replace />} />
    </Routes>
  );
}

function App() {
  return (
    <AuthProvider>
      <AppProvider>
        <Router>
          <AppRoutes />
        </Router>
      </AppProvider>
    </AuthProvider>
  );
}

export default App;
```

### src/types/index.ts

```typescript
export interface Policy {
  id: string;
  title: string;
  content: string;
  summary: string;
  uploadedAt: Date;
}

export interface Congressman {
  id: string;
  name: string;
  email: string;
  district: string;
  state: string;
  party: string;
  avatar: string;
  phone?: string;
  termStart?: string;
  committee?: string;
}

export interface CensusData {
  zipCode: string;
  population: number;
  medianIncome: number;
  medianAge: number;
  educationLevels: {
    lessThanHighSchool: number;
    highSchool: number;
    someCollege: number;
    bachelors: number;
    graduate: number;
  };
  demographics: {
    white: number;
    black: number;
    hispanic: number;
    asian: number;
    other: number;
  };
  ageGroups?: {
    '18-24': number;
    '25-34': number;
    '35-44': number;
    '45-54': number;
    '55-64': number;
    '65-74': number;
    '75+': number;
  };
  occupations: {
    management: number;
    service: number;
    salesOffice: number;
    construction: number;
    production: number;
  };
  homeownershipRate?: number;
  povertyRate?: number;
  collegeRate?: number;
  incomeDistribution?: {
    'Under $25,000': number;
    '$25,000-$50,000': number;
    '$50,000-$100,000': number;
    '$100,000-$200,000': number;
    'Over $200,000': number;
  };
}

export interface DigitalTwin {
  id: string;
  name: string;
  age: number;
  education: string;
  annualIncome: number;
  occupation: string;
  demographics: string;
  zipCode: string;
  personalStory: string;
  policyImpact: string;
  politicalPolicies: string[];
}

export interface ChatMessage {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  timestamp: Date;
}

export interface PolicySuggestion {
  id: string;
  title: string;
  description: string;
  impactedPopulation: string;
  severity: 'low' | 'medium' | 'high';
}
```

### backend/src/index.js

```javascript
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import dotenv from 'dotenv';
import authRoutes from './routes/auth.js';
import districtsRoutes from './routes/districts.js';
import cacheRoutes from './routes/cache.js';
import aiRoutes from './routes/ai.js';

// Load environment variables from .env.local first, then .env
dotenv.config({ path: '.env.local' });
dotenv.config();

const app = express();
const PORT = process.env.PORT || 3001;

// Security middleware
app.use(helmet());

// CORS configuration
app.use(cors({
  origin: process.env.CORS_ORIGIN || 'http://localhost:5173',
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

// Rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP, please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
});

app.use(limiter);

// Body parsing middleware
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({ 
    status: 'OK', 
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV || 'development'
  });
});

// API routes
app.use('/api/auth', authRoutes);
app.use('/api/districts', districtsRoutes);
app.use('/api/cache', cacheRoutes);
app.use('/api/ai', aiRoutes);

// 404 handler
app.use('*', (req, res) => {
  res.status(404).json({ error: 'Route not found' });
});

// Global error handler
app.use((error, req, res, next) => {
  console.error('Global error handler:', error);
  
  if (error.type === 'entity.parse.failed') {
    return res.status(400).json({ error: 'Invalid JSON payload' });
  }
  
  res.status(500).json({ 
    error: 'Internal server error',
    message: process.env.NODE_ENV === 'development' ? error.message : 'Something went wrong'
  });
});

// Start server
app.listen(PORT, () => {
  console.log(`🚀 Server running on port ${PORT}`);
  console.log(`📊 Health check: http://localhost:${PORT}/health`);
  console.log(`🔐 Auth endpoints: http://localhost:${PORT}/api/auth`);
  console.log(`🌍 Environment: ${process.env.NODE_ENV || 'development'}`);
});

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  process.exit(0);
});

process.on('SIGINT', () => {
  console.log('SIGINT received, shutting down gracefully');
  process.exit(0);
});

export default app; 
```

### postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

```

### tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};

```

### vite.config.ts

```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
        secure: false,
      },
    },
  },
});

```

[46 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]