# Project export: Pyro*AI

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: TreeHacks 2025
- Tagline: Stay Ahead of the Flames
- Devpost: https://devpost.com/software/pyro-ai
- GitHub: https://github.com/EthanSantos/pyroai
- Demo: https://pyroai.vercel.app/
- Video: https://www.youtube.com/embed/fTVpI_663GE?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — EthanSantos (60 commits), conniely (18 commits), kellyy8 (14 commits), katjpg (8 commits)

## Devpost submission (written by the team)

### Inspiration

Not so long ago in January 2025, the Palisades and Eaton fires took over Los Angeles and global headlines, consuming over 37,000 acres, destroying more than 16,000 structures, and tragically claiming at least 29 lives. As this event unraveled, we recognized the need for smarter, more sustainable wildfire management systems that prioritize safety and empower communities to act swiftly. That's why we built Pyro.AI—a centralized wildfire monitoring dashboard designed to protect lives, safeguard ecosystems, and foster resilience against climate-related disasters. Our dashboard extends beyond existing platforms like Watch Duty by offering tools tailored to real-time wildfire detection, risk assessment, and evacuation planning.

### What it does

Automated Evacuation Planning Identifies the safest and most efficient routes from danger zones to ensure timely evacuations. Identifies the safest and most efficient routes from danger zones to ensure timely evacuations. Fire Detection Using Camera Feeds Utilizes real-time camera feeds integrated with a Yolov8 model trained on the D-fire dataset to detect wildfires with high accuracy. This feature allows users to toggle detection on or off as needed, providing flexibility and control. Utilizes real-time camera feeds integrated with a Yolov8 model trained on the D-fire dataset to detect wildfires with high accuracy. This feature allows users to toggle detection on or off as needed, providing flexibility and control. Intelligent Chat System for Safety Insights A personal wildfire guide powered by Google Gemini, offering real-time safety insights. By ingesting live environmental data—such as air quality, temperature, wind speed, and humidity—it provides actionable recommendations tailored to users' locations, helping them make informed decisions during emergencies. A personal wildfire guide powered by Google Gemini, offering real-time safety insights. By ingesting live environmental data—such as air quality, temperature, wind speed, and humidity—it provides actionable recommendations tailored to users' locations, helping them make informed decisions during emergencies.

### How we built it

Our development process began with a critical question: How might we provide real-time wildfire detection, risk assessment, and automated evacuation planning to ensure users are informed, educated, and empowered to act swiftly during wildfire emergencies? Which helped us devise 3 core hypotheses: Hypothesis 1: Real-time Wildfire Detection and Risk Assessment How might we develop an integrated system that combines real-time wildfire detection with accurate risk assessment to provide timely and actionable information to emergency responders and the public? Hypothesis 2: Automated Evacuation Planning and Route Optimization How might we create an automated evacuation planning system that optimizes routes and provides personalized guidance to ensure swift and safe evacuations during wildfire emergencies? Hypothesis 3: Real-time Information Platform for Wildfire Preparedness and Response How might we design a platform that delivers real-time news, updates, and educational content to effectively inform and prepare users for wildfire emergencies, leading to improved response and outcomes during actual events? Prototyping Process To explore these hypotheses, we wanted to quickly build a functional prototype. We acknowledged that one of the major pain points of product development is the gap between ideation and implementation. Because of this, we decided to utilize Lovable.dev due to its 3 core advantages: Rapid Transformation from Idea-to-Prototype Instantly translate brainstorming sessions and concepts into an interactive and functional prototype with just a few prompts. Deployment in just a single click to validate and test our ideas with ease. Instantly translate brainstorming sessions and concepts into an interactive and functional prototype with just a few prompts. Deployment in just a single click to validate and test our ideas with ease. Full Stack Development Without Technical Barriers Live rendering for immediate visual feedback. Select-to-Edit functionality for precise component modifications. AI-assisted debugging and code refinement. Live rendering for immediate visual feedback. Select-to-Edit functionality for precise component modifications. AI-assisted debugging and code refinement. Iterative Development with AI Assistance Make quick adjustments in natural language based on user feedback. Make quick adjustments in natural language based on user feedback. Competitive Analysis Next, to thoroughly explore our problem space, we conducted a Competitive Analysis of Watch Duty to identify opportunities and limitations in addressing real-time wildfire detection, risk assessment, and evacuation planning. Watch Duty is a free, nonprofit wildfire alert app that provides real-time updates through vetted data from firefighters, dispatchers, and first responders. Strengths Provides accurate, real-time wildfire detection through human-vetted updates, ensuring reliability during emergencies. Offers detailed evacuation zones and shelter information to support informed decision-making during crises. Integrates satellite imagery (VIIRS/MODIS) for fire tracking and risk assessment. Limitations Lack of centralized predictive tools for fire spread modeling and automated risk assessment. Limited user notification scope (up to four counties), reducing coverage for those monitoring multiple regions. Absence of automated evacuation route optimization, relying on manual updates instead. Opportunities Develop predictive fire spread models to enhance real-time risk assessment capabilities. Introduce automated evacuation planning with route optimization to improve user safety and response time. Expand notification capabilities to allow broader regional monitoring for users in high-risk areas. Research Process What was another important aspect was conducting a mixed-method research approach combining primary and secondary research methods to gain a holistic understanding of user needs, behaviors, and challenges related to wildfire detection, risk assessment, and evacuation planning. Primary Research We conducted 1:1 qualitative interviews with five Los Angeles residents who directly experienced or were in close proximity to the January 2025 Palisades and Eaton wildfires. These interviews aimed to uncover firsthand experiences, emotional responses, and unmet needs during wildfire emergencies. Key insights: Information Overload: Participants described feeling overwhelmed by fragmented information from multiple sources (news outlets, social media, government alerts). Delayed Notifications: Many reported receiving evacuation orders too late or relying on word-of-mouth updates from neighbors. Evacuation Challenges: Interviewees highlighted confusion about safe evacuation routes due to unclear or outdated maps, leading to heightened anxiety during emergencies. Secondary Research We conducted an extensive literature review focusing on wildfire management systems, emergency response technologies, and user behavior during natural disasters. This included academic papers, government reports, and case studies on recent wildfire events. Key findings: Real-Time Data Gaps: Current systems often lack integration of real-time fire spread models with actionable risk assessments for users. Evacuation Route Optimization: Studies emphasized the importance of dynamic route optimization tools that adapt to changing fire conditions to reduce evacuation delays. User-Centric Design: Research highlighted the need for accessible interfaces that prioritize clarity and usability under high-stress conditions. How We Built It After collectively ideating and thoroughly exploring our problem space, to finally test our hypotheses we integrated advanced technologies and APIs to deliver a comprehensive wildfire management system. Automated Evacuation Planning We utilized OpenRouteService (ORS), a highly customizable routing API, to calculate the safest and most efficient evacuation routes. ORS's features, such as avoiding hazard zones using the "avoid_polygon" parameter, were critical for dynamically rerouting users away from wildfire-affected areas. The system integrates real-time environmental data from APIs like openmeteo to account for changing weather conditions and fire spread patterns, ensuring routes are always updated. Fire Detection Fire detection is powered by a YOLOv8 model, a state-of-the-art object detection algorithm trained on the D-fire dataset. This allows for high-accuracy detection of fires and smoke in real-time camera feeds. We integrated live camera feeds like AlertCalifornia Videos, enabling users to toggle fire detection on or off for enhanced situational awareness. Readily Accessible Information via Chat System The chat system is built using Google Gemini, which processes real-time environmental data such as air quality, temperature, wind speed, and humidity. By combining this data with safety insights, the chat system provides users with actionable recommendations tailored to their specific location and circumstances. Wildfire Monitoring Dashboard The dashboard consolidates critical information into an intuitive interface: Air Quality Index (AQI): Data is sourced from openmeteo and processed to display localized AQI levels. Safety Score & Wildfire Risk Level: These metrics are calculated using a mathematical formula that combines environmental factors (e.g., temperature, wind speed) with fire spread predictions from our CNN model. Mapbox v9 Satellite Integration: Real-time satellite imagery is displayed using Mapbox's API, offering users a clear view of wildfire locations and affected areas. Machine Learning Models A Wildfire Convolutional Neural Network (CNN) was trained on satellite imagery data to predict wildfire risk levels and fire spread patterns. The model architecture includes convolutional layers optimized for spatial data analysis, enabling accurate predictions based on environmental conditions. Tabs and Features Alerts Tab: Displays categorized updates (e.g., "All," "Alerts," "General," "Shelters") sourced from reliable APIs like openmeteo and Google Gemini. Routes Tab: Integrates automated evacuation routing powered by OpenRouteService to guide users safely out of danger zones. Chat Tab: Provides real-time safety insights and answers user queries through Google Gemini's AI capabilities. News & Updates Integration The dashboard aggregates wildfire-related news and updates into categories like "All," "Alerts," "General," and "Shelters," ensuring users stay informed during emergencies. APIs Used Mapbox: For satellite imagery and map-based visualizations of wildfire locations. Google Gemini: Powers the intelligent chat system for safety insights. openmeteo: Supplies real-time environmental data such as air quality, weather conditions, and wind speed for risk assessment and evacuation planning.

### Challenges we ran into

Our development process faced several technical hurdles: Backend-frontend integration complexities when connecting our Flask server with the React frontend, particularly for real-time data updates Implementation challenges in calculating accurate wildfire risk scores that incorporate multiple environmental factors Deployment difficulties with our backend system due to TensorFlow package dependencies and compatibility issues

### Accomplishments we're proud of

We successfully developed essential features that make a meaningful social impact: Created a comprehensive wildfire monitoring system that helps protect communities and ecosystems Implemented real-time fire detection and risk assessment capabilities Developed automated evacuation planning tools that can help save lives during emergencies

### What we learned

Our development journey gave valuable insights into firsthand experience in the importance of usability testing and continuous user feedback for improving our platform We also discovered the effectiveness of rapid prototyping tools like Lovable.dev in accelerating development and validation of ideas

### What's next

for Pyro.AI Looking ahead, we plan to refine our core feature--automated evacuation planning by: Implementing multi-point evacuation routing to handle large-scale evacuations more efficiently Enhancing the OpenRouteService integration to account for real-time traffic conditions Developing backup route suggestions for scenarios where primary routes become compromised As well as evacuation zone management: Expand the safety scoring system to provide more granular risk assessments for different areas Improve danger zone calculations using more sophisticated geometric algorithms Enhance the visualization of evacuation zones in the MapboxMap component

## README (from the GitHub repository)

# Pyro.AI
<div align="center">
  <img width="947" alt="pyroai" src="https://github.com/user-attachments/assets/9fed5ec9-b0fe-474b-aa34-d12faa8a03ed" />
</div>

## Tech Stack
<div align="center">
  <img alt="NextJS" src="https://img.shields.io/badge/NextJS-000000?style=for-the-badge&logo=next.js&logoColor=white" />
  <img alt="Flask" src="https://img.shields.io/badge/Flask-000000?style=for-the-badge&logo=Flask&logoColor=white" />
  <img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white" />
  <img alt="Python" src="https://img.shields.io/badge/Python-3776AB?style=for-the-badge&logo=Python&logoColor=white" />
  <img alt="YOLOv8" src="https://img.shields.io/badge/YOLOv8-FF0000?style=for-the-badge" />
  <img alt="Tensorflow" src="https://img.shields.io/badge/Tensorflow-FF6F00?style=for-the-badge&logo=TensorFlow&logoColor=white" />
  <img alt="TailwindCSS" src="https://img.shields.io/badge/TailwindCSS-06B6D4?style=for-the-badge&logo=tailwind-css&logoColor=white" />
  <img alt="ShadCN" src="https://img.shields.io/badge/ShadCN-000000?style=for-the-badge" />
  <img alt="OpenRouteService" src="https://img.shields.io/badge/OpenRouteService-FF6600?style=for-the-badge&logo=OpenStreetMap&logoColor=white" />
  <img alt="GeminiAI" src="https://img.shields.io/badge/GeminiAI-4285F4?style=for-the-badge&logo=google&logoColor=white" />
  <img alt="Vercel" src="https://img.shields.io/badge/Vercel-000?style=for-the-badge&logo=vercel&logoColor=white" />
</div>

## Video Demo
[Watch the demo on YouTube](https://www.youtube.com/watch?v=fTVpI_663GE)

## Inspiration
Not so long ago in January 2025, the Palisades and Eaton fires took over Los Angeles and global headlines, consuming over 37,000 acres, destroying more than 16,000 structures, and tragically claiming at least 29 lives. As this event unraveled, we recognized the need for smarter, more sustainable wildfire management systems that prioritize safety and empower communities to act swiftly.

That's why we built Pyro.AI—a centralized wildfire monitoring dashboard designed to protect lives, safeguard ecosystems, and foster resilience against climate-related disasters. Our dashboard extends beyond existing platforms like Watch Duty by offering tools tailored to real-time wildfire detection, risk assessment, and evacuation planning.
## What It Does
**Automated Evacuation Planning**  
- Computes the safest and most efficient evacuation routes using real-time data and OpenRouteService, ensuring timely evacuations.

**Real-time Fire Detection**  
- Processes live camera feeds with a YOLOv8 model (trained on the D-fire dataset) to quickly detect wildfires with high accuracy. Users can toggle detection on or off as needed.

**Intelligent Safety Chat**  
- Acts as a personal wildfire guide powered by Google Gemini, delivering real-time safety insights by analyzing live environmental data (air quality, temperature, wind speed, and humidity).

## How We Built It
We began by asking: *How might we provide real-time wildfire detection, risk assessment, and automated evacuation planning to ensure users are informed, educated, and empowered to act swiftly during wildfire emergencies?*

Our approach combined:
- **Rapid Prototyping:** Leveraging tools like Lovable.dev for quick iteration and live rendering.
- **Core Hypotheses:** Focusing on real-time detection, optimized evacuation routing, and actionable safety insights.
- **Competitive Analysis:** Studying existing platforms like Watch Duty to identify opportunities for innovation and improvement.

## Information Architecture
<div align="center">
  <img width="1380" alt="pyroaiarchitecture" src="https://github.com/user-attachments/assets/898b9870-8ce7-4bae-a067-0e10746ddae7" />
</div>

## Challenges We Ran Into
- **Accurate Risk Assessment:** Developing a wildfire risk scoring system that dynamically integrates diverse environmental data.
- **Deployment Issues:** Overcoming compatibility issues, particularly with TensorFlow dependencies, to ensure smooth deployment.

## Accomplishments That We're Proud Of
- Created a comprehensive wildfire monitoring system that helps protect communities and ecosystems within 30 hours at TreeHacks.
- Implemented real-time fire detection and risk assessment capabilities.
- Developed automated evacuation planning tools that can help save lives during emergencies.

## What We Learned
- Our development journey gave valuable insights into firsthand experience in the importance of usability testing and continuous user feedback for improving our platform
- We also discovered the effectiveness of rapid prototyping tools like Lovable.dev in accelerating development and validation of ideas

## What's Next for Pyro.AI
- Implementing multi-point evacuation routing to handle large-scale evacuations more efficiently
- Enhancing the OpenRouteService integration to account for real-time traffic conditions
- Developing backup route suggestions for scenarios where primary routes become compromised


## Detected evidence (automated analysis)

Indexed codebase: 39 recognized source files, 140 KB.
- CSS (language) — detected in the code
- Flask (technology) — detected in the code
- Google Gemini (technology) — detected in the code
- Next.js (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- PyTorch (technology) — claimed on Devpost, not found in the code
- TensorFlow (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (50 of 50)

```
backend/.gitignore
backend/.vercelignore
backend/models/wildfire_cnn.onnx
backend/models/wildfire_yolo_v8.pt
backend/requirements.txt
backend/server.py
backend/utils/image_processor.py
backend/utils/video.py
backend/vercel.json
frontend/.gitignore
frontend/components.json
frontend/next.config.ts
frontend/package.json
frontend/postcss.config.mjs
frontend/README.md
frontend/src/app/about/page.tsx
frontend/src/app/api/news/route.ts
frontend/src/app/api/shelters/route.ts
frontend/src/app/dashboard/page.tsx
frontend/src/app/features/page.tsx
frontend/src/app/globals.css
frontend/src/app/layout.tsx
frontend/src/app/news/EvacShelterCard.tsx
frontend/src/app/news/NewsSection.tsx
frontend/src/app/news/page.tsx
frontend/src/app/page.tsx
frontend/src/components/AlertsTab.tsx
frontend/src/components/AnimatedNumber.tsx
frontend/src/components/ChatTab.tsx
frontend/src/components/MapboxMap.tsx
frontend/src/components/NavigationBar.tsx
frontend/src/components/RoutesTab.tsx
frontend/src/components/SidePanel.tsx
frontend/src/components/ui/alert.tsx
frontend/src/components/ui/badge.tsx
frontend/src/components/ui/button.tsx
frontend/src/components/ui/card.tsx
frontend/src/components/ui/input.tsx
frontend/src/components/ui/label.tsx
frontend/src/components/ui/scroll-area.tsx
frontend/src/components/ui/separator.tsx
frontend/src/components/ui/tabs.tsx
frontend/src/components/UnifiedTabContent.tsx
frontend/src/components/VideoFeed.tsx
frontend/src/context/WildfireContext.tsx
frontend/src/lib/utils.ts
frontend/src/utils/getLocationDetails.tsx
frontend/tailwind.config.ts
frontend/tsconfig.json
README.md
```

### Dependencies

- backend/requirements.txt: Flask, flask-cors, numpy, onnxruntime, opencv-python, Pillow, python-dotenv, requests, ultralytics
- frontend/package.json: @google/generative-ai@^0.21.0, @mapbox/polyline@^1.2.1, @radix-ui/react-label@^2.1.2, @radix-ui/react-scroll-area@^1.2.3, @radix-ui/react-separator@^1.1.2, @radix-ui/react-slot@^1.1.2, @radix-ui/react-tabs@^1.1.3, @shadcn/ui@^0.0.4, @turf/turf@^7.2.0, @types/mapbox__polyline@^1.0.5, @types/node@^20, @types/react@^19, @types/react-dom@^19, axios@^1.7.9, class-variance-authority@^0.7.1, clsx@^2.1.1, lucide-react@^0.475.0, mapbox-gl@^3.10.0, next@15.1.7, postcss@^8, react@^19.0.0, react-dom@^19.0.0, react-icons@^5.4.0, react-markdown@^9.0.3, shadcn-ui@^0.9.4, tailwind-merge@^3.0.1, tailwindcss@^3.4.1, tailwindcss-animate@^1.0.7, typescript@^5

### Recent commits (newest first)

- Merge pull request #8 from EthanSantos/EthanSantos-patch-1
- Create README.md
- vercel ignore for deployments
- removed unnecessary files
- code cleanup
- alerts tab
- start user out of the fire
- date added
- Merge remote-tracking branch 'origin/fix/wildfire-risk-score'
- fixed risk percentage
- fixing coordinate issues
- added shelters fixed route.ts
- adding more refined calculations for wildfire risk score
- air quality index
- Merge pull request #6 from EthanSantos/merge-evac
- Merge remote-tracking branch 'origin/evacshelter' into merge-evac
- Merge remote-tracking branch 'origin/main'
- fixed chatbot
- fixed news appearance and search bar
- fixed ui

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

### backend/requirements.txt

```
Flask
flask-cors
Pillow
requests
python-dotenv
onnxruntime
numpy

opencv-python
ultralytics
```

### frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@google/generative-ai": "^0.21.0",
    "@mapbox/polyline": "^1.2.1",
    "@radix-ui/react-label": "^2.1.2",
    "@radix-ui/react-scroll-area": "^1.2.3",
    "@radix-ui/react-separator": "^1.1.2",
    "@radix-ui/react-slot": "^1.1.2",
    "@radix-ui/react-tabs": "^1.1.3",
    "@shadcn/ui": "^0.0.4",
    "@turf/turf": "^7.2.0",
    "axios": "^1.7.9",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "lucide-react": "^0.475.0",
    "mapbox-gl": "^3.10.0",
    "next": "15.1.7",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-icons": "^5.4.0",
    "react-markdown": "^9.0.3",
    "tailwind-merge": "^3.0.1",
    "tailwindcss-animate": "^1.0.7"
  },
  "devDependencies": {
    "@types/mapbox__polyline": "^1.0.5",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "postcss": "^8",
    "shadcn-ui": "^0.9.4",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

```

### backend/server.py

```python
import os
from flask import Flask, jsonify, request, Response
from flask_cors import CORS
from PIL import Image
import requests
from io import BytesIO
import numpy as np
import onnxruntime as ort
import cv2
from datetime import datetime

from utils.image_processor import preprocess_image
from utils.video import load_yolo_model, process_frame

app = Flask(__name__)
CORS(app)

# ----------------------------
# Global Toggle for Detection
# ----------------------------
detection_enabled = False  # This global variable controls YOLO detection

# ----------------------------
# ONNX MODEL (Wildfire CNN) Setup
# ----------------------------
MODEL_DIR = "models"
ONNX_MODEL_PATH = os.path.join(MODEL_DIR, "wildfire_cnn.onnx")
os.makedirs(MODEL_DIR, exist_ok=True)

app.logger.info("Loading the ONNX model...")
session = ort.InferenceSession(ONNX_MODEL_PATH)
# Get the input name (assumes one input tensor)
input_name = session.get_inputs()[0].name

def onnx_predict(session, processed_image):
    """
    Prepare the image and run inference using ONNX Runtime.
    """
    # Expand dims to add a batch dimension and cast to float32
    input_data = np.expand_dims(processed_image, axis=0).astype(np.float32)
    outputs = session.run(None, {input_name: input_data})
    return outputs[0]

# ----------------------------
# YOLOv8 MODEL Setup for Video Processing
# ----------------------------
app.logger.info("Loading the YOLOv8 model...")
yolo_model = load_yolo_model(os.path.join(MODEL_DIR, "wildfire_yolo_v8.pt"))

# ----------------------------
# Routes and Utility Functions
# ----------------------------

@app.route('/', methods=['GET'])
def index():
    return "Flask server up and running :)"

def download_and_process_image(image_url):
    """
    Download the image from the provided URL and preprocess it.
    """
    response = requests.get(image_url)
    if response.status_code != 200:
        raise Exception("Failed to fetch image")
    
    image = Image.open(BytesIO(response.content))
    processed_image = preprocess_image(image)
    return processed_image


def fetch_weather_data(latitude, longitude):
    """
    Fetch current weather data from OpenMeteo API
    """
    try:
        base_url = "https://api.open-meteo.com/v1/forecast"
        
        params = {
            'latitude': latitude,
            'longitude': longitude,
            'current': [
                'temperature_2m',
                'relative_humidity_2m',
                'wind_speed_10m',
            ],
            'temperature_unit': 'fahrenheit',
            'wind_speed_unit': 'mph'
        }
        
        response = requests.get(base_url, params=params)
        response.raise_for_status()
        
        data = response.json()
        current = data['current']
        
        return {
            'temperature': current['temperature_2m'],
            'humidity': current['relative_humidity_2m'],
            'wind_speed': current['wind_speed_10m']
        }
    except Exception as e:
        app.logger.error(f"Error fetching weather data: {str(e)}")
        return None

@app.route('/api/predict', methods=['POST'])
def predict_wildfire_risk():
    try:
        data = request.json
        if not data or 'imageUrl' not in data:
            return jsonify({"error": "No image URL provided"}), 400

        # get coordinates and swap order for OpenMeteo
        coordinates = data.get('coordinates', None)
        if not coordinates or len(coordinates) != 2:
            return jsonify({"error": "Valid coordinates required"}), 400
            
        # swap longitude, latitude -> latitude, longitude (for OpenMeteo)
        longitude, latitude = coordinates  # og format from Mapbox
        weather_coordinates = [latitude, longitude]  # format for OpenMeteo
        
        # validate latitude/longitude ranges
        if not (-90 <= latitude <= 90) or not (-180 <= longitude <= 180):
            return jsonify({"error": "Invalid coordinates: latitude must be between -90 and 90, longitude between -180 and 180"}), 400
        
        # fetch weather data with correct coordinate order
        weather_data = fetch_weather_data(latitude, longitude)
        if not weather_data:
            return jsonify({"error": "Failed to fetch weather data"}), 500
            
        aqi = data.get('aqi', 0)
        
        # get weather factors from OpenMeteo
        temperature = weather_data['temperature']
        humidity = weather_data['humidity']
        wind_speed = weather_data['wind_speed']
        
        app.logger.info(f"""
            Weather data for coordinates {coordinates}:
            Temperature: {temperature}°F
            Humidity: {humidity}%
            Wind Speed: {wind_speed} mph
        """)
        
        # Process image
        app.logger.info(f"Downloading image from: {data['imageUrl']}")
        processed_image = download_and_process_image(data['imageUrl'])
        
        # Run CNN prediction
        prediction = onnx_predict(session, processed_image)
        cnn_score = float(prediction[0][0])
        
        # Normalize environmental factors
        aqi_normalized = min(aqi / 500, 1.0)
        humidity_factor = max(0, 1 - (humidity / 100))
        
        # Temperature risk factor (increases after 80°F)
        temp_factor = 1.0
        if temperature > 80:
            temp_factor = 1.0 + ((temperature - 80) / 40)
        
        # Wind risk factor (exponential increase after 15mph)
        wind_factor = 1.0
        if wind_speed > 15:
            wind_factor = 1.0 + ((wind_speed - 15) / 15) ** 1.5
        
        # Calculate comprehensive risk score
        base_risk = (
            0.35 * cnn_score +
            0.20 * aqi_normalized +
            0.15 * min(wind_factor, 2.0) +
            0.15 * min(temp_factor, 2.0) +
            0.15 * humidity_factor
        )
        
        risk_percentage = min(int(base_risk * 100), 100)

        
        app.logger.info(f"""
            Prediction details for coordinat
[truncated — 4676 more characters]
```

### frontend/src/app/layout.tsx

```typescript
// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";

import NavigationBar from "@/components/NavigationBar";

export const metadata: Metadata = {
  title: "Wildfire Monitoring Dashboard",
  description: "Dashboard for monitoring wildfires",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className="antialiased flex">
        <NavigationBar />
        <div className="flex-1">{children}</div>
      </body>
    </html>
  );
}

```

### frontend/src/app/page.tsx

```typescript
// home page
"use client"

import Link from "next/link";
import { Button } from "@/components/ui/button";

export default function Home() {

  return (
    <div className="min-h-screen overflow-x-hidden bg-gradient-to-br from-gray-900 via-gray-800 to-orange-900">
      {/* Navigation */}
      <nav className="p-4">
        <div className="container mx-auto flex justify-end items-center">
          <div className="space-x-6">
            <Link
              href="/about"
              className="text-gray-300 hover:text-orange-400 transition-colors"
            >
              About Us
            </Link>
            <Link
              href="/features"
              className="text-gray-300 hover:text-orange-400 transition-colors"
            >
              Features
            </Link>
          </div>
        </div>
      </nav>

      {/* Hero Section */}
      <div className="container mx-auto px-4 flex items-center min-h-[85vh] overflow-hidden relative">
        {/* Left content */}
        <div className="max-w-4xl pl-12 z-10">
          <h1 className="text-6xl font-bold text-white mb-6">Meet PYRO.AI!</h1>
          <h2 className="text-7xl font-bold mb-8 animate-gradient tracking-tight">
            Stay Ahead of the Flames
          </h2>
          <p className="text-xl text-gray-300 mb-12 max-w-2xl">
            Your real-time AI companion in wildfire safety. We're here to help protect what matters most,
            providing critical updates and personalized evacuation guidance when every moment counts.
          </p>
          <Link href="/dashboard">
            <Button className="bg-orange-500 hover:bg-orange-600 text-white px-8 py-6 text-lg rounded-lg transform transition hover:scale-105 shadow-lg">
              Get Started →
            </Button>
          </Link>
        </div>

        {/* MacBook Preview with Glowing Effect */}
        <div className="flex-1 ml-[-10%] scale-[1.50] origin-center mr-[-15%] relative">
          {/* Glowing effect */}
          <div
            className="absolute top-[14%] left-[23.3%] w-[60%] h-[63.7%] bg-orange-500 rounded-2xl blur-3xl opacity-30 z-0"
            style={{ filter: "blur(60px)" }}
          />
          {/* Map overlay */}
          <img
            src="/map.jpg"
            alt="Dashboard Map"
            className="absolute top-[14%] left-[23.3%] w-[60%] h-[63.7%] object-cover rounded-2xl z-20"
          />
          {/* MacBook frame */}
          <img
            src="/mac-background.png"
            alt="PYRO.AI Dashboard Preview"
            className="w-full h-auto object-contain relative z-10"
          />
        </div>
      </div>
    </div>
  )
}

```

### frontend/src/app/news/page.tsx

```typescript
'use client'

import NewsSection from './NewsSection';

export default function NewsPage() {
  return (
    <div className="container mx-auto p-4">
      <h1 className="text-2xl font-bold mb-4">News & Updates</h1>
      <NewsSection />
    </div>
  );
}

```

### frontend/src/app/about/page.tsx

```typescript
"use client";

import Link from "next/link";
import { Button } from "@/components/ui/button";
import { ArrowLeft, Flame } from "lucide-react";

export default function About() {
  return (
    <div className="h-screen bg-gradient-to-br from-gray-900 via-gray-800 to-red-950 overflow-hidden flex flex-col">
      {/* Navigation */}
      <nav className="p-3">
        <div className="container mx-auto">
          <Link 
            href="/"
            className="inline-flex items-center text-gray-300 hover:text-orange-400 transition-colors"
          >
            <ArrowLeft className="h-4 w-4 mr-2" />
            Back to Home
          </Link>
        </div>
      </nav>

      {/* Main Content */}
      <div className="flex-1 flex items-center justify-center">
        <div className="container mx-auto px-4">
          <div className="max-w-6xl mx-auto">
            {/* Mission Header */}
            <div className="flex items-center justify-center gap-3 mb-6">
              <Flame className="h-10 w-10 text-orange-500" />
              <h1 className="text-4xl font-bold text-white">Our Mission</h1>
            </div>

            {/* Story Section */}
            <div className="flex justify-center mb-8">
              <div className="bg-black/30 rounded-xl p-8 backdrop-blur-sm border border-gray-800 shadow-xl w-[95%]">
                <h2 className="text-2xl font-semibold text-orange-400 mb-4">
                  The Catalyst for Change
                </h2>
                <p className="text-gray-300 leading-relaxed mb-6 text-lg">
                  In January 2025, the world watched in horror as devastating wildfires engulfed Los Angeles, 
                  with the Palisades and Eaton fires consuming over 37,000 acres, destroying more than 16,000 
                  structures, and tragically claiming at least 29 lives. For weeks, these fires dominated global 
                  headlines, exposing critical gaps in wildfire detection, risk assessment, and evacuation planning.
                </p>
                <div className="border-l-4 border-orange-500 pl-6 py-2">
                  <p className="text-xl text-white italic">
                    It is clear that now more than ever, there is an urgent need for proactive and smarter 
                    wildfire management systems.
                  </p>
                </div>
              </div>
            </div>

            {/* Info Sections */}
            <div className="flex justify-center mb-8">
              <div className="grid md:grid-cols-2 gap-6 w-[95%]">
                <div className="bg-black/20 rounded-xl p-6 border border-gray-800">
                  <h3 className="text-xl font-semibold text-orange-400 mb-3">Our Solution</h3>
                  <p className="text-gray-300 text-lg">
                    PYRO.AI combines cutting-edge artificial intelligence with real-time data to provide 
                    early detection, accurate risk assessment, and life-saving evacuation guidance.
                  </p>
                </div>
                <div className="bg-black/20 rounded-xl p-6 border border-gray-800">
                  <h3 className="text-xl font-semibold text-orange-400 mb-3">Our Impact</h3>
                  <p className="text-gray-300 text-lg">
                    By leveraging advanced technology and data analytics, we're working to ensure that 
                    communities are better prepared and protected from the threat of wildfires.
                  </p>
                </div>
              </div>
            </div>

            {/* CTA Section */}
            <div className="text-center">
              <Link href="/dashboard">
                <Button 
                  className="bg-gradient-to-r from-orange-600 to-red-600 hover:from-orange-500 hover:to-red-500 
                            text-white px-8 py-6 text-xl rounded-lg transform transition hover:scale-105 shadow-lg"
                >
                  Join Us in Making a Difference →
                </Button>
              </Link>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
```

### frontend/src/app/features/page.tsx

```typescript
"use client";

import Link from "next/link";
import { Button } from "@/components/ui/button";
import { ArrowLeft, Navigation, Flame, Radio, Brain, Route, Bell, Shield } from "lucide-react";

export default function Features() {
  return (
    <div className="min-h-screen bg-gradient-to-br from-gray-900 via-gray-800 to-red-950">
      {/* Navigation */}
      <nav className="p-4">
        <div className="container mx-auto">
          <Link 
            href="/"
            className="inline-flex items-center text-gray-300 hover:text-orange-400 transition-colors"
          >
            <ArrowLeft className="h-4 w-4 mr-2" />
            Back to Home
          </Link>
        </div>
      </nav>

      {/* Main Content */}
      <div className="container mx-auto px-4 py-16">
        <div className="max-w-6xl mx-auto">
          {/* Header */}
          <div className="text-center mb-16">
            <h1 className="text-5xl font-bold text-white mb-6">
              Cutting-Edge Features
            </h1>
            <p className="text-xl text-gray-300 max-w-3xl mx-auto">
              Advanced technology working around the clock to keep communities safe
            </p>
          </div>

          {/* Feature Grid */}
          <div className="grid md:grid-cols-3 gap-8 mb-16">
            {/* Feature 1: Evacuation Planning */}
            <div className="bg-black/30 rounded-2xl p-8 backdrop-blur-sm border border-gray-800 shadow-xl 
                          transform transition-all duration-300 hover:scale-105">
              <div className="flex items-center gap-4 mb-6">
                <div className="bg-orange-500/10 p-3 rounded-lg">
                  <Route className="h-8 w-8 text-orange-400" />
                </div>
                <h3 className="text-2xl font-semibold text-white">Automated Evacuation</h3>
              </div>
              <ul className="space-y-4 text-gray-300">
                <li className="flex items-start gap-2">
                  <Navigation className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Real-time route optimization based on fire spread</span>
                </li>
                <li className="flex items-start gap-2">
                  <Bell className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Instant alerts for evacuation orders</span>
                </li>
                <li className="flex items-start gap-2">
                  <Shield className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Safe shelter location guidance</span>
                </li>
              </ul>
            </div>

            {/* Feature 2: Fire Detection */}
            <div className="bg-black/30 rounded-2xl p-8 backdrop-blur-sm border border-gray-800 shadow-xl 
                          transform transition-all duration-300 hover:scale-105">
              <div className="flex items-center gap-4 mb-6">
                <div className="bg-orange-500/10 p-3 rounded-lg">
                  <Flame className="h-8 w-8 text-orange-400" />
                </div>
                <h3 className="text-2xl font-semibold text-white">Smart Detection</h3>
              </div>
              <ul className="space-y-4 text-gray-300">
                <li className="flex items-start gap-2">
                  <Radio className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>24/7 satellite monitoring and early detection</span>
                </li>
                <li className="flex items-start gap-2">
                  <Brain className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>AI-powered fire spread prediction</span>
                </li>
                <li className="flex items-start gap-2">
                  <Flame className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Real-time fire behavior analysis</span>
                </li>
              </ul>
            </div>

            {/* Feature 3: Information Access */}
            <div className="bg-black/30 rounded-2xl p-8 backdrop-blur-sm border border-gray-800 shadow-xl 
                          transform transition-all duration-300 hover:scale-105">
              <div className="flex items-center gap-4 mb-6">
                <div className="bg-orange-500/10 p-3 rounded-lg">
                  <Brain className="h-8 w-8 text-orange-400" />
                </div>
                <h3 className="text-2xl font-semibold text-white">Instant Access</h3>
              </div>
              <ul className="space-y-4 text-gray-300">
                <li className="flex items-start gap-2">
                  <Navigation className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Live evacuation maps and shelter locations</span>
                </li>
                <li className="flex items-start gap-2">
                  <Bell className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Emergency alerts and notifications</span>
                </li>
                <li className="flex items-start gap-2">
                  <Shield className="h-5 w-5 text-orange-400 mt-1 flex-shrink-0" />
                  <span>Community safety resources and guidelines</span>
                </li>
              </ul>
            </div>
          </div>

          {/* CTA Section */}
          <div className="text-center">
            <Link href="/dashboard">
              <Button 
                className="bg-gradient-to-r from-orange-600 to-red-600 hover:from-orange-500 hover:to-red-500 
                          text-white px-8 py-6 text-lg rounded-lg transform transition hover:scale-105 shadow-lg"
              >
                Experience PYRO.AI →
              </Button>
            </Link>
          </div>
        </div>
      </div>
    </div>
  );
} 
```

### frontend/src/app/dashboard/page.tsx

```typescript
// dashboard page
"use client"

import { useState, useEffect } from "react";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import MapboxMap from "@/components/MapboxMap";
import { AnimatedNumber } from "@/components/AnimatedNumber";
import { Wind, Shield, Flame } from "lucide-react";
import { SidePanel } from "@/components/SidePanel";
import { WildfireProvider } from "@/context/WildfireContext";

// Define helper function for safety color
function getSafetyColor(score: number): string {
  if (score < 25) return "text-red-600";
  if (score < 50) return "text-orange-500";
  if (score < 75) return "text-yellow-500";
  return "text-green-600";
}

// --- API Interfaces and helper function for weather and AQI ---
interface WeatherResponse {
  current: {
    temperature_2m: number;
    wind_speed_10m: number;
    time: string;
  };
  hourly: {
    time: string[];
    temperature_2m: number[];
    wind_speed_10m: number[];
    relative_humidity_2m: number[];
  };
}

interface AirQualityResponse {
  hourly: {
    time: string[];
    us_aqi: number[];
  };
}

async function getWeatherAndAQI(latitude: number, longitude: number) {
  // Weather data endpoint
  const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,wind_speed_10m,relative_humidity_2m`;

  // Air quality endpoint
  const aqiUrl = `https://air-quality-api.open-meteo.com/v1/air-quality?latitude=${latitude}&longitude=${longitude}&hourly=us_aqi`;

  try {
    const [weatherResponse, aqiResponse] = await Promise.all([
      fetch(weatherUrl),
      fetch(aqiUrl)
    ]);

    const weatherData: WeatherResponse = await weatherResponse.json();
    const aqiData: AirQualityResponse = await aqiResponse.json();

    return {
      weather: weatherData,
      airQuality: aqiData
    };
  } catch (error) {
    console.error('Error fetching data:', error);
    throw error;
  }
}

export default function Dashboard() {
  // State variables for wildfire data
  const [riskValue, setRiskValue] = useState<string>("N/A");
  const [safetyScore, setSafetyScore] = useState<number | null>(null);
  const [userCoordinates, setUserCoordinates] = useState<[number, number] | null>(null);
  const [routeData, setRouteData] = useState<any>(null);

  // New state for AQI (Air Quality Index)
  const [aqi, setAqi] = useState<number | null>(null);

  // Sample fireData array used in the chat prompt.
  const fireData = [
    {
      Name: "Sepulveda Fire",
      Location: "405 Freeway, North Sepulveda Boulevard",
      County: "Los Angeles",
      AcresBurned: 45,
      Url: "https://www.fire.ca.gov/incidents/2025/1/23/sepulveda-fire/",
    },
    {
      Name: "Gilman Fire",
      Location: "Gilman Drive, South of La Jolla",
      County: "San Diego",
      AcresBurned: 2,
      Url: "https://www.fire.ca.gov/incidents/2025/1/23/gilman-fire/",
    },
    {
      Name: "Gibbel Fire",
      Location: "State Street and Gibbel Road, Hemet",
      County: "Riverside",
      AcresBurned: 15,
      Url: "https://www.fire.ca.gov/incidents/2025/1/23/gibbel-fire/",
    }
  ];

  // Update AQI whenever userCoordinates changes
  useEffect(() => {
    async function updateAQI() {
      if (userCoordinates) {
        try {
          const { airQuality } = await getWeatherAndAQI(userCoordinates[1], userCoordinates[0]);
          // We use the first hourly AQI value from the API response
          if (airQuality.hourly && airQuality.hourly.us_aqi.length > 0) {
            setAqi(airQuality.hourly.us_aqi[0]);
          }
        } catch (error) {
          console.error("Error updating AQI:", error);
        }
      }
    }
    updateAQI();
  }, [userCoordinates]);

  const aqiDisplay = aqi !== null ? aqi : "N/A";

  return (
    <WildfireProvider
      safetyScore={safetyScore}
      riskValue={riskValue}
      userCoordinates={userCoordinates}
      fireData={fireData}
      routeData={routeData}
      setSafetyScore={setSafetyScore}
      setRiskValue={setRiskValue}
      setUserCoordinates={setUserCoordinates}
      setRouteData={setRouteData}
    >
      <div className="flex flex-col h-screen bg-white text-gray-800">
        {/* Page Header */}
        <header className="flex items-center justify-between p-4 border-b border-gray-200">
          <h1 className="text-xl font-bold">WILDFIRE MONITORING DASHBOARD</h1>
          <span className="text-sm text-gray-500">1/24/2025</span>
        </header>


        {/* Main Content */}
        <div className="flex-1 flex min-h-0 bg-slate-100">
          {/* Left side: Map and Cards */}
          <div className="w-3/4 p-4 flex flex-col min-h-0">
            {/* Top Row: Three Cards */}
            <div className="grid grid-cols-3 gap-4 mb-4">
              {/* Air Quality Index Card */}
              <Card>
                <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
                  <CardTitle className="text-sm font-medium">AIR QUALITY INDEX</CardTitle>
                  <Wind className="h-4 w-4 text-muted-foreground" />
                </CardHeader>
                <CardContent>
                  <div className="text-2xl font-bold text-red-600">{aqiDisplay}</div>
                  <p className="text-xs text-muted-foreground">Current AQI</p>
                </CardContent>
              </Card>

              {/* Safety Score Card */}
              <Card>
                <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
                  <CardTitle className="text-sm font-medium">SAFETY SCORE</CardTitle>
                  <Shield className="h-4 w-4 text-muted-foreground" />
                </CardHeader>
                <CardContent>
                  <div className={`text-2xl font-bold ${safetyScore !== null ? getSafetyColor(safetyScore) : ""}`}>
                    {safetyScore !== null ? <AnimatedNumber value={safetyScore} duration
[truncated — 1489 more characters]
```

### frontend/src/app/api/shelters/route.ts

```typescript
import { NextResponse } from 'next/server';

interface Shelter {
  id: number;
  name: string;
  address: string;
  region: string;
  lat: number;
  lng: number;
  capacity: number;
  information: string;
  date_created: string;
}

const shelters: Shelter[] = [
  {
    id: 1,
    name: "San Diego Emergency Center",
    address: "4000 La Jolla Village Dr",
    region: "La Jolla",
    lat: 32.8700,
    lng: -117.2200,
    capacity: 250,
    information: "Full medical facilities available",
    date_created: new Date().toISOString()
  },
  {
    id: 2,
    name: "Hemet Community Shelter",
    address: "1200 State Street",
    region: "Hemet",
    lat: 33.7100,
    lng: -116.9700,
    capacity: 200,
    information: "Pet-friendly facility",
    date_created: new Date().toISOString()
  },
  {
    id: 3,
    name: "UCSD Evacuation Site",
    address: "9500 Gilman Dr",
    region: "La Jolla",
    lat: 32.8800,
    lng: -117.2350,
    capacity: 500,
    information: "Large capacity facility with medical support",
    date_created: new Date().toISOString()
  },
  {
    id: 4,
    name: "Pasadena Emergency Shelter",
    address: "285 E Walnut St",
    region: "Pasadena",
    lat: 34.1478,
    lng: -118.1445,
    capacity: 200,
    information: "24/7 emergency services available",
    date_created: new Date().toISOString()
  },
  {
    id: 5,
    name: "Westwood Community Center",
    address: "1350 S Sepulveda Blvd",
    region: "Westwood",
    lat: 34.0635,
    lng: -118.4452,
    capacity: 150,
    information: "Food and medical supplies available",
    date_created: new Date().toISOString()
  },
  {
    id: 6,
    name: "Downtown LA Shelter",
    address: "1400 S Main St",
    region: "Downtown",
    lat: 34.0522,
    lng: -118.2437,
    capacity: 300,
    information: "Large capacity emergency shelter",
    date_created: new Date().toISOString()
  },
  {
    id: 7,
    name: "Valley Emergency Center",
    address: "15100 Valley Blvd",
    region: "San Fernando Valley",
    lat: 34.1478,
    lng: -118.3568,
    capacity: 250,
    information: "Family-friendly facility",
    date_created: new Date().toISOString()
  },
  {
    id: 8,
    name: "Long Beach Safe Haven",
    address: "2100 Ocean Blvd",
    region: "Long Beach",
    lat: 33.9283,
    lng: -118.1157,
    capacity: 175,
    information: "Coastal evacuation center",
    date_created: new Date().toISOString()
  },
  {
    id: 9,
    name: "Pasadena Community Center",
    address: "1750 N Altadena Dr",
    region: "Pasadena",
    lat: 34.1675,
    lng: -118.1309,
    capacity: 225,
    information: "Full emergency services and medical care",
    date_created: new Date().toISOString()
  },
  {
    id: 10,
    name: "Rose Bowl Emergency Shelter",
    address: "1001 Rose Bowl Dr",
    region: "Pasadena",
    lat: 34.1613,
    lng: -118.1676,
    capacity: 400,
    information: "Large capacity venue with full amenities",
    date_created: new Date().toISOString()
  },
  {
    id: 11,
    name: "San Diego Convention Center",
    address: "111 W Harbor Dr, San Diego, CA 92101",
    region: "San Diego",
    lat: 32.7113,
    lng: -117.1625,
    capacity: 1000,
    information: "Large capacity shelter with medical support",
    date_created: new Date().toISOString()
  },
  {
    id: 12,
    name: "San Diego High School",
    address: "1700 12th Ave, San Diego, CA 92101",
    region: "San Diego",
    lat: 32.7110,
    lng: -117.1570,
    capacity: 500,
    information: "Emergency shelter with food and supplies",
    date_created: new Date().toISOString()
  },
  {
    id: 13,
    name: "San Diego State University Shelter",
    address: "5500 Campanile Dr, San Diego, CA 92182",
    region: "San Diego",
    lat: 32.7743,
    lng: -117.0710,
    capacity: 600,
    information: "Emergency shelter with food and medical supplies",
    date_created: new Date().toISOString()
  },
  {
    id: 14,
    name: "Mission Valley Shelter",
    address: "12345 Mission Valley Rd, San Diego, CA 92120",
    region: "San Diego",
    lat: 32.7750,
    lng: -117.1500,
    capacity: 400,
    information: "Shelter with full amenities and support services",
    date_created: new Date().toISOString()
  },
  {
    id: 15,
    name: "Chula Vista Community Center",
    address: "276 Fourth Ave, Chula Vista, CA 91910",
    region: "San Diego",
    lat: 32.6401,
    lng: -117.0842,
    capacity: 300,
    information: "Community center serving as an emergency shelter",
    date_created: new Date().toISOString()
  }
];

function findNearestShelters(lat: number, lng: number, maxDistance: number = 20) {
  return shelters.filter(shelter => {
    const distance = calculateDistance(lat, lng, shelter.lat, shelter.lng);
    return distance <= maxDistance;
  }).map(shelter => ({
    ...shelter,
    distance: calculateDistance(lat, lng, shelter.lat, shelter.lng)
  }));
}

function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
  const R = 6371; // Earth's radius in km
  const dLat = toRad(lat2 - lat1);
  const dLon = toRad(lon2 - lon1);
  const a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  return R * c;
}

function toRad(value: number): number {
  return value * Math.PI / 180;
}

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const lat = parseFloat(searchParams.get('lat') || '0');
  const lng = parseFloat(searchParams.get('lng') || '0');

  if (lat && lng) {
    const nearestShelters = findNearestShelters(lat, lng);
    return NextResponse.json({ shelters: nearestShelters });
  }

  return NextResponse.json({ shelters });
} 
```

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