Planenificator is a serverless, interactive Web Application and CLI-based flight planning and navigation log preparation tool designed for VFR (Visual Flight Rules) flights.
It allows pilots to plan their routes interactively on a map, overlay georeferenced ENAIRE VFR charts, fetch real-time weather forecasts to calculate headings and ground speeds, verify compliance with the semi-circular flight level rules, filter active NOTAMs to detect conflicts, and print a complete Operational Briefing package to PDF.
Live version available at https://mgmacias95.github.io/planenificator/
- 🗺️ Interactive Planning Map: Add, drag, or delete waypoints on an interactive Leaflet map.
- 📱 iPad-friendly planning: Use the large Add waypoint control and tap the map to place fixes; drag to pan and pinch to zoom. The interface adapts to portrait and landscape orientations and can be added to the iPad Home Screen.
- 🗺️ Warped VFR Chart Overlays: Georeference and display official ENAIRE VFR charts directly onto the map (supports Lambert Conformal Conic projections).
- ⚡ ENAIRE Live Catalog Downloader: Browse the active catalog of ENAIRE VFR charts, download them directly, and load them in-memory without uploading maps to GitHub.
- 💨 Dynamic Wind Calculations: Fetches forecasted wind direction and speed at specific altitudes along the flight path using the high-resolution ECMWF model (via Open-Meteo API).
- 📐 Wind Triangle Calculations: Resolves the exact wind correction angle (WCA) to compute Heading and Ground Speed (GS) for each leg.
- 📈 Climb & Descent Profile: Calculates Top of Climb (TOC) and Top of Descent (TOD) milestones dynamically, adjusting altitudes and speeds (e.g. Best Climb Vy vs. Cruise TAS) accordingly.
- 🛑 Semi-Circular Rule Verification: Alerts if flight levels/cruising altitudes do not comply with standard European semi-circular flight level rules.
⚠️ Smart NOTAM Conflict Checker:- Queries ENAIRE's official ArcGIS servers for active Spanish NOTAMs.
- Matches spatial coordinates (using a 2km safety corridor around the route).
- Checks departure, destination, and alternate aerodrome NOTAMs.
- Parses daily schedule windows (Item D/Item E) to filter out inactive NOTAMs based on your takeoff hour.
- Warns about active conflicts and appends nearby informational NOTAMs to the printed briefing.
- 🖨️ Printable Navigation Briefing: Exports a clean, formatted navigation log table, active conflicts warning header, and nearby NOTAM logs into a multi-page PDF briefing.
The web application is fully serverless and runs Python logic directly inside the browser using Pyodide (WebAssembly).
To run the Web UI locally:
- Clone the repository.
- Start a simple HTTP server in the repository root directory:
python -m http.server 8080
- Open your browser and navigate to http://localhost:8080/.
Since the app is purely static and client-side, you can host it directly on GitHub Pages:
- Enable GitHub Pages in your repository settings.
- Configure it to serve from the root of your repository.
- The
.nojekyllfile at the root ensures all Python package files are served correctly without Jekyll build errors.
For advanced users, a command-line script is also available.
Set up your virtual environment and install dependencies:
uv venv
source .venv/bin/activate
uv pip compile -r requirements.txt -r requirements-dev.txtpython main.py --kml=my_route.kml --dep LEBA --dest LEBA --alt LEDE --cruise-alt 5500 --tas 80 --datetime="2026-07-25 15:00"For information about available options run:
python main.py -hBelow is an example output generated by running:
python main.py --dep LEBA --dest LEBA --alt LEDE --cruise-alt 5500 --tas 80 --kml=my_route.kmlWARNING:root:Semi circular rule not followed for leg Villaviciosa de Córdoba (TOC) -> Espiel (true course: 48.843793, alt: 5500)
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Waypoint | True course | Heading | Wind | Altitude | TAS | GS | Leg | ETE | ETA |
+===========================+===============+===========+================+============+=======+======+=======+=========+=======+
| Castillo Almodovar | 268 | 260 | 181° / 9.8 kt | 2500 | 70 | 69 | 4 | 3m 29s | 11:32 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Posadas | 285 | 277 | 181° / 9.8 kt | 2500 | 70 | 72 | 1 | 0m 48s | 11:33 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| TOC | 285 | 275 | 188° / 13.2 kt | 5500 | 80 | 80 | 6 | 4m 33s | 11:37 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Hornachuelos | 37 | 42 | 188° / 13.2 kt | 5500 | 80 | 91 | 18 | 12m 04s | 11:49 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Villaviciosa de Cordoba | 92 | 102 | 196° / 14.1 kt | 5500 | 80 | 82 | 16 | 11m 27s | 12:01 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Embalse del Guadalmellato | 101 | 107 | 195° / 8.7 kt | 5500 | 80 | 80 | 15 | 11m 04s | 12:12 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Montoro | 179 | 180 | 197° / 5.9 kt | 5500 | 80 | 74 | 7 | 5m 54s | 12:18 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Bujalance | 213 | 212 | 197° / 5.9 kt | 5500 | 80 | 74 | 15 | 12m 26s | 12:30 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Espejo | 358 | 357 | 185° / 6.2 kt | 5500 | 80 | 86 | 10 | 7m 19s | 12:38 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| TOD | 358 | 357 | 185° / 6.2 kt | 2000 | 80 | 86 | 5 | 3m 49s | 12:41 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
| Total | | | | | | | 98.55 | 72m 53s | 12:41 |
+---------------------------+---------------+-----------+----------------+------------+-------+------+-------+---------+-------+
==================== NOTAM SECURITY NOTICE ====================
[WARNING] EN ROUTE CONFLICT WITH NOTAM V34285/26 (CERRO MURIANO)
Limits: FL0 - FL2500
Text: TEMPORARY SEGREGATED AREA FOR UAS FLYING ACT WI 380022N 0044541W, 380340N 0044858W, 380419N 0044815W, 380308N 0044311W, 380153N 0044458W, 380022N 0044541W CORDOBA/CERRO MURIANO RMK: THE ACTIVATION/DEACTIVATION OF THIS AREA WILL BE CARRIED OUT IN REAL TIME BY TACTICAL COORDINATION WITH ECAO (OPERATIVE AIR TRAFFIC SQUADRON) SEVILLA
[WARNING] DEPARTURE AERODROME (LEBA) CONFLICT WITH NOTAM V31704/26
Text: AERODROME CLOSED VFR OPS, EXC OPERATIONAL TFC: TUE: 0940-1010/ 1035-1055 THU: 1200-1230/ 1250-1310 SAT: 0935-1005/ 1030-1050 SUN: 1455-1525/ 1545-1605
[WARNING] DEPARTURE AERODROME (LEBA) CONFLICT WITH NOTAM V21643/26
Text: REF AD-2 LEBA: IAC 1 - RNP Z RWY 03 (LPV ONLY) NOT AVBL IAC 5 - RNP Z RWY 21 (LPV ONLY) NOT AVBL
============================================================================
Create paths using Google Earth and export them as kml. Pro tip: you can create overlays in Google Earth Pro to see the official VFR charts while creating your route plan.
Planenificator bundles and utilizes open geographic and aeronautical datasets for 100% offline flight planning:
- GeoNames: Spanish municipal and populated settlement gazetteer data is provided by GeoNames under the Creative Commons Attribution 4.0 International (CC BY 4.0) license.
- OurAirports: Spanish aerodrome, airstrip, and heliport data is sourced from OurAirports (Dedicated to the Public Domain / CC0).