Prompt file imported from ibnehussain/batch01app (
.github/prompts/plan-weatherDashboardApp.prompt.md). Copyright stays with the author.
Weather Dashboard App — Plan
Functional Requirements
- Location Search — User can search for a city/location by name
- Current Weather Display — Show temperature, weather condition, humidity, wind speed, and "feels like"
- Weather Icon — Display an icon representing the current condition
- 5-Day Forecast — Show upcoming daily forecast with high/low temps and conditions
- Unit Toggle — Switch between Celsius and Fahrenheit
- Frontend fetches weather data from Flask backend via
fetch()/ AJAX - Dynamically update the DOM without full page reload
- Display loading state while data is being fetched
- Display user-friendly error messages (e.g., "City not found")
- Flask exposes
GET /api/weather?city=&unit= - Flask calls OpenWeatherMap API server-side and returns clean JSON
- Handle invalid city names and API errors with appropriate HTTP status codes (400, 404, 502)
Non-Functional Requirements
- Response time under 2 seconds under normal conditions
- Cache repeated requests for the same city (in-memory dict or Flask-Caching)
- API key stored server-side only in
.env— never exposed to browser - Input validation and sanitization on the Flask endpoint
- CORS configured to allow only the expected frontend origin
- Responsive design — works on mobile, tablet, and desktop
- Accessible UI — proper contrast ratios, semantic HTML, ARIA labels
- Graceful degradation when the third-party API is unavailable
- Meaningful HTTP error codes returned from Flask
- Environment-based configuration via
python-dotenv - Clear separation of concerns: Flask handles data fetching; JS handles rendering
User Stories
US-1: Search for Weather by City
As a user, I want to search for a city by name so that I can view the current weather conditions for that location.
Acceptance Criteria:
- A search input and button are visible on the page
- Typing a city name and submitting fetches and displays current weather
- If the city is not found, a clear error message is shown
US-2: View Current Weather Details
As a user, I want to see the current temperature, humidity, wind speed, and weather condition so that I can understand what the weather is like right now.
Acceptance Criteria:
- Displays temperature, humidity, wind speed, "feels like", and a weather icon
- Data updates each time a new city is searched
- A loading indicator appears while data is being fetched
US-3: View a Multi-Day Forecast
As a user, I want to see a 5-day forecast so that I can plan my week around expected weather conditions.
Acceptance Criteria:
- Forecast shows each day's date, high/low temperature, and weather condition icon
- Forecast updates when a new city is searched
- Displayed below the current weather section
US-4: Toggle Between Celsius and Fahrenheit
As a user, I want to switch between Celsius and Fahrenheit so that I can view temperatures in my preferred unit.
Acceptance Criteria:
- A toggle (button or switch) is always visible on the dashboard
- Switching units instantly converts all displayed temperatures without re-fetching data
- The selected unit persists when the user searches for a new city
Architecture
Components
- Frontend: HTML + CSS + JavaScript (browser)
- Backend: Flask (Python) — API proxy, input validation, caching
- External API: OpenWeatherMap (
/data/2.5/weather+/data/2.5/forecast) - Config:
.envwithOWM_API_KEYloaded viapython-dotenv
API Contract
GET /api/weather?city=London&unit=metric
200 OK:
{
"city": "London",
"country": "GB",
"current": {
"temp": 18,
"feels_like": 16,
"humidity": 72,
"wind_speed": 5.1,
"condition": "Partly Cloudy",
"icon": "02d"
},
"forecast": [
{ "date": "2026-06-09", "high": 20, "low": 13, "condition": "Rain", "icon": "10d" },
...
]
}
400: { "error": "City name is required" }
404: { "error": "City not found" }
502: { "error": "Weather service unavailable" }
Data Flow
- User types city name and clicks Search
- JS shows loading spinner, calls
GET /api/weather?city=...&unit=... - Flask validates and sanitizes input
- Flask checks in-memory cache (keyed by
city:unit) - On cache miss: Flask calls OWM current + forecast endpoints
- Flask parses raw OWM JSON into clean response shape and stores in cache
- Flask returns JSON to frontend
- JS hides spinner, renders current weather and forecast cards
Folder Structure
batch01app/
├── backend/
│ ├── app.py # Flask app entry point, routes
│ ├── weather_service.py # OWM API calls, data parsing
│ ├── cache.py # In-memory cache logic
│ ├── requirements.txt # Flask, requests, python-dotenv
│ └── .env # OWM_API_KEY (never committed)
│
├── frontend/
│ ├── index.html # Main HTML shell
│ ├── css/
│ │ └── style.css # Responsive styles, weather cards
│ └── js/
│ ├── app.js # Entry point: event listeners, orchestration
│ ├── api.js # fetch() calls to Flask backend
│ └── ui.js # DOM rendering, loading/error states
│
├── .gitignore # Ignore .env, __pycache__, venv/
└── README.md # Setup instructions
Tech Stack
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | HTML + CSS + JS | UI rendering, user input |
| Backend | Flask (Python) | API proxy, key management |
| Weather API | OpenWeatherMap | Live weather data source |
| Config | python-dotenv | Secure API key management |
| Caching | In-memory dict | Reduce external API calls |