Портфолио-проект Loliconus — интерактивный дашборд погоды на базе Open-Meteo API. Демонстрирует полный стек: REST API интеграция, ETL-пайплайн, визуализация данных, CI/CD production-grade.
Рынок: РФ (ru-RU локаль, кириллица, московское время по умолчанию)
- 🔴 Live mode — живые данные прямо из Open-Meteo API (JS fetch)
- 📸 Snapshot mode — ежедневный CI-снимок (06:00 МСК), работает без сети
- 🔍 Поиск города с дебаунсом 300 мс, геолокация браузера
- 📅 7-дневный прогноз с графиком температур и анализом тренда
- ⏱ Почасовой прогноз с переключением дней без перезагрузки
- 🌫 Качество воздуха — PM2.5, PM10, CO, NO₂, O₃, European AQI
- 🧮 11 метеоиндексов — Heat Index, Wind Chill, Humidex и другие
- 🌡 Comfort Score — взвешенный индекс комфорта 0–100
- ❄️ Алерты — Frost Risk, High Wind Alert
- 🌙 Dark mode из коробки (
prefers-color-scheme) - ♿ A11y — ARIA-атрибуты, skip-to-content,
prefers-reduced-motion - 📱 Адаптивный дизайн — mobile, tablet, desktop
Добавьте скриншоты после первого деплоя:
docs/screenshots/hero.png,docs/screenshots/charts.png,docs/screenshots/indices.png
Weather Dashboard is a portfolio project showcasing REST API integration with Open-Meteo, ETL data processing, interactive Chart.js visualizations, and production-grade CI/CD. Built with Python 3.14 (snapshot generation) and Vanilla JS ES2022 (browser runtime). Deployed to GitHub Pages via GitHub Actions with OIDC, SHA-pinned actions, and supply chain security.
| Инструмент | Версия | Назначение |
|---|---|---|
| Python | 3.14 | Генерация снимков, расчёты |
| httpx | ≥ 0.28 | Async HTTP-клиент |
| Jinja2 | ≥ 3.1 | Шаблонизация HTML |
| tenacity | ≥ 9.0 | Retry + exponential backoff |
| Chart.js | 4.x | Интерактивные графики |
| Vanilla JS | ES2022 | Рантайм браузера |
| uv | latest | Менеджер пакетов Python |
| ruff | ≥ 0.9 | Линтер и форматтер |
| ty | ≥ 0.0.1a1 | Type checker |
| pytest + hypothesis | latest | Тесты |
| respx | ≥ 0.21 | Mock httpx |
| GitHub Actions | — | CI/CD |
| GitHub Pages | — | Хостинг |
| Индекс | Формула / Источник | Условие применения |
|---|---|---|
| Heat Index | Rothfusz/NWS многочлен | T ≥ 27°C, RH ≥ 40% |
| Wind Chill | Environment Canada (2001) | T ≤ 10°C, V ≥ 1.3 м/с |
| Humidex | MSC (Masterson & Richardson, 1979) | — |
| Dew Point | Magnus (α=17.625, β=243.04°C) | RH > 0% |
| UV Risk | WHO UV Index Scale | — |
| EAQI Category | European Environment Agency | — |
| Precip Intensity | WMO No. 8 (CIMO Guide) | — |
| Weather Trend | МНК без NumPy, R² | ≥ 2 значений |
| Comfort Score | Взвешенные субиндексы | 5 параметров |
| Frost Risk | T_min < 0°C | — |
| High Wind Alert | Шкала Бофорта ≥ 14 м/с | — |
Weather-Dashboard-Open-Meteo-API/
├── src/weather_dashboard/
│ ├── api/
│ │ ├── client.py # Async httpx-клиент, retry, кеш
│ │ ├── endpoints.py # StrEnum URL/переменных (SSOT)
│ │ └── models.py # frozen dataclasses, RFC 9457
│ ├── processing/
│ │ ├── aggregations.py # hourly → daily агрегаты
│ │ ├── indices.py # 11 метеоиндексов (pure, без NumPy)
│ │ └── validators.py # ValueError/warnings на некорректный вход
│ ├── rendering/
│ │ ├── generator.py # Оркестратор пайплайна
│ │ └── templates/ # Jinja2 шаблоны
│ └── config.py # frozen dataclass + os.environ
├── tests/
│ ├── unit/ # test_validators, test_aggregations, test_indices
│ ├── integration/ # test_client (respx mock)
│ └── conftest.py
├── docs/ # GitHub Pages output (CI-генерация)
│ ├── index.html
│ ├── about.html
│ └── assets/
│ ├── data.js # Snapshot JSON
│ ├── dashboard.js # Live mode + Chart.js
│ └── style.css
├── .github/
│ ├── workflows/
│ │ ├── deploy.yml # Cron 06:00 MSK + push→deploy
│ │ └── quality.yml # PR gates
│ └── ISSUE_TEMPLATE/
├── pyproject.toml # SSOT (PEP 518/621)
└── ...
- Python 3.14+
- uv
git clone https://github.com/Loliconus/Weather-Dashboard-Open-Meteo-API.git
cd Weather-Dashboard-Open-Meteo-API
# Установить зависимости из lockfile
uv sync --frozen --all-extras
# Установить pre-commit хуки
uv run pre-commit installuv run python -m weather_dashboard.rendering.generator
# → Генерирует docs/index.html, docs/about.html, docs/assets/data.js# Любой статический сервер, например:
cd docs && python -m http.server 8080
# Открыть http://localhost:8080# Все тесты + coverage
uv run pytest --cov=src --cov-report=term-missing -v
# Только юнит-тесты (быстро, < 10 сек)
uv run pytest tests/unit/ -q
# Только интеграционные
uv run pytest tests/integration/ -v
# С HTML-отчётом coverage
uv run pytest --cov=src --cov-report=html
open htmlcov/index.htmlТребования: coverage ≥ 80% (processing/), ≥ 60% (api/)
push → main ──┐
├──▶ quality gates (ruff + ty + pytest ≥80%)
cron 06:00 MSK┘ │
▼
generate snapshot (Python)
│
▼
upload docs/ artifact
│
▼
deploy → GitHub Pages (OIDC)
- SHA-пиннинг всех
uses:(SLSA / OWASP A03:2025) - OIDC — без секретов в репозитории
uv sync --frozen— детерминированная сборка изuv.lock
| Источник | Использование | Лицензия |
|---|---|---|
| Open-Meteo | Прогноз, геокодирование, высоты | CC BY 4.0 |
| GeoNames | Данные геокодирования | CC BY 4.0 |
| Copernicus DEM GLO-90 | Высоты рельефа | DOI: 10.5270/ESA-c5d3d65 |
| CAMS (Copernicus) | Качество воздуха | CC BY 4.0 |
Данные погоды предоставляются Open-Meteo.com по лицензии CC BY 4.0.
Loliconus — GitHub
- Код: MIT License
- Данные погоды: CC BY 4.0 (Open-Meteo)