A Linux weather application that displays current weather in the system tray. Supports multiple weather providers and shows data directly on the panel — no need to open a browser.
Built with GTK 3, AppIndicator3, and Jinja2 templates.
- Current weather visible in the system tray (temperature, humidity, pressure, wind)
- Emoji-based weather icon rendered via Cairo + Pango
- Full weather forecast in a dialog window with Dracula dark theme (WebKit2)
- Pluggable weather providers: wttr.in and Open-Meteo (no API key required)
- Automatic data refresh every 60 seconds
- Automatic city detection based on IP address (ipinfo.io)
- 7 languages: Polish, English, German, French, Italian, Spanish, Czech
- Per-provider settings (e.g. forecast days 1–14)
- Settings applied reactively — no app restart needed
- Customizable Jinja2 HTML templates with 3-level resolution (user override → provider → default)
- Linux with system tray support (e.g. GNOME with AppIndicator extension, KDE, XFCE)
- Python >= 3.10
- System packages:
sudo apt install gir1.2-appindicator3-0.1 gir1.2-webkit2-4.1 libgirepository1.0-dev
git clone https://github.com/<user>/weather.git
cd weather
python3 -m venv .venv
.venv/bin/pip install -e .# After installation:
weather
# Or via module:
PYTHONPATH=src python3 -m weatherAfter launching, an emoji icon with the current weather appears in the system tray. The context menu (right-click) contains:
- Weather — full forecast for the coming days
- Options — city, provider, language and per-provider settings
- Information — about the application
- Quit — quit the application
src/weather/
├── __init__.py # package version
├── __main__.py # python -m weather
├── app.py # WeatherTrayIcon — main application class
├── data/
│ ├── base.py # Data — base JSON-backed class
│ ├── config.py # Config — static configuration
│ ├── language.py # Language — UI translations + WMO codes
│ └── options.py # OptionsData — user preferences
├── services/
│ ├── geolocation.py # IP-based city detection
│ ├── icon_renderer.py # EmojiIconRenderer — emoji→PNG via Cairo+Pango
│ ├── models.py # CurrentWeather, DailyForecast, WeatherData dataclasses
│ ├── provider.py # WeatherProvider Protocol
│ ├── registry.py # Provider registry (register/create/list)
│ ├── renderer.py # DefaultWeatherRenderer — Jinja2 HTML rendering
│ └── providers/
│ ├── wttr_in/ # wttr.in provider + template
│ └── open_meteo/ # Open-Meteo provider + template
├── ui/
│ ├── simple_dialog.py # SimpleDialog — base GTK dialog
│ ├── options_dialog.py # OptionsDialog — settings form with tabs
│ ├── information_dialog.py # InformationDialog — about dialog
│ ├── field_wrapper.py # FieldWrapper — form field builder
│ └── labels.py # LeftLabel, CenterLabel
└── resources/
├── config.json
├── lang/ # pl, en, de, fr, it, es, cs
└── templates/
└── forecast.html # default Jinja2 template (Dracula theme)
| Provider | API Key | Geocoding | Details |
|---|---|---|---|
| wttr.in | Not needed | Built-in | Rich localized data via format-based API |
| Open-Meteo | Not needed | Separate geocoding API | Free, open-source weather API |
Each provider lives in its own subfolder under services/providers/ with auto-registration. Adding a new provider requires:
- Create
services/providers/{key}/withprovider.pyand__init__.py - Implement the
WeatherProviderProtocol - Call
register_provider()in__init__.py - Optionally add a
templates/forecast.htmloverride
Forecast HTML is rendered via Jinja2 with a 3-level template resolution:
- User override:
~/.local/share/weather/templates/{provider_key}/forecast.html - Provider template: bundled with the provider package
- Default fallback:
weather.resources.templates/forecast.html
Templates receive: city, provider_name, current (CurrentWeather), daily (list of DailyForecast), t (translations), wmo (WMO code descriptions).
# Development environment:
python3 -m venv .venv
.venv/bin/pip install -e . ruff mypy pytest types-requests typing_extensions
# Linting:
.venv/bin/ruff check src/
# Formatting:
.venv/bin/ruff format src/
# Type checking:
.venv/bin/mypy src/weather/
# Tests (253 unit tests):
.venv/bin/pytest -vTests use mocked GTK widgets (stubs in tests/conftest.py), so they run without an X11 server or the system gi package.
- Python 3.10+
- GTK 3 + AppIndicator3 — system tray and UI
- WebKit2 — rendering forecast as HTML
- Jinja2 — HTML template engine
- Cairo + Pango — emoji-to-PNG icon rendering
- requests — API communication
- wttr.in / Open-Meteo — weather data sources
- ipinfo.io — IP-based geolocation
User preferences are stored in:
~/.local/share/weather/options.json
Available options:
| Option | Description | Default |
|---|---|---|
city |
City name | Auto-detected via IP |
locale |
UI language (pl, en, de, fr, it, es, cs) |
pl |
provider |
Weather provider (wttr.in, open-meteo) |
wttr.in |
providers_settings |
Per-provider settings (e.g. forecast_days: 1–14) |
{"forecast_days": 3} |
Adrian Kuriata