Skip to content

Releases: munzzyy/hopandhaul

v0.7.0 — real boats, real numbers

Choose a tag to compare

@munzzyy munzzyy released this 09 Jul 20:24

Boats that exist, numbers that are real

The engine used to invent transportation when geography got wet: a Honolulu–Maui ferry (dead since 2009), trains from Finland to Tallinn straight across the Gulf of Finland, and one 40 km/h formula pricing every boat on Earth. v0.7.0 replaces all of that with real data — still zero keys.

Ferries are now a real mode

  • 85 researched passenger-ferry corridors ship with the app (data/ferries.json): actual terminals, operators, crossing times, sailings per day, and fare bands checked against operator/aggregator pages. Every entry cites its source and date.
  • A ferry leg only exists where a corridor does. Helsinki–Tallinn is Tallink/Viking from $14; Dar es Salaam–Zanzibar is the real Azam boat (and yes, that split gets recommended — it clears the $200 rule); Maui simply gets no ferry, because there isn't one.
  • A land/water grid (Natural Earth, 0.25°) plus a sea-gap detector stops land legs from crossing open sea. Calibrated against a 29-pair corpus so the Channel Tunnel keeps its trains and Barcelona–Valencia keeps its coastal rail while Turku–Tallinn loses its imaginary one.

Real numbers, keyless

  • Real ground timetables via Transitous — real operators, departures, and door-to-door times on train/bus/ferry legs, in the server and the static browser build. Fares on those legs stay labeled estimates; schedules are open data, ticket prices aren't.
  • US fares anchored to reality: a bundled extract of the BTS Consumer Airfare Report (public domain) with real average fares for ~4,100 US city-pair markets. The model gets clamped into each route's real band — thin expensive routes (Aspen, Jackson Hole) stop being underpriced — and the itinerary shows the real market numbers next to the estimate.
  • Place search and weather now work with no keys: Photon and Open-Meteo replace key-gated Geoapify/OpenWeather defaults (Geoapify stays as the keyed upgrade). Live FX for non-USD fares comes from frankfurter.dev with the old table as offline fallback.

One-command trips

hopandhaul go JFK "Tallinn" --date 2026-08-15

The full pipeline — direct vs splits, real ferries, anchored fares, live schedules, the $200 rule, leg-by-leg itinerary with provenance — in a terminal, zero keys.

Removed

  • The Amadeus flight fallback. Amadeus decommissions its entire self-service API portal on 2026-07-17; better removed deliberately than broken silently next week. Duffel remains the (optional) live-fare provider.

Gates

ruff clean · 12 module selftests · 57/57 Python↔JS parity cases (8 new: ferries, sea gaps, anchors) · both UIs verified in a headless browser · cold-verified end to end.

Data sources and licenses are listed in the README's new attribution section.

v0.6.0: the itinerary behind every price

Choose a tag to compare

@munzzyy munzzyy released this 09 Jul 17:18

Results used to end at a dollar figure with nothing behind it. Every option now opens into a leg-by-leg itinerary: the actual airports (code and name), an example clock schedule with airport-arrival and connection buffers, what each leg costs and where that number comes from, and a verify link per leg (Google Flights for air, Rome2Rio for ground) so you can check every number against reality before you book.

With DUFFEL_API_KEY set, flight legs upgrade to a real offer: real carrier, flight number, departure and arrival times, real price, tagged LIVE. Without a key everything stays labeled as an estimate. The tool never invents an airline or a departure time it doesn't have, and a day is only presented as fully real when every single leg came from a live offer.

The CLI also runs with zero keys now: python -m hopandhaul.duffel --from JFK --to ASE --date 2026-08-15 --auto-gateways prices with the same estimates as the map and prints full itineraries.

Itinerary strings are translated in all 46 locales. 287 self-test checks, 49/49 web-parity cases, and a cold line-by-line review before release.

Try it on the map · API docs

v0.5.0 — one map, in your language

Choose a tag to compare

@munzzyy munzzyy released this 08 Jul 17:39

One map. The map used to wrap infinitely and show several copies of the world when you panned — it's now bounded to a single world.

Place names translate. Continent and country labels on the map now follow the UI language across all 46 locales, drawn as their own labels over a clean base instead of tile text baked in English. Country names come from the browser's Intl.DisplayNames; continents from bundled CLDR data. No new dependencies.

v0.4.0 — Try it in your browser

Choose a tag to compare

@munzzyy munzzyy released this 08 Jul 02:10

hopandhaul now runs entirely in your browser. Open the map, click where you're starting from and where you're headed, and it works out whether flying into a cheaper airport and taking the train the rest of the way beats flying direct. No install, no server, no API keys.

The whole estimate engine (the $200 rule, group math, time budgets, CO2e) was ported from Python to JavaScript and runs on your own machine. A parity test in CI checks the JavaScript against the Python on every push, so the browser version can't quietly drift from the command line one.

Try it: https://munzzyy.github.io/hopandhaul/

The Python CLI and local server are unchanged. If you bring your own flight-price keys, running the server still gets you live fares instead of estimates.

Eight themes for the trip planner

Choose a tag to compare

@munzzyy munzzyy released this 07 Jul 20:25

Eight themes for the trip planner.

  • Theme picker in the header: Departure Board, Boarding Pass, Night Flight (OLED black), Terminal (CRT amber), High Contrast, Rail Poster, Old Map, and Coastal, plus Auto. Keyboard-first (arrows, Home/End, Escape), saved on-device, applied before first paint. Every theme clears WCAG AA contrast, checked with real math rather than by eye.
  • The map keeps up: tiles ride the light or dark base, and route colors redraw on every theme change - including a switch between two themes on the same base, which used to leave the old theme's line colors behind.
  • No new dependencies, no new external requests. The engine is untouched.

46 languages and a face-lift

Choose a tag to compare

@munzzyy munzzyy released this 06 Jul 02:31

Two big changes.

The UI now speaks 46 languages. Pick yours from the globe button. Arabic, Hebrew, Persian, and Urdu flip the whole layout right-to-left, map panels included. Detection follows your browser, your choice sticks, and a language whose catalog fails to load falls back to English instead of breaking. The runtime is a small hand-rolled module, not a framework.

The redesign that rode along: an own palette for dark and light, SVG icons instead of emoji, B612 Mono for the numbers that matter, themed map pins and tiles, and hand-drawn brand marks. Plus a batch of accessibility and correctness fixes from a line-by-line review of the frontend: results focus handling, listbox semantics, a language-switch race, CSP font and manifest directives, and token corruption on place names containing dollar signs.

Still zero runtime dependencies. The one vendored font is OFL-licensed and served same-origin.

Translation fixes from native speakers are the friendliest PR there is — see CONTRIBUTING.md.