Real-time power outage monitoring dashboard for Ukraine.
(No real credentials required. Features an interactive UI preview).
Important
For Your Security: It is highly recommended to deploy your own instance of the Cloudflare Worker! Your login credentials are sent to the API to generate stateless tokens, so you should only trust your own deployment, not public instances run by strangers.
Warning
Legal Disclaimer:
- This is an unofficial, independent project created for educational and personal use.
- This project is NOT affiliated with, endorsed by, or connected to "E-Svitlo", "Enera", or any energy distribution company.
- The software is provided "AS IS", without warranty of any kind. Use at your own risk.
- About
- Features
- Supported Regions
- Quick Start / Deployment
- Architecture & Security
- API Reference
- Troubleshooting
- Roadmap & Contributing
EnergoMonitor is a progressive web application (PWA) that helps users track scheduled power outages in real-time. The app displays countdown timers, outage schedules, and queue numbers fetched securely from regional energy provider portals.
- ⏱️ Live Countdown Timer — see exactly when power will go on/off.
- 📅 Multi-Day Schedule — detailed timeline for today and tomorrow.
- 🔢 Queue & Status Display — know your disconnection group and current status.
- 🔄 Smart Auto-Refresh — updates automatically with exponential backoff.
- 📴 Offline Support — Service Worker caches assets and last fetched data for offline viewing.
- 🔒 Stateless Token Auth — API uses server-side AES-256-GCM encryption to generate session tokens.
- 🛡️ No Database — your passwords are never stored on any external server or database.
- 🛑 Local Client Encryption — saved accounts in your browser are encrypted locally.
- 🚫 Rate Limiting — built-in protection against brute force and spam at the edge.
- ⚙️ Custom API Backend — deploy your own Cloudflare Worker for maximum privacy.
This app works only with the E-Svitlo platform (*.e-svitlo.com.ua).
| Region | Code | Operator | Status |
|---|---|---|---|
| 🏙️ Vinnytsia Oblast | vn |
Enera Vinnytsia | ✅ Supported |
| 🏛️ Kyiv Oblast | kv |
Local Networks | ✅ Supported |
| 🌻 Sumy Oblast | sm |
Enera Sumy | ✅ Supported |
| 🏰 Chernihiv Oblast | cn |
Enera Chernihiv | ✅ Supported |
| ⚙️ Dnipropetrovsk Oblast | dp |
CEK | ✅ Supported |
| 🌾 Luhansk Oblast | lg |
Enera Skhid | ✅ Supported |
| 🔌 Generic | ek |
Universal Entry | ✅ Supported |
(Note: DTEK/YASNO are currently not supported as they use different platforms).
To set up your own instance of EnergoMonitor, you need to deploy the API (Backend) and the UI (Frontend).
For a complete step-by-step guide (in English and Ukrainian), please see our detailed Deployment Guide.
- Deploy the Worker: Create a Cloudflare Worker using
worker/index.js. - Set Secret: Add a
WORKER_SECRETenvironment variable in Cloudflare (required for token encryption). - Update Frontend: In
frontend/index.html, update theDEFAULT_API_URLto your new Worker URL. - Host Frontend: Use GitHub Pages, Cloudflare Pages, or Vercel to host the
/frontenddirectory.
┌─────────────────────┐ ┌──────────────────────┐ ┌───────────────────┐
│ Frontend (PWA) │────▶│ Cloudflare Worker │────▶│ e-svitlo.com.ua │
│ Static HTML/JS │ │ (API Proxy) │ │ (Data Source) │
│ │ │ │ │ │
│ • Local encryption │ │ • Encrypted Tokens │ │ • Scrape HTML │
│ • localStorage │ │ • Session Auto-heal │ │ • Parse schedule │
│ • Service Worker │ │ • Rate limiting │ │ • Queue numbers │
│ • Offline cache │ │ • PII Stripping │ │ │
└─────────────────────┘ └──────────────────────┘ └───────────────────┘
│ │
│ ▼
│ ┌──────────────────┐
└─────────────────▶│ Cloudflare Edge │
│ Cache API │
│ • Sessions: 30m │
│ • Data: 30s │
└──────────────────┘
- User enters login details in the UI.
- The UI sends them to
/api/v1/login. - The Cloudflare Worker validates the login, creates a Stateless Encrypted Token (using your
WORKER_SECRET), and sends the token back to the UI. - The UI encrypts the Token locally (Web Crypto API) and saves it in
localStorage. - On refresh, the UI sends only the Token to
/api/v1/schedule. The Worker decrypts it in memory, fetches data, strips out all personal data (PII) (addresses, EIC codes), and returns clean schedules. - The Worker caches the data for 30 seconds to prevent DDoS. No passwords are ever saved to disk.
If you deploy the Worker, you get a fully functional REST API.
Health check endpoint. Returns API status, version, and supported regions.
Authenticates the user with the provider and issues a stateless token. Request Body:
{
"email": "user@example.com",
"password": "your_password",
"region": "vn"
}
Main endpoint for fetching outage data. Requires Token. Request Body:
{
"token": "U2FsdGVkX19...",
"force": false
}
Success Response (200 OK):
{
"provider": "esvitlo",
"queue": "4.2",
"message": "Офіційне повідомлення від обленерго",
"filia": "АТ «ВІННИЦЯОБЛЕНЕРГО»",
"disconnections": {
"planned": [
{
"acc_begin": "27-02-2026, 10:00",
"accend_plan": "27-02-2026, 16:00",
"typeid": "Виконання ремонтних робіт"
}
],
"current": [],
"gpv_schedule": [
{ "start_time": "08:00", "end_time": "12:00", "diff_time": "4 год. 00 хв." }
],
"gpv_tomorrow": [],
"date_tomorrow": "22.02.2026"
}
}
Destroys the session on the provider's side and clears the edge cache. Request Body:
{"token": "U2FsdGVkX19..."}
- API Error (503 "WORKER_SECRET not configured"): You must configure the
WORKER_SECRETenvironment variable in your Cloudflare Dashboard. See the Deployment Guide. - CORS Error: Ensure you updated the
DEFAULT_API_URLinindex.htmlto point to your Cloudflare Worker. Make sure the URL ends with a slash/. - "Invalid token" or Auth Error: Your session might have expired or the password changed. Try logging in again.
- Timer Frozen / Not Updating: Browsers throttle JS in background tabs. Bring the tab to the foreground or rely on the PWA standalone mode.
- Rate Limit (429): The API allows 5 logins per 5 minutes and 60 data fetches per minute. Wait a few minutes and try again.
- 🔔 Push Notifications — alerts before outages start.
- 🤖 Telegram Bot — get updates via Telegram.
- 🌐 i18n Support — Multi-language UI support.
- Fork the repository.
- Create a feature branch (
git checkout -b feature/amazing-feature). - Commit your changes (
git commit -m 'Add amazing feature'). - Push to the branch (
git push origin feature/amazing-feature). - Open a Pull Request.
This project is licensed under the MIT License.