Weather data is free. Weather decisions are not.
This isn't a temperature display - it's a small explainable decision engine that turns raw weather and air quality data into specific, reasoned answers: should you carry an umbrella, is today good for a run, is the air safe to breathe, is travel likely to be disrupted.
Every recommendation comes with a plain-English reasoning trace citing the exact factor(s) behind it, instead of a black-box yes/no.
Live demo: add your deployed URL here after deploying
Add a screenshot or GIF of the dashboard here once deployed - the recommendation cards with visible reasoning are the most important thing for a visitor to see in the first few seconds.
A typical weather app's job ends at displaying data. This project's actual subject is the
recommendation engine sitting on top of that data: five independent, unit-tested rules,
each with its own configurable thresholds and its own human-readable explanation, orchestrated
by a small engine that knows nothing about the rules themselves. Adding a new recommendation
type means writing one new class - no existing code changes. See
docs/architecture.md for the full design and
docs/decision-log.md for the reasoning behind every major
architectural choice (why no provider averaging, why no Redis/auth/DB in v1, why thresholds
live in configuration instead of code).
- Should I carry an umbrella today?
- Is today good for running?
- Is today good for outdoor activities?
- Is today good for travelling?
- Is the air quality safe?
The original MVP answered "what should I do today, for one location." This maintenance pass extends that without changing what the project fundamentally is - still Spring Boot + Thymeleaf, still server-rendered, still zero database, still one Docker image:
- Location search now supports disambiguation: if a search term matches more than one place, a picker is shown instead of silently guessing (e.g. searching a common city name).
- Browser geolocation ("use my location") and hourly + 5-day forecast (Open-Meteo only, matching the project's existing no-cross-provider-fallback policy for anything beyond current conditions).
- Pressure, visibility, sunrise/sunset, local time, and coordinates added to the conditions display.
- Dark mode, with no flash-of-incorrect-theme,
prefers-color-schemerespected on first visit, and the choice persisted inlocalStorage. - Recent searches and a retry action on the error state.
- One new file,
static/js/dashboard.js- the project's first and only client-side script, intentionally small, vanilla, and framework-free. Everything else stays server-rendered.
See the changelog at the bottom of this README for the complete list of changes made in this pass, including the Spring Boot 3.3.4 → 3.5.16 version bump (the 3.3.x line reached end-of-life).
- Java 17 + Spring Boot 3.5 + Maven
- Thymeleaf for server-rendered views
- Vanilla JavaScript (
static/js/dashboard.js) for dark mode, geolocation, and recent searches - no framework, no bundler, no build step - Open-Meteo (primary weather/air-quality/forecast/geocoding provider - no API key required)
- OpenWeatherMap (documented fallback provider for current conditions only, used if
Open-Meteo is unavailable; forecast has no fallback, see
docs/decision-log.md) - Caffeine for in-memory caching with per-data-type TTLs
- Docker + GitHub Actions CI
No API key is required to run this project - Open-Meteo, the primary provider, is keyless.
- Java 17+
- (No local Maven install required - the Maven Wrapper is included)
git clone https://github.com/your-username/weather-intelligence-dashboard.git
cd weather-intelligence-dashboard
./mvnw spring-boot:runThen open http://localhost:8080.
Note: browser geolocation ("use my location") only works over
localhostor HTTPS - this is a browser security restriction, not an application bug. It works fine locally and on any HTTPS deployment.
./mvnw clean verifyThe application runs completely without this, since it only engages if Open-Meteo fails. To exercise it deliberately:
cp .env.example .env
# edit .env and set OPENWEATHERMAP_API_KEY (free key at https://openweathermap.org/api)
export $(cat .env | xargs)
./mvnw spring-boot:rundocker build -t weather-intelligence-dashboard .
docker run -p 8080:8080 weather-intelligence-dashboardor with Compose:
docker compose up --buildsrc/main/java/com/portfolio/weatherintel/
├── config/ # Typed configuration properties, RestClient + cache beans
├── controller/ # Thymeleaf-facing controllers and view models
├── domain/ # Normalized domain model (WeatherSnapshot, ForecastSnapshot,
│ # HourlyForecastPoint, DailyForecastPoint, Location, enums)
├── provider/ # WeatherProvider interface + Open-Meteo/OpenWeatherMap implementations
├── aggregation/ # Primary/fallback orchestration with caching
├── engine/ # Rule interface, RecommendationEngine, and the five rules
├── service/ # GeocodingService
└── exception/ # Domain exceptions and the global exception handler
src/main/resources/
├── templates/ # Thymeleaf views (dashboard.html, error.html, fragments/)
└── static/
├── css/dashboard.css # All styling, including the dark theme variable set
└── js/dashboard.js # The project's only client-side script (theme, geolocation,
# recent searches) - vanilla, no build step
See docs/architecture.md for the full data flow diagram.
| Rule | Answers | Key factors |
|---|---|---|
UmbrellaRule |
Should I carry an umbrella? | Precipitation probability, precipitation amount |
RunningSuitabilityRule |
Is today good for running? | Feels-like temperature, wind speed, AQI |
OutdoorActivityRule |
Is today good for outdoor activities? | Feels-like temperature, precipitation probability, AQI |
TravelSuitabilityRule |
Is today good for travelling? | Wind speed, precipitation probability/amount |
AirQualityRule |
Is the air quality safe? | US EPA AQI banding |
All thresholds are configurable in application.yml under weather.rules.* - tuning the
engine's behavior does not require a code change.
- "What to wear" recommendation (layered clothing logic)
- User profiles / personalized sensitivity thresholds
- Redis-backed caching for multi-instance deployment
- User accounts and authentication
- Historical trend visualization
Each of these is a deliberate scope decision, documented in
docs/decision-log.md, not an oversight.
See Deployment instructions below, or jump straight to
docs/architecture.md for the resilience and caching design that
makes this deployable as a single, stateless instance. For an evaluation of hosting options
and a deployment checklist, see docs/deployment-review.md.
See CHANGELOG.md for a complete list of changes made in each maintenance
pass.
MIT