8.5 KiB
8.5 KiB
Changelog
v0.2.8 — 2026-09-16 23:53
data/airports_eu.csv: reduced the dataset to onlylarge_airportrows (dropped all 731 medium_airport + 54 seaplane_base) — the map now shows just the 260 biggest EU airports;/api/airportsand the circle layer pick it up with no code changese2e/map.spec.ts: marker-click test repointed from ESSV Visby Airport (a medium_airport, now removed) to UKBB Boryspil International Airport — with only large_airport rows left it is the most isolated marker inside the initial zoom-4 viewport: its nearest surviving airport is Chişinău (LUKK), ~126 px away at the initial zoom (Kyiv Zhuliany, geographically closer, was a medium and got cut)- Verified: unit suite 12/12;
tsc --noEmitclean; e2e suite 3/3 green against the rebuilt compose instance (/api/airportsserves 260 features)
v0.2.7 — 2026-09-16 23:39
data/airports_eu.csv: removed all 6400small_airportrows from the OurAirports EU export — the map now shows only the 1045 bigger airports (260 large + 731 medium + 54 seaplane_base);/api/airportsand the circle layer pick it up with no code changese2e/map.spec.ts: marker-click test repointed from EKRN Bornholm Airport (a small_airport, now removed) to ESSV Visby Airport on Gotland — its nearest remaining airport is Stockholm Skavsta across the Baltic Sea (~59 px away at the initial zoom), so its marker cannot be overlapped by a neighbouring circle- Verified: unit suite 12/12; e2e suite 3/3 green against the rebuilt compose instance (
/api/airportsserves 1045 features)
v0.2.6 — 2026-09-16 22:41
Dockerfile: install stages switched from npm to bun (oven/bun:1.4.2-alpine,bun install --frozen-lockfile);package-lock.jsonreplaced bybun.lock; no BuildKittype=cachemounts — they don't persist across builds on this daemon, and bun install is fast enough (~3 s cold) that cross-build caching isn't worth itDockerfile: newprod-depsstage (bun install --production) so the runtime image carries prod-onlynode_modules— devDeps (typescript, vitest, @types) are no longer shipped; build and runtime stages otherwise unchanged (still node:22-alpine, full.next, no standalone output).dockerignore: excludes docs/deployment files (*.md,Dockerfile*,docker-compose*) from the build context so changelog-only commits don't invalidate the COPY layer and re-runnext build- Verified: full cold build 77 s → 58 s; e2e suite 3/3 green against the rebuilt compose instance
v0.2.5 — 2026-09-16 21:22
AGENTS.md: new "E2E tests (mandatory)" section codifies the e2e workflow — the compose instance behind Traefik (https://flight.dev.kkhost.pl) is always the app under test, never a localnext devon :3000; deploy current code first withdocker compose up -d --build; browsers run through the shared remote Playwright server at192.168.1.4:3000, and plainnpx playwright testhandles deploy + readiness + remote connectplaywright.config.ts: dropped theE2E_LOCAL=1local-dev path accordingly — no more local :3000 dev instance for e2e; the default (and only) mode is browsers on the shared remote Playwright server against the prod build behind Traefik, withwebServerrunningdocker compose up -d --build;E2E_REMOTE=1and explicitPW_TEST_CONNECT_WS_ENDPOINT/E2E_BASE_URLoverrides are unchanged
v0.2.4 — 2026-09-16 21:06
playwright.config.ts: default e2e mode now targets the prod build behind Traefik (https://flight.dev.kkhost.pl) —baseURLdefaults to that URL andwebServerrunsdocker compose up -d --build(300 s timeout) instead ofnpm run dev, becausenext devdoes not render for non-loopback clients: Turbopack's HMR WebSocket fails from the remote browsers, so the page loads blankE2E_LOCAL=1keeps the local iteration path (browsers on this box,webServerauto-startsnpm run dev, baseURLlocalhost:3000) as a fallback when the proxy or compose stack is down;E2E_REMOTE=1and explicitPW_TEST_CONNECT_WS_ENDPOINT/E2E_BASE_URLoverrides are unchanged
v0.2.3 — 2026-09-16 20:30
playwright.config.ts: e2e now launches browsers on the shared remote Playwright server (Docker,ws://192.168.1.4:3000/) by default — when no env vars are set it exportsPW_TEST_CONNECT_WS_ENDPOINTpointing at that box; in this modebaseURLdefaults to this box's LAN IP (http://192.168.1.26:3000) because pages load from the remote browser's perspective, while the localwebServerstill auto-startsnpm run devE2E_LOCAL=1restores fully-local runs (browsers on this box,localhost:3000baseURL) as a fallback when the remote server is down;E2E_REMOTE=1keeps its previous behavior for runners on other machines — skipswebServerentirely and pairs withE2E_BASE_URL; an explicitPW_TEST_CONNECT_WS_ENDPOINTalways wins over the default
v0.2.2 — 2026-09-16 20:05
playwright.config.ts: e2e suite can now run on a different machine than the app — withE2E_REMOTE=1the localwebServerblock is skipped entirely andbaseURLdefaults tohttp://flight.dev.kkhost.pl;E2E_BASE_URLoverridesbaseURLin both modes; with no env vars set behavior is unchanged (localwebServerauto-startsnpm run dev)
v0.2.1 — 2026-09-16 19:49
- Clamp map zoom to the useful gameplay range:
minZoom: 3/maxZoom: 14on the MapLibre options incomponents/Map.tsx(exported asMIN_ZOOM/MAX_ZOOM) — wheel travel from the Europe overview is now ~10 levels instead of ~16, and street-level zoom past the z12 pitch transition no longer exists - e2e: new test that wheels well past both limits via
page.mouse.wheel(basemap tile fetches blocked for speed/determinism; clamping is pure camera behavior) and asserts viaexpect.pollon the map instance thatgetZoom()settles at 14 / 3, i.e. clamped within [3, 14]
v0.2.0 — 2026-09-16 18:32
- Docker deployment: multi-stage
Dockerfile(node:22-alpine; deps → build → runtime) runningnext starton port 3000; nooutput: 'standalone'— the runtime stage keeps fullnode_modulesbecause/api/mlworker/[file]reads maplibre-gl dist files from disk at runtime (and/api/airportsreadsdata/*.csv) .dockerignore: node_modules, .next, data/*.db, test-results, *.tsbuildinfo, plus .git/.env/.codenomad and the e2e harness (@playwright/testis a host-global install, not a project dependency — Next's build-time type check would fail on it inside the image)docker-compose.yml: single serviceflight, no published ports, joins external networkdev_netwith Traefik labels routingHost(flight.dev.kkhost.pl)→ port 3000 (plain HTTP entrypointweb; TLS terminated upstream)- Verified: container builds and runs; router registered in dev_traefik rawdata;
curl -H "Host: flight.dev.kkhost.pl" http://localhost/→ 200,/api/airports→ 200 GeoJSON (7445 features), mlworker .mjs files served from node_modules inside the container; unit suite 12/12 and e2e suite 2/2 still green
v0.1.0 — 2026-09-16 18:24
- Scaffolded Next.js (App Router) + TypeScript project; dev server on port 3000 (
npm run dev) - Full-viewport MapLibre GL map with OpenFreeMap "liberty" vector basemap (attribution included via style)
- Zoom-driven camera controller: top-down at zoom ≤ 6, smoothstep tilt to 45° pitch by zoom ≥ 12; pitch is a pure function of zoom so it never fights pan/zoom gestures
- Lite 3D terrain from AWS terrarium raster-DEM tiles (
map.setTerrain); toggleable off via?terrain=0orNEXT_PUBLIC_TERRAIN=0(off in e2e for deterministic headless rendering) - EU airport seed data: OurAirports CSV (official mirror at davidmegginson.github.io/ourairports-data — the legacy ourairports.com/data URL now 404s) filtered to continent=EU with types small/medium/large_airport + seaplane_base → committed as
data/airports_eu.csv(7445 airports; heliports, closed and balloon sites excluded — rationale documented inlib/airports.ts) GET /api/airports: server-side CSV parse with in-memory cache, returns GeoJSON FeatureCollection (properties: name, icao, lat, lon)- Client renders airports as a GeoJSON circle layer (no DOM markers); click → popup with name + ICAO; header shows loaded airport count (
data-testid="airport-count") - MapLibre worker served from node_modules via
/api/mlworker/*route — bundlers break the URL MapLibre derives for its worker, which silently hangs GeoJSON source updates - Tests: vitest unit suite (CSV parse/filter, GeoJSON build, pitch curve, API handler) + self-contained Playwright e2e suite (
webServerauto-startsnpm run dev; page load + airport count + marker click popup)