Repository navigation
Releases
Rail extracts rail-data-2026-11-02
Rail, ferry and bus OSM extracts built by .github/workflows/rail-extract.yml from Geofabrik country extracts. Coverage, checksums and per-region, per-layer source dates are in manifest.json.
Val
What's Changed
- fix(client): defer the elevation-track rebuild while panning by @rui-nar in #279
- fix(release): keep release notes in one language by @rui-nar in #282
- fix(segments): report why a train route could not be resolved (#277) by @rui-nar in #280
- fix: give ProjectNotifier a real same-ref load-supersession token by @rui-nar in #284
- fix(server): resolve train routes through MOTIS/Transitous, not dead HAFAS APIs (#277) by @rui-nar in #281
- fix: bound route-track points in the editor and on PUT /track by @rui-nar in #285
- chore(graphify): refresh the code graph after the train-route work by @rui-nar in #287
- fix: replace ProjectNotifier's 3 hand-rolled supersession counters with one primitive by @rui-nar in #288
- fix(server): try the next working when a line number's first match misses by @rui-nar in #289
- chore(graphify): refresh the code graph after the #286 candidate scan by @rui-nar in #290
- perf(map): audit + Phase 0/1 — decode heavy payloads off the UI isolate by @rui-nar in #297
Full Changelog: v0.48.0...validation
TraxJourney v0.53.1
TraxJourney v0.53.1
10 changes since v0.53.0
🐛 Fixed
- Map — Zooming out and back in on the map no longer leaves frozen copies of your trip's markers on screen.
- Map — keep a marker mounted when its visible copy changes world.
- Map — keep the plain marker key on the copy already on screen.
- Map — key a marker's extra world copies by offset, not world index.
- Strava — bind Strava connect to the client that started it (client).
- Strava — bind Strava connect to the client that started it.
- Strava — finish a web Strava connect even after leaving Settings.
- Strava — bind each Strava code to the state it arrived with.
- Strava — return to the app after approving Strava on Android.
- Strava — ignore a replayed Strava return on Android.
⚠️ Upgrade notes
- Reviews — Connecting Strava needs this version of the Android app; older versions show an error on Connect. Accounts already connected keep working.
Internal changes (12)
- plan for binding Strava connect to the starting client
- fold round-1 review into the Strava connect plan
- Strava connect plan round 2
- fold R2-1 (owner override) into the Strava connect plan
- record U2 unit review
- amend Strava connect plan after the U1 unit review
- record accepted D9 residual risk and U1 fix outcomes
- narrow the hostile-app boundary (owner decision on U1R2-1)
- link follow-up #584
- U4 for I1-1 (owner override), ledger round for the integrated diff
- Strava connect binding delivery record
- refresh the code graph after #585
Full changelog: v0.53.0...v0.53.1
TraxJourney v0.53.0
TraxJourney v0.53.0
142 changes since v0.52.0
🚀 New
In the app
- Web app — You can now import a trip ZIP archive, photos included, from the same Import button as a .traxj file.
- Web app — name both import formats in the picker text.
- Web app — Importing a large trip archive no longer loads the whole file into the app's memory, and a file over the size limit is refused as soon as you pick it.
- GPX import — Activities imported from a GPX file now show the local time where they were recorded, and keep the time zone of the place they started.
- GPX import — On Android, a GPX file can be opened in TraxJourney from the share menu or "Open with", and imported into a trip of your choice. (#368)
- GPX import — A trip's GPX export now holds one track per activity, with its name, type and real start and end times, so other apps (and TraxJourney) see each activity separately. Train, flight and other connections are separate tracks too. (#367)
- Gpx-Import — The GPX import review shows times in the local time where the track was recorded, and can import every track of a file at once.
- GPX import — A GPX file with several tracks, such as a TraxJourney export, can be imported as separate activities in one go, and an exported Strava activity keeps its distance and moving time when imported back.
- Map — Server-Timing on the simplified geometry endpoints.
- Web app — block builds below the server's minimum version.
- Perf — split each simplified geo fetch into server time and wait.
- Day-Meta — Day notes and tags now save only the days you changed, so editing on one device can no longer overwrite another device's notes on other days.
- Encryption — With end-to-end encryption on, a device that is locked or awaiting approval can no longer save memories or journal entries unencrypted, and a travel companion's encrypted memories no longer end up unreadable for the rest of the trip; the save is refused instead. An invite link created before the trip owner turned on encryption can no longer be used to join.
- Photos — add rank placement helpers for photo order.
- Encryption — confirm or replace an unconfirmed recovery key.
- Posters — Posters of an encrypted trip now ask before sending your memory text to the server, and finished posters are deleted from the server 30 days after they were made.
- Encryption — With end-to-end encryption on, your Strava activity list is no longer saved on the server's disk while you pick activities; it is kept only in memory for up to an hour.
- Encryption — If you turned on encryption with a recovery key and never confirmed you saved it, the app now offers to create a new one.
- Photos — Photos already uploaded sideways get their thumbnails turned upright by a one-time maintenance step.
- Crypto — With encryption on, a device that hasn't unlocked your key (or is still waiting for approval) now says so on the trip screen and no longer saves memories or journal entries unencrypted; memories you add to someone else's trip stay readable by the other travellers, and Polarsteps imports into your own trips are encrypted.
- Web app — Dart port of the server's track maths, pinned by Python vectors.
- Posters — Generating a poster for an end-to-end encrypted trip now asks before sending your memories' titles and notes to the server, and lets you make the poster without that text.
- Encryption — With encryption on, everything added to your trips after you turned it on (Strava and GPX activities, split pieces, imported trips, Polarsteps memories) is now encrypted the next time you open the trip on an unlocked device, and memories you wrote on a friend's unencrypted trip become readable to the other travellers again.
- Crypto — Encrypted trips now show corrected elevation gain for edited and GPX-imported activities, and elevation charts no longer dive to sea level where the recording had gaps.
- Web app — With encryption on, you can again trim, split and reset activity tracks: the edit happens on your device and the track stays encrypted on the server. The trip screen also tells you how many activities imported by another traveller could not be encrypted.
- Trips — Editing a trip no longer reloads the whole map at full detail.
Server & deployment
- Project — add StagedPhoto / StagedPhotos type. (#469)
- Export — A trip's ZIP download now holds the complete trip (people, day notes, sleeping options and trip settings) and your journal photos, not only its memories and their photos. Large ZIP downloads use less server memory.
- Import — Importing a trip file no longer leaves broken photos on its memories and journal entries: photos whose image isn't there are left out, and a replaced trip keeps the photos it already had.
- Import — shared photo processing and a safe ZIP stager (#469 U3).
- Import — Trips exported as a ZIP can now be imported back, photos included, within your storage allowance. Only one trip import runs at a time; a second one is asked to try again in a minute. (#469)
- Day-Meta — Day notes, tags and counters edited on two devices no longer overwrite each other: each save now only changes the days you edited.
- API — serve min_client_version on /api/version.
- Jobs — log route jobs stuck pending or running for 30 minutes.
- API — ApiClient.patch.
- Database — photo_order_json column, dense photos_json, AUTOINCREMENT memory/journal ids.
- Monitoring — count Overpass requests by purpose and route resolves by source.
- Rail — route corpus and its runner.
- Activities — Resetting an edited activity now restores its original distance, times, speed and elevation figures exactly. Encrypted activities can be trimmed, split and reset again once the app update that edits them on your device ships.
- Rail — daily check exports the local rail data's age.
- Rail — the box refreshes its rail data monthly.
- Rail — stores and readers learn layers (store schema 3).
- Activities — has_gain_snapshot in the trip payload.
- Rail — filter ferry and bus layers in the extract build.
- Activities — compare-and-swap on a friend's trip the caller edits.
- Rail — ferry and bus extracts keep only the tags the builder reads.
- Rail — ferry and bus stores know where their relations' stops are.
- Rail — ferry and bus resolve from local stores first.
- Rail — ferry and bus legs in the route corpus, gated in CI.
- Rail — publish only the layers RAIL_PUBLISH_LAYERS names.
🐛 Fixed
In the app
- Strava — Connecting Strava no longer puts your sign-in session in the link sent to Strava.
- Sign-in — Deleting your account now also removes your Immich connection and your poster, video and route jobs.
- Strava — If you take more than 10 minutes to approve TraxJourney on Strava, the error now says the link expired so you know to try again.
- Sign-in — Your Strava, Polarsteps and Immich connection credentials are now stored encrypted. Self-hosted instances must set the new CREDENTIALS_ENCRYPTION_KEY variable (see .env.example) before upgrading.
- Sign-in — log Google sign-in failures without the token.
- People & encounters — Profile photos of people you met, added by a travel companion, now show for everyone on the trip and count towards the trip owner's storage.
- Strava — Fetching activity tracks from Strava no longer leaves you needing to reconnect Strava after its access expires, and disconnecting Strava during a track fetch now fully revokes the app's access.
- People & encounters — warn about stray files left in an avatar folder.
- People & encounters — Profile photos of people met on a trip that a travel companion added now show for every member of the trip, and count towards the trip owner's storage.
- People & encounters — Old copies of replaced or removed profile photos that were left in a travel companion's storage are now cleaned up, freeing that space.
- Companions — Other people on a shared trip no longer see your email address when you haven't set a name; they see "Traveller" instead. Your display name can no longer be saved empty.
- People & encounters — Photos of deleted people that were still taking up a travel companion's storage are now cleaned up.
- Sharing — Shared trip pages, comments, likes and the visitors list no longer show someone's email address when they haven't set a name; they show "Traveller" instead.
- People & encounters — Old profile photo copies still counted against someone who left a shared trip are now cleaned up.
- A11Y — Screen readers now announce an imported activity's name first, and "Imported from a GPX file" last.
- People & encounters — Old copies of replaced profile photos left in a trip owner's storage are now cleaned up, freeing that space.
- Activities — Deleting a piece of a split activity that belongs to another trip member now tells you only its owner or the trip owner can delete it, instead of silently putting it back.
- GPX import — fall back to the tzdata package and skip rejected candidates.
- GPX import — Connecting segments in a TraxJourney GPX export can no longer be imported as activities.
- GPX import — Importing a TraxJourney GPX export back into the same trip no longer duplicates its activities.
- Map — Turning on auto-zoom now zooms the map to whatever you already have selected, instead of waiting for your next selection.
- Web app — Importing a GPX file keeps the activity type you pick, and sharing a GPX file to the app no longer briefly claims you have no trip.
- GPX import — Importing a TraxJourney GPX export back into the same trip no longe...
Rail extracts rail-data-2026-10-05
Rail-only OSM extracts built by .github/workflows/rail-extract.yml from Geofabrik country extracts. Coverage, checksums and per-region source dates are in manifest.json.
TraxJourney v0.52.0
TraxJourney v0.52.0
155 changes since v0.51.0
🚀 New
In the app
- Licence, privacy & terms — TraxJourney is now officially open source under the GNU AGPL v3. Settings > About links to the source code.
- Licence, privacy & terms — TraxJourney now publishes its privacy policy and terms of service at traxjourney.com/privacy and traxjourney.com/terms.
- Licence, privacy & terms — The sign-in, sign-up and Settings screens and the home page footer now link to the privacy policy and terms of service.
- Web app — Importing a trip under a name you already use now asks whether to keep both trips or replace the existing one. (#452)
- App — The plan page has a "Withdraw and get a refund" button during the first 14 days after your first purchase. It shows the refund before you confirm. (#441)
- Video — You can now turn a trip into an animated video (30, 60 or 90 seconds) from the trip's export menu, follow its progress on the map and download it, or open the link from the ready email even when signed out. Encrypted trips ask for your consent before their tracks are used.
- Video — When you create a trip video you can now choose how the camera moves: Variable (zooms to follow each leg), Overview (the whole trip stays in view) or Fixed zoom, with an option to zoom out for flights and long legs. (#518)
- Video — The trip video dialog has a Preview button that shows a quick low-resolution animation of your video, with the camera and length you chose, before you render it. Previews don't count toward your monthly videos. (#519)
Server & deployment
- Monitoring — log once when /metrics skips a gauge left by an older mode. (#437)
- Import — When importing a trip whose name you already use, you can now replace that trip with the file: its share links and companions stay. Journal entries in an imported trip file are now imported with their text instead of turning into an empty flight. (#452)
- Plans & billing — Within 14 days of your first purchase you can withdraw from your paid plan and get back the unused part of the period you paid for. Deleting your account within those 14 days refunds it too. (#441)
- Jobs — add the video queue, its worker service and ffmpeg in the image.
- Plans & billing — Each plan now lists how many trip videos it includes per month and at which resolution.
- Video — legs, clips, pacing and timeline for trip videos.
- Video — add error_message to the videojob table.
- Video — video API, job runner, sweeps and emails.
- Video — add the deterministic follow camera.
- Video — render trip videos to MP4 from banded basemaps.
- Video — add overview and fixed-zoom camera paths.
- Video — none (server-internal profiling tooling; no user-facing change).
- Video — Trip videos are encoded at a higher quality, so the route line and map labels look sharper; video files are about 1.5 times larger.
- Video — Trip videos draw the route line, the transport icons and the info panels with smooth edges instead of jagged pixels, and the transport icons now match the ones in the app.
- Video — add a preview kind to video jobs outside the monthly quota.
- Video — render trip video previews as animated WebP (#519 U2).
- Video — preview jobs with an hourly rate limit (#519 U3).
- Video — add bench --profile for CPU-stage profiling (U3, #517).
- Video — tile prefetcher and the plan's request order. (#517)
- Video — log render setup time in the render summary.
🐛 Fixed
In the app
- Sign-in — the access-log middleware no longer warns about non-JWT bearer tokens.
- Sign-in — the quiet JWT decode also swallows an unusable key.
- Web app — show "too large" for a 413 on trip import, even from a proxy. (#434)
- Photos — keep stored photo names inside the owner's folder.
- Posters — only use memories that belong to the trip.
- Sharing — serve only photos of the shared trip.
- Plans & billing — Paid plans no longer list backups or priority support, and the hosted plan on the home page no longer promises backups, priority support, custom share domains or background Strava sync. None of these was actually provided. (#432)
- Web app — Web app files are now served only from the web build folder.
- Sharing — read share tiles only from the tile cache directory.
- Posters — read memory photos without creating their folder.
- Web app — warn that replace removes photos, and ask again on a second conflict. (#452)
- Web app — say replace deletes missing people, and test the screen's import flow. (#452)
- Import — give people created from a file no avatar name. (#452)
- Home page — The home page now shows the real starting price of the hosted plans, taken from the current plan list, and no longer claims the hosted service includes everything self-hosting does. (#432)
- Photos — fetch photos from a URL only from public addresses.
- Immich — connect only to public Immich servers unless the operator allows the host.
- App — Before you delete your account, the app now tells you that your paid plan will be cancelled immediately. If the deletion is refused, the reason stays on screen until you dismiss it.
- App — The admin panel now explains why deleting a user was refused, and the Delete my account button shows it is working instead of looking unresponsive.
- App — After deleting your account, the app no longer shows a spurious "Account not deleted" message when tidying up this device fails.
- Sign-in — refuse an unusable JWT_SECRET at startup. (#453)
- Sign-in — say why PyJWT refuses a JWT_SECRET, not just that it looks like a key. (#453)
- App — The admin panel now shows the full reason when deleting a user is refused, instead of a message cut off mid-sentence.
- App — The plan page now shows the last day you can withdraw, and counts it from when your current subscription started. (#441)
- App — After withdrawing, the plan page tells you if part of your refund could not be made automatically and will be refunded to you separately. (#441)
- App — Before you withdraw, the plan page tells you if part of the refund cannot go back to your card and will be refunded to you separately. (#441)
- Import — A GPX file with a wrong timestamp (such as a point dated 1970) now imports with its moving time intact, and the import preview warns about the odd dates so they can be corrected before importing. (#462, #491)
- Web app — Encrypted memories, journal entries and activity names that this device cannot decrypt now show as "Encrypted content unavailable" instead of unreadable text. (#466)
- Web app — Editing an encrypted memory or journal entry on a device that cannot decrypt it no longer shows unreadable text; the encrypted text is kept as it was, and the other details can still be changed. (#466)
- Web app — encrypt every typed value; resend only the editor's untouched envelope. (#466)
- Web app — decide which field is kept as stored from what reveal could not decrypt. (#466)
- Trips — Creating or renaming a trip at the same moment as another save that takes the same name now tells you the name is already in use, instead of failing with a server error. (#467)
- Settings — Renaming a trip to a name you already use now tells you so and keeps the settings open, instead of closing as if the rename had worked. (#467)
- Settings — prune a copy of the day-meta, not the screen's own (#467, fixes R1-1).
- Video — send real encrypted tracks for consent; keep the create request alive.
- Video — refuse early when no video worker listens or no video is left.
- Sharing — Share-link visitor stats no longer show trip owners the email address of people who opened the link while signed in — only their display name and avatar.
- Sharing — make the visitor_key test deterministic, temper the docstring.
- Sharing — Photos viewed through a share link no longer carry the location, capture time or camera details embedded in the original file. Your own photos are unchanged.
- Sharing — strip thumbnail comments, harden the share-copy lifecycle, share stripped photos from the app.
- Sharing — serve the stripped copy to the app signed in, remove share copies on import-replace.
- Strava — TraxJourney no longer keeps heart-rate data from your Strava activities. Heart-rate values that earlier imports had stored are deleted when the server updates, and they no longer appear in trip exports o...
TraxJourney v0.51.0
TraxJourney v0.51.0
51 changes since v0.50.0
✨ Highlights
Importing a GPX file now starts with a preview of the track — drawn on the map, with its name, distance, climb, date and activity type already filled in from the file — so you confirm rather than retype, and files with several tracks, duplicate tracks or dates outside the trip are handled before anything is added; routes planned in Komoot, RideWithGPS and Garmin can now be imported too, and imported activities carry a GPX badge you can filter by. Opening the map of a large or older trip is much faster the first time, and saved filters and selections now survive reopening a shared trip instead of being overwritten by another trip or account in the same browser. The app is also now called TraxJourney throughout, and project backups are saved as .traxj files — older .viewtrip files can no longer be imported.
🚀 New
In the app
- GPX import — Importing the same GPX file into a trip twice is now refused, naming the activity that already has that track, instead of silently adding a second copy of it. (#260)
- GPX import — Routes planned in Komoot, RideWithGPS and similar tools can now be imported. Imported files also fill in their own date, time, name and activity type where they have them, instead of asking you to type them again, and the moving time no longer counts the stops. (#260)
- GPX import — Importing a GPX file now shows you what is in it first — the track's name, distance, climb and when it happened — with everything filled in from the file, so you confirm instead of typing it all in. Files holding several tracks let you pick one, and a track already in the trip is flagged before you add it twice. (#260)
- GPX import — Importing a GPX file now shows you the track first — drawn, with its distance, climb and timing — and fills in its name, type, date and times from the file itself, so you confirm instead of typing. Files with several tracks let you pick; a track already in the trip is flagged before you add it twice; and a date outside the trip warns you rather than quietly extending it. (#260)
- GPX import — The GPX badge now says what it means — hover it, or ask a screen reader, and it reads "Imported from a GPX file". Imported tracks carry the same badge in the track editor, and a trip holding both synced and imported activities can now be filtered by where they came from. (#260)
- Trip stats — ask the terrain whether there was a hill there at all. (#386)
- Trips — Project backups are now saved as .traxj files, and older .viewtrip files can no longer be imported.
- Brand — The app is now called TraxJourney everywhere, including the browser tab, the installed app's home-screen name and the sign-in screen.
Server & deployment
- API — The project file export endpoint is now GET /api/projects/{name}/export-traxj; /export-viewtrip is gone.
- Brand — Emails and exported GPX files now say TraxJourney.
- Database — Self-hosting: when DATABASE_URL is not set, the database file is now traxjourney.db. The server refuses to start next to an old viewtripweb.db until you rename it (with its -wal/-shm files and backups) or set DATABASE_URL.
🐛 Fixed
In the app
- Map — give every vertex the zoom level that keeps it (#369 stage A).
- Map — stop vertex_levels walking a collinear run one point at a time.
- Trips — Editing a day's notes while a Strava sync or GPX import is running no longer loses the edit. (#391)
- GPX import — Deleting or editing an activity imported from a GPX file now works in the browser. The identifier those activities were given was too large for the web app to carry exactly, so the app asked the server about an activity that did not exist. (#260)
- Map — Opening a large trip's map is much faster the first time, and no longer slows down other requests while it loads.
- Map — guard the read-path write-back, and re-parent the migration.
- GPX import — Imported files fill in their own date, time, name and activity type where they have them, instead of asking you to type them again. Moving time excludes the stops — including on phones that keep recording while you stand still — and routes planned in Komoot, RideWithGPS or Garmin are recognised. (#260)
- GPX import — get the parse off the event loop, and fingerprint the file not the form. (#260)
- Trips — Deleting a memory, journal entry or encounter while another device is editing the same trip no longer leaves the trip in an inconsistent state, and adding or editing a transport segment no longer fails with "this trip changed elsewhere" when a background route lookup finishes at the same moment. (#399)
- GPX import — Importing a GPX file keeps the times the file recorded instead of shifting them by your timezone, and an activity that runs past midnight can now be imported. If the server cannot be reached the dialog says so and lets you close it. (#260)
- GPX import — don't let a source filter outlive the chip that clears it. (#260)
- GPX import — a source filter is escapable whichever source it names. (#260)
- GPX import — pruning a stale filter must not cost the user their selection. (#260)
- Trip stats — measure the sensor's noise, not the spliced series'. (#386)
- Trip stats — stop claiming a margin three seeds out of five do not have. (#386)
- Trip stats — sweep the model's error properly, and stop misnaming the loss. (#386)
- Map — prepare a cold trip once, however many requests ask at the same time (#369 stage C).
- Filters — A saved filter on an activity type, transport, tag or sleeping mode that no longer matches anything in the trip is now dropped, instead of leaving the trip empty with no way to untick it other than "Clear all". (#409)
- Map — Older trips now load their map quickly the first time too, not only trips added or edited since the last update.
- Track editor — On a phone, the track editor now shows which activity you are editing: "Reset to Strava" / "Reset track" moved into the menu at the top right, which had been pushing the activity name out of the title bar. (#407)
- Track editor — On a phone, the track editor's title bar now shows the activity's name on its own, so more of it fits. (#407)
- Map — stop unpreparable rows starving the backfill sweep.
- Filters — a shared trip's saved state is not your trip's to prune. (#409)
- Track editor — The track editor no longer lets a split go out while a save is still in progress, and pressing Back while a save is finishing no longer closes the screen behind the editor as well. (#407)
- Track editor — a Reset picked after the window widens still resets. (#407)
- Map — the backfill cursor skipped every app-created activity.
- Filters — Viewers and co-owners of a shared trip now get their selection and filters back when they reopen it, and opening a share link, a companion's trip with the same name, or another account on the same browser no longer overwrites the filters and selection saved for your own trip. (#409)
- Map — make a stuck backfill sweep visible without flooding the log.
- Track editor — While a track edit is being saved, Split and Cut are greyed out in the point menu. (#407)
- Filters — a load never keeps the last account's filter, and the old key moves once. (#409)
- Filters — keep a same-trip reload's filter, and delete the old key only after a confirmed write. (#409)
- Filters — delete the old UI-state key only by claiming it. (#409)
- Trips — the import picker refuses files that aren't .traxj.
Server & deployment
- Activities — keep _write_track_geometry callable without a session.
- Server — Saving or editing something no longer occasionally fails with a "502 Bad Gateway" error that went away on retry. (#400)
- Activities — scope a local-activity delete to the project it names. (#405)
- Bench — make the model-error fixture reproducible, and mean one thing. (#386)
- API — An outdated app asking the server for something that no longer exists now gets a clear error, instead of silently saving a web page in place of your data (for example a trip backup).
- API — Importing a project now only accepts .traxj files and s...
ViewTripWeb v0.50.0
ViewTripWeb v0.50.0
20 changes since v0.49.0
🚀 New
In the app
- Sharing — Public and shared trip links now load only as much map detail as the current zoom can show, instead of the whole trip at full resolution — far less data to download and far less memory held, which is the difference between a long trip opening on a phone and not. (#321)
Server & deployment
- Rail — Train routes drawn by an older version of the route finder are now redrawn quietly in the background, so an improvement to how routes are traced reaches trips you already planned instead of only new ones. A few are redone per hour rather than all at once, and routes you edited by hand are never touched. (#364)
🐛 Fixed
In the app
- Web app — Importing a trip's photos no longer saturates the connection. While the photos download in the background, the app now checks for them with a small request instead of re-downloading the entire trip every three seconds — on a long trip that was tens of megabytes a time, for three minutes. (#308)
- Trip stats — Climb totals on hand-edited activities and GPX imports were counting GPS wobble as ascent, sometimes several times over, while hills on imported planned routes could vanish entirely. Both are fixed, and existing trips are corrected when the server next starts. (#260)
- Settings — Setting a trip end date now really removes the days after it — they used to reappear right after you confirmed. The warning also tells you when a later day has an activity or a memory on it and will stay put. (#358, #362)
- Web app — Offline maps keep their detailed tracks again. A trip you have opened once on a device now keeps its full-detail route for the next time you open it without a connection. Exported and shared images are drawn from that full-detail route too, so a single-day export no longer comes out angular. (#317)
- Days — A day whose only content is a journal entry, an encounter or a segment now shows up in the day strip, is offered by the add button and counts towards the trip's day numbering. The day list already showed it, but the rest of the app behaved as though the day were not there. (#370)
- Map — Zooming into a shared trip, or into a trip someone shared with you, now brings the finer map detail it asks the server for instead of leaving the track as coarse as it first loaded. (#321)
- Settings — Moving a shared trip's end date earlier no longer deletes the notes, tags and sleeping entry of a day one of your travel companions has a journal entry on — those days stay, and the warning now says so. If the app cannot reach the server to check, it keeps every day past the new end date rather than deleting any. (#372)
- Trip stats — Climb totals are more accurate on tracks that are recorded sparsely, or whose altitude readings update more slowly than their position — flat ground on those could previously be reported as hundreds of metres of climbing. Gentle rolling terrain on imported routes is also counted properly instead of being flattened away. (#376)
- GPX import — Activities imported from a GPX file with some points missing elevation no longer show a drop to sea level on the elevation chart, and their total climb is no longer overstated. Existing activities are corrected automatically. (#374)
- Sharing — Renaming a trip no longer breaks its shared link. Visitors could briefly get an error, or be sent the full-detail map instead of the lighter one built for their zoom level, for about a minute after a rename. (#321)
- Trip stats — Editing or splitting an activity no longer rewrites how much climb it had. The figure your tracking app recorded is kept, split proportionally between the pieces, and restored in full if you reset the track. (#386)
Server & deployment
- Rail — Train routes now start and end at the right station. Some legs were drawn from a point several kilometres away — Paris Gare de l'Est to Strasbourg began 14 km south of the city — because the map data's platform outlines were being mistaken for track. (#359)
- Rail — Train routes now start at the station rather than at the edge of town where the map data leaves a gap. Paris Montparnasse to Bordeaux began 3.5 kilometres out, on the ring line south of the station. Nantes to Rennes is also drawn along the direct line it runs on instead of a detour via Le Mans. (#363)
- Day-Meta — On a shared trip, the notes on a day can no longer be deleted by someone whose app cannot see what is still keeping that day in the trip. (#387, #388)
⚠️ Upgrade notes
- Rail — Rail data must be refreshed after this release — run
scripts/fetch_rail_data.py --dest /app/data/railon the box. It rebuilds all regions rather than skipping them, since the store format changed while the published extracts did not. There is no window to plan around: the reader serves the existing stores until each is replaced.
Internal changes (7)
- judge the elevation sentinel per run, not by the median (#374)
- detect the elevation sentinel by grade, not by altitude (#374)
- adversarial-review follow-ups to #370/#372 (#384)
- refresh the code graph after the #359 fix
- cover the candidate day a only the server can see
- refresh the code graph after the #308/#317/#321 wave
- pin elevation gain against the classes it keeps breaking
Full changelog: v0.49.0...v0.50.0
ViewTripWeb v0.49.0
ViewTripWeb v0.49.0
75 changes since v0.48.0
✨ Highlights
Opening, panning and zooming the map on long trips is much faster and no longer freezes or stalls: the app now downloads only the track detail and the area you are actually looking at, fetches elevation data separately and compactly, and uses far less memory — including on trips with many photo memories and on shared public trip links. Train, ferry and bus segments resolve properly again too, drawing their real route in seconds instead of a straight line; entering just the train number is now enough (the operator picker is gone, since numbers are looked up across every supported railway at once), regional lines like RE1 and RE8 are found, late-evening departures are matched to the right day, and when a train genuinely cannot be found the app says so and shows the operator's reason instead of quietly reporting an approximate route. Alongside that, Settings has a new Performance section showing where your last trip spent its loading time — with a button to copy the details into a bug report — version numbers now show the server's version next to the app's, deleting several segments at once no longer silently fails, and tapping an activity on the map moves the day strip to the matching day.
🚀 New
In the app
- Web app — Settings now has a Performance section showing where the last trip you opened spent its loading time, with a button to copy the details into a bug report. (#291)
- Web app — Settings can now switch how the map draws its background tiles, and reports how smoothly the map ran while you were panning. (#276)
- Perf — measure whether the freeze is GC, before assuming it is. (#276)
- Perf — count the structures, so 1.5 GB stops being a guess. (#276)
- Web app — Maps on long trips use far less memory: the app now downloads track detail matched to how far you are zoomed in, and asks for more as you zoom. (#295)
- Web app — Wherever the app shows a version number — the splash screen, the sign-in and welcome pages, project settings and Settings > About — it now shows the server's version next to the app's, so a bug report can name both. If the server cannot be reached the line says "server unknown" rather than going blank. (#275)
Server & deployment
- API — compact elevation endpoint, and what it revealed about the scope. (#295)
- API — zoom level of detail for map geometry. (#295)
- Rail — local per-region rail store, builder and reader. (#345)
- Rail — report relation members the extract does not hold. (#345)
- Rail — read route geometry from local region stores, behind a source interface.
- Install the published rail data onto the box. (#345)
🐛 Fixed
In the app
- Web app — Fixed the app freeze (ANR) that could still happen when panning the map right as the elevation chart finished loading, including on shared/public trip links.
- Segments — When a train can't be found with its operator, the app now says so plainly — and shows the reason the operator gave — instead of only reporting an "approximate route". Those segments are also retried automatically rather than being stuck on a wrong line for good. (#277)
- Web app — close staleness gaps in the async _buildFullTrack rebuild.
- Web app — Fixes two more rare situations where switching trips quickly after opening a large trip could leave the loading indicator stuck.
- Web app — The Operator picker has been removed from train segments. Choosing an operator no longer had any effect — train numbers are looked up across every supported railway at once.
- Fixed rare cases where quickly reloading or retrying a trip (e.g. tapping Retry more than once) could leave the map or activity list showing stale or inconsistent data.
- Editing the track of a long route no longer bogs down the map — vertex handles are thinned when the whole route is on screen, and zooming in brings back every point in view.
- Address adversarial-review findings on the #283 supersession fix.
- Replace ProjectNotifier's 3 hand-rolled supersession counters with one primitive.
- Web app — record named load-pipeline spans. (#291)
- Web app — Opening a large trip is smoother — the map and the activity list stay responsive while the full-resolution track and elevation data load in the background, instead of freezing in short bursts for the first few seconds. (#292)
- Web app — The map no longer stutters in short bursts while a trip's full-resolution track loads — it now appears in a single step once ready. (#293)
- Web app — The moment a trip's full-resolution track appears on the map is no longer accompanied by a brief freeze. (#293)
- Web app — Selecting a day or an activity on the map is now noticeably quicker on long trips. (#294)
- Web app — split fetch from decode in the load spans, and record payload sizes.
- Web app — Panning the map shortly after opening a large trip no longer freezes the app. (#299)
- Web app — Reopening a large trip no longer freezes the map when you start panning. (#299)
- Web app — The Performance section in Settings now also reports how smoothly the map ran while you were panning it. (#276)
- Large trips are less likely to fail to load their full-resolution track and elevation data, and the Performance section in Settings now says plainly when a request failed rather than just how long it took. (#276)
- Web app — The map uses far less memory on trips with many photo memories, which should stop the app freezing on long trips. (#276)
- Perf — keep stall evidence across reloads, name the refresh that fired. (#276)
- Web app — merge the on-device cache row at blob level. (#276)
- Web app — Opening a large trip downloads far less data and uses much less memory: elevation is fetched separately and compactly instead of being bundled into one very large response. (#295)
- Web app — Viewing a large trip no longer downloads its elevation data twice. (#295)
- Web app — Long trips use noticeably less memory, and tapping the map responds faster on them. (#276)
- Perf — Map detail no longer drops to straight lines when zoomed out, and loading a long trip's map is much faster again.
- Web app — Fixed a multi-second freeze when a trip's elevation data finished loading, and when zooming the map replaced the low-detail tracks with detailed ones.
- Web app — Fixed the elevation chart briefly showing the whole trip instead of the activity you just selected.
- Map — Settings -> Performance now reports how long the map itself spends laying out and painting each frame, next to how many track points and markers it was drawing. (#276)
- Map — Tracks on the map now draw at the full detail the server sends for the current zoom, instead of being thinned to roughly half of it first. (#276)
- Map — Zooming in on a long trip is much faster — the app now asks the server only for the part of the route that is on screen, instead of the whole trip at full zoom detail. (#324)
- Perf — The performance report now shows what the map itself costs to lay out and paint each frame.
- Elevation — Opening a trip is faster and uses much less memory — the app no longer downloads every GPS elevation sample to draw an elevation chart that only shows 300 points. (#323)
- Map — Panning the map no longer makes the server rebuild the whole trip's geometry, so the map fills in faster and other requests stop timing out while it works.
- Web app — Tapping an activity on the map now spins the day strip to that activity's day, so the map and the day strip always agree on which day you are looking at. (#322)
- Version — The startup screen no longer briefly reads "server unknown" before the server version appears.
- Map — Fixed map requests still timing out at high zoom on long trips, and a map that could stay stale for up to fifteen minutes after an edit.
- Map — Fixed the Android app freezing and becoming unresponsive while panning or zooming the map.
- Map — The map again loads only the area you are looking at, so zooming in no longer waits on the whole trip being rebuilt.
- Map — Reduced the memory the app uses while loading a trip's map.
- Map — Smoother map while a trip loads — ...
Rail extracts rail-data-2026-09-08
Rail-only OSM extracts built by .github/workflows/rail-extract.yml from Geofabrik country extracts. Coverage, checksums and per-region source dates are in manifest.json.