Releases: munzzyy/hopandhaul
Release list
v0.7.0 — real boats, real numbers
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
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.
v0.5.0 — one map, in your language
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
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
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
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.