A full-stack web application for viewing and exploring water treatment facilities data from Google Cloud Firestore.
- Data Grid with Virtual Scrolling: Efficiently display 15,611+ facilities with infinite scroll
- Search & Filtering: Full-text search and filters by facility type, enrichment status, and state
- Map View: Interactive Google Maps integration with facility markers
- Detail View: Comprehensive facility information modal
- Real-time Statistics: Dashboard showing total facilities, enriched count, and type breakdown
app/
├── backend/ # FastAPI backend
│ ├── main.py # API endpoints
│ └── requirements.txt
├── frontend/ # Next.js frontend
│ ├── app/ # Next.js app directory
│ ├── components/ # React components
│ ├── lib/ # Utilities and API client
│ └── types/ # TypeScript types
└── WEB_APP_PROMPT.md
- Python 3.11+
- Node.js 18+
- Google Cloud SDK (for Firestore authentication)
- Google Cloud Project:
aquamap-488903
The easiest way to run both backend and frontend together:
npm run devThis will start both servers in the same terminal. See README-SCRIPTS.md for other options.
- Navigate to the backend directory:
cd backend- Create a virtual environment:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate- Install dependencies:
pip install -r requirements.txt- Set up Google Cloud authentication:
gcloud auth application-default login
gcloud auth application-default set-quota-project aquamap-488903- Create a
.envfile (optional, defaults are set):
GOOGLE_CLOUD_PROJECT_ID=aquamap-488903
FIRESTORE_COLLECTION=facility
API_HOST=localhost
API_PORT=8000
CORS_ORIGINS=http://localhost:3000- Run the backend server:
python main.py
# Or: uvicorn main:app --reload --host localhost --port 8000The API will be available at http://localhost:8000
- Navigate to the frontend directory:
cd frontend- Install dependencies:
npm install- Create a
.env.localfile:
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_google_maps_api_key_here- Run the development server:
npm run devThe application will be available at http://localhost:3000
See README-SCRIPTS.md for detailed information about running both servers together.
List facilities with pagination, filtering, and search.
Query Parameters:
limit(required): Number of records per page (default: 50, max: 100)cursor(optional): Cursor for cursor-based paginationpage(optional): Page number for offset-based paginationsearch(optional): Full-text search queryfacility_type(optional): Filter by facility typestate(optional): Filter by state abbreviation (e.g., "CA", "NY")is_enriched(optional): Filter by enrichment status (0 or 1)
Response:
{
"data": [...],
"pagination": {
"has_next_page": true,
"next_cursor": "last_osm_id",
"current_page": 1,
"per_page": 50
}
}Get a single facility by OSM ID.
Get statistics about facilities.
Response:
{
"total_count": 15611,
"enriched_count": 5000,
"not_enriched_count": 10611,
"drinking_water_count": 8000,
"wastewater_count": 7611
}- FastAPI: Modern Python web framework
- google-cloud-firestore: Firestore client library
- Pydantic: Data validation
- Uvicorn: ASGI server
- Next.js 14: React framework with App Router
- TypeScript: Type safety
- TanStack Query: Data fetching and caching
- TanStack Table: Data grid functionality
- TanStack Virtual: Virtual scrolling for performance
- Tailwind CSS: Styling
- Google Maps JavaScript API: Map integration
Collection: facility
Document Fields (22 total):
- Primary:
osm_id,osm_type,facility_type - Basic Info:
name,operator,address,phone,website,capacity,description - Location:
latitude,longitude,coordinates_from_polygon,polygon_wkt,osm_url - Google Maps:
place_id,google_maps_url,types,business_status,distance_from_osm,matched_keywords,is_enriched
- The backend uses cursor-based pagination for efficient infinite scroll
- Frontend implements virtual scrolling to render only visible rows
- Search is implemented client-side (consider Algolia for advanced search)
- State extraction from addresses is done client-side
- Google Maps API key is optional but required for map view
Deploy to Google Cloud Run, Heroku, or similar platform. Ensure:
- Service account with Firestore access
- Environment variables configured
- CORS origins updated
Deploy to Vercel, Netlify, or similar platform. Ensure:
NEXT_PUBLIC_API_URLpoints to deployed backendNEXT_PUBLIC_GOOGLE_MAPS_API_KEYis configured
MIT