This project provides a modern weather forecast web application using the WeatherAPI.com service. It has been completely rebuilt using Blazor (.NET 10) with a Microsoft Fluent UI interface.
- 10-day weather forecast with detailed conditions
- Current weather conditions (temperature, humidity, wind, visibility, pressure)
- Astronomy data (sunrise/sunset, moon phase & illumination)
- Weather alerts with collapsible detail cards
- UV Index classification (Low → Extreme) with WHO recommendations
- Air Quality Index (EPA scale) with health guidance and PM2.5/PM10 readings
- Microsoft Fluent UI for Blazor components
- Location autocomplete search powered by WeatherAPI
- Temperature unit toggle — switch between °C and °F
- Dark/Light theme toggle
- Responsive layout for desktop and mobile
- .NET 10 SDK
- A WeatherAPI key (sign up at WeatherAPI.com)
Set your WeatherAPI key via one of these methods:
Option A — appsettings.json (development only; keep out of source control):
{
"WeatherApiKey": "your_key_here"
}Option B — Environment variable (recommended for production):
export WEATHER_API_KEY=your_key_herecd WeatherBlazor
dotnet runThen open your browser at http://localhost:5155/.
cd WeatherBlazor.Tests
dotnet testWeatherBlazor/ ← Blazor Web App (.NET 10)
├── Components/
│ ├── Layout/
│ │ ├── MainLayout.razor ← Header, search bar, theme toggle
│ │ └── ReconnectModal.razor
│ ├── Pages/
│ │ ├── Home.razor ← Main weather page
│ │ └── NotFound.razor
│ └── Weather/
│ ├── SearchBar.razor ← Autocomplete location search
│ ├── CurrentWeatherCard.razor ← Current conditions
│ ├── ForecastList.razor ← 10-day forecast
│ ├── AstronomyCard.razor ← Sun/moon information
│ ├── SafetyMetrics.razor ← UV Index + Air Quality
│ └── AlertsSection.razor ← Collapsible weather alerts
├── Models/
│ └── WeatherModels.cs ← All data models (C# records/classes)
├── Services/
│ ├── IWeatherService.cs ← Service interface
│ ├── WeatherApiService.cs ← WeatherAPI.com implementation
│ ├── SafetyFeaturesService.cs ← UV + AQI enrichment
│ └── AstronomyService.cs ← Moon phase + daylight enrichment
└── wwwroot/
└── app.css ← Weather app styles (light + dark)
WeatherBlazor.Tests/ ← xUnit unit tests
├── SafetyFeaturesServiceTests.cs
└── AstronomyServiceTests.cs
The application uses Blazor Server with interactive server-side rendering:
IWeatherService— abstraction layer; swap providers by implementing this interfaceWeatherApiService— concrete implementation usingHttpClient+System.Text.JsonSafetyFeaturesService— static enrichment for UV Index and Air QualityAstronomyService— static enrichment for astronomy data and moon phases- Dependency injection via
Program.cs; API key read fromWeatherApiKeyconfig orWEATHER_API_KEYenv var
curl "http://localhost:5000/api/validate-location?location=New York"
curl "http://localhost:5000/api/search-locations?q=London"
curl -X POST http://localhost:5000/api/weather/bulk
-H "Content-Type: application/json"
-d '{"locations": ["New York", "London", "Tokyo"], "tempUnit": "celsius"}'
curl "http://localhost:5000/api/detailed-forecast?location=Paris"
### Running with Docker
1. Build the Docker image:
```bash
docker build -t weather-py .
-
Run the container:
docker run -p 80:80 -e WEATHER_API_KEY=your_weather_api_key weather-py
-
Access the application at
http://localhost/forecast?zip=12345.
Run the test suite using pytest:
pytestWhen WEATHER_DEBUG_MODE=true is set in your .env file, a debug panel becomes available. The panel is hidden by default and can be opened by:
- Clicking the "🔧 DEBUG" tab on the left edge of the screen
- Pressing
Ctrl+Shift+D
The debug panel provides:
- Weather JSON - Raw API response for the current city with syntax highlighting
- Cache - View cached API requests with TTL countdown
- State - Live StateManager state and event log
- Requests - API call history with timing and status
- Environment - Server info and safe environment variables
Note: The debug panel is hidden on mobile devices (screens ≤ 768px).
This project includes a GitHub Actions workflow (.github/workflows/deploy-to-azure.yml) that deploys both the Python/Flask app and the Blazor Server app to Azure Container Apps on every push to master.
The existing Dockerfile builds the Flask app. It is deployed to the Azure Container App specified by the CONTAINER_APP_NAME repository secret.
The Dockerfile.blazor file contains the multi-stage build definition for the .NET 10 Blazor Server application located in WeatherBlazor/.
# Build the image (run from the repository root)
docker build -f Dockerfile.blazor -t weather-blazor:latest .
# Run the container locally
docker run -p 8080:80 \
-e WeatherApiKey=your_weather_api_key \
-e AzureOpenAI__ApiKey=your_openai_key \
-e AzureOpenAI__Endpoint=your_openai_endpoint \
-e AzureOpenAI__Deployment=your_deployment_name \
weather-blazor:latest
# Visit http://localhost:8080The build-and-deploy-blazor job in the workflow builds and pushes the Blazor image to GitHub Container Registry as weather-blazor:latest, then deploys it to a separate Azure Container App (distinct from the Python app) so Azure generates a unique URL for the Blazor front-end.
On first run the job creates the Container App; subsequent runs update it.
| Secret | Description |
|---|---|
AZURE_CLIENT_ID |
Azure service-principal / app registration client ID (shared) |
AZURE_TENANT_ID |
Azure AD tenant ID (shared) |
AZURE_SUB_ID |
Azure subscription ID (shared) |
GHCR_USERNAME |
GitHub username for GHCR authentication (shared) |
GHCR_PAT |
GitHub personal access token with write:packages scope (shared) |
RESOURCE_GROUP |
Azure resource group name (shared) |
CONTAINER_APP_ENVIRONMENT |
Name of the existing Azure Container Apps managed environment (shared) |
BLAZOR_CONTAINER_APP_NAME |
New — unique name for the Blazor Container App (e.g. weather-blazor) |
WEATHER_API_KEY |
New — API key for weatherapi.com |
AZURE_OPENAI_API_KEY |
Azure OpenAI API key (shared) |
AZURE_OPENAI_ENDPOINT |
Azure OpenAI endpoint URL (shared) |
AZURE_OPENAI_DEPLOYMENT |
Azure OpenAI deployment/model name (shared) |
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
Author: John Wildes
Email: johnwildes@decklatedev.com
