Skip to content

v3.2.0

Latest

Choose a tag to compare

@mauriceboe mauriceboe released this 04 Jul 23:25
Release 2 9 0 (5) (1)

TREK 3.2.0

TREK becomes a platform. A sandboxed Plugin System with a community registry, one-click installs and a full author SDK. Collections — a personal place library that lives outside your trips. Public transit routing right in the planner, no API key needed. AI booking import for the confirmations structured parsing can't read. On top: per-user Appearance & theming, a robust offline mode with real conflict resolution, video in journeys and files, subscribable calendar feeds, an in-app help centre — and Vietnamese as language number 22.

No breaking changes — all 19 database migrations run automatically on startup, and Collections and AI Parsing stay off until you enable them.


Plugin System

TREK is now extensible. Anyone can build a plugin — a dashboard widget, a full page, or a headless integration — and self-hosters can browse a community registry and install it with one click, without ever touching TREK's source. Plugins run with real OS-level isolation behind an explicit permission model, and the whole system ships with an author toolchain that takes you from scaffold to published registry entry in a handful of commands. (#1415)

  • Three plugin typeswidgets render on the dashboard (sidebar card or a hero slot on the boarding-pass bar), pages get their own entry in the navigation, and integrations run headless server logic (API routes + scheduled jobs)
  • Real isolation, not a label — every active plugin runs as its own OS process under Node's permission model: it cannot read trek.db or any TREK secret, write files, spawn processes, or load native addons; its data lives in a separate per-plugin SQLite file
  • Capability permissions — a plugin declares what it needs (own database, membership-checked trip reads, public user profiles, namespaced WebSocket broadcasts, per-host outbound HTTP) and TREK's RPC host only exposes what was granted — an ungranted call is unreachable, not merely refused
  • Egress guard with SSRF backstop — all outbound traffic (fetch, sockets, UDP, even DNS) is restricted to the plugin's declared hosts, and connections to loopback/private/link-local/metadata addresses are refused even for allow-listed hosts
  • Sealed plugin UI — pages and widgets render in sandboxed, opaque-origin iframes with a locked-down per-plugin CSP; a plugin's frontend can never read your session cookie or the surrounding TREK page
  • Registry with one-click installAdmin → Plugins → Discover browses the public TREK-Plugins registry; installing verifies the artifact's pinned SHA-256 (plus an optional Ed25519 author signature), safely unpacks it, and registers it inactive — nothing runs until you flip the toggle
  • Review before you install — the detail view lists in plain language what a plugin can access, which hosts it talks to, and what it will ask you to configure, alongside a Reviewed badge for maintainer-scanned versions and an honest disclaimer about what the sandbox does and doesn't guarantee
  • Re-consent on updates — an update that requests new permissions or new outbound hosts is installed but left off until you approve the exact delta; an update can never silently widen a plugin's access
  • A real management surface — search, type/status filters, Update all, per-plugin health, error log, a capability audit log, restart, and uninstall with the choice to keep or delete the plugin's data
  • trek-plugin-sdk on npmnpx trek-plugin-sdk create scaffolds a plugin, dev runs it locally against a mock host that enforces your manifest's permission grants exactly like the TREK host (no TREK instance needed; the OS sandbox and egress guard apply inside a real TREK), and publish does the entire release — pack → GitHub release → preflight → auto-opened registry PR — in one command
  • Koffi, the reference plugin — TREK's mascot ships as a worked example: an animated suitcase hero widget driven by your real trip data, published in the registry
  • On by default, with a kill switch — the plugin system is available out of the box, but installed plugins still have to be activated one by one, so nothing third-party runs until you turn a specific plugin on; set TREK_PLUGINS_ENABLED=false to switch the whole system off (installed plugins stay on disk, deactivated)
  • Hardened by adversarial audit — two dedicated audit passes (threat model: malicious plugin author, malicious artifact) before merge closed sandbox-escape, SSRF, decompression-bomb, DoS and consent-bypass findings

Docs: Plugins · Plugin Development · Plugin Permissions · Publishing a Plugin


Collections — A Personal Place Library

A place you saved used to exist only inside its trip. The new Collections addon gives every user a place library outside of any trip: keep named lists of spots you've discovered — a "Norway someday" wishlist, "Best coffee in Lisbon" — copy places into and out of any trip, and share lists with other users. Enable it under Admin → Addons to get the new /collections page. (#1081)

  • Named lists — each with a colour, description, links and a cover image (upload or search Unsplash); a built-in All saved view unions your whole library
  • Idea / Want to go / Visited — a per-place status you cycle with one tap, plus status and category filters
  • List + map layout — lists rail, places list and a persistent map side by side, with a full-map toggle and a place detail sheet; mobile keeps a list/map switch
  • Save from a trip — "Save to collection" in the place inspector and context menus, plus a bulk action that copies every selected trip place into a chosen list (duplicates are skipped)
  • Copy to trip — saved places copy into any trip with name, description, category, notes, price, coordinates, photo and tags; the trip's add-place modal gains a Saved places picker sorted by proximity to the trip
  • Bulk actions — select-all, bulk delete, bulk copy-to-trip, and move or duplicate a selection into another list
  • Sharing with member roles — invite other users to a list (accept/decline, like Vacay fusion) with per-member roles: viewer, editor or admin, enforced on the server and synced live
  • Dashboard widget — your lists as compact badges on the dashboard, hideable per user
  • Custom labels — each list can define its own labels (e.g. Berlin, Hamburg, Ostsee in a "Germany 2026" list) to group its places. Create/rename/recolor/delete them in a label manager, assign them from a place's detail sheet or in bulk from the selection toolbar, and filter both the list and the map by label (multi-select, any-match). Labels are shared with everyone on the list — managing and assigning needs edit rights, filtering is open to all members

Full guide: Collections


Public Transit Routing

Google-Maps-style public transit directions, right in the planner — with no paid provider. Routing comes from Transitous, the community-run MOTIS service built on open GTFS feeds: free, open data, no API key required. (#1065)

  • Automated transport mode — the Add-transport dialog gets a Manual / Automated switch; Automated embeds the transit search, and a new tram button on each day header opens it with that day preset
  • Journey search — from/to stop search with the day's own places and hotels as quick picks, depart/arrive time, mode filters (train, subway, tram, bus, ferry, cable car) and ranking by best route, fewer transfers or less walking
  • Readable results — itinerary cards with local times, duration, transfers and walking minutes, line badges in their official colors, and an expandable stop-by-stop breakdown with platforms, headsigns and operators
  • First-class transit entries — a saved journey is its own reservation type: the day timeline renders the legs inline and folds the full itinerary out in place, and the Transports tab lists journeys in their own section
  • Journey view — duration / transfers / walking stat tiles, inline title rename, notes with a markdown toolbar, and a "Change route" action that re-runs the search pre-seeded with the journey's endpoints
  • Real paths on the map — journeys draw along the actual rail and bus alignments in each line's color, with walks as dotted connectors, on both map renderers
  • Right times, right slot — times are station-local, transfer waits count toward the duration, and after-midnight arrivals land on the next trip day
  • Self-host friendly — the server proxies Transitous (authenticated, rate-limited, cached); point TRANSIT_API_URL at your own MOTIS instance for zero third-party egress

Also on the map: booking route endpoint labels now default to off for a calmer look — re-enable them anytime in Settings.

Docs: Transport: Flights, Trains & Cars


AI Booking Import

Booking import no longer gives up on documents KDE Itinerary can't read. The new opt-in AI Parsing addon adds an LLM fallback that extracts flights, trains, buses, ferries, rental cars, hotels, restaurants and event tickets from unstructured confirmations — with first-class support for self-hosted local models. Based on work by @jubnl. (#1301, #1318)

  • Bring your own model — Local (Ollama), OpenAI — including any OpenAI-compatible endpoint via a custom base URL — or Anthropic; Anthropic reads the original PDF natively (scans included), the others work on the extracted text
  • Runs only when needed — structured parsing still goes first; the AI is asked only about files it can't read, and every AI result is flagged for review
  • Reliable on local models — a layered extraction router makes exactly one schema-constrained call per document (a multi-leg flight comes back as all its legs at once), then deterministically backfills booking reference, total price, currency and overnight arrival dates from the document itself
  • Qwen3-8B recommended, one-click pull — the admin config lists your installed Ollama models and pulls the recommended qwen3:8b with a live progress bar; NuExtract models are supported too — configure them under the OpenAI-compatible provider, where they're detected and driven through their native template format
  • Review before save — each parsed booking opens the normal edit modal pre-filled; nothing is written to the trip until you confirm
  • Parses in the background — the upload modal closes immediately; a progress widget tracks the parse, survives a page reload, and offers one-click review when done
  • Everything lands connected — venues become geocoded trip places, hotel bookings create the accommodation on the matching days, the parsed price becomes a linked Cost, and the source document is attached to the booking
  • Richer bookings — seat, class, platform and price are captured; hotels bring their address, rental cars their company, events their venue with phone and website
  • Instance-wide or per-user — admins can pin one provider and model for everyone in Admin → Addons, or each user configures their own under Settings → Integrations (API keys stored encrypted)

Appearance — Make TREK Yours

A new Settings → Appearance tab lets every user personalize TREK's look — per user, saved to your account, with a live preview. The default reproduces TREK's current look exactly, so nothing changes until you opt in. (#950, #951, #1025, #1271, #1370)

  • Seven color schemes — Default, High Contrast, Indigo, Teal, Rose, Amber and Violet, each with separate light- and dark-mode palettes
  • Custom accent color — pick your own accent (independently for light and dark) from swatches or a free picker, with a live contrast hint
  • Text size — an "Everything" slider (80–160 %) plus per-size sliders for Large / Medium / Normal / Small text, each with a live sample; the whole app resizes as you drag
  • Readability (experimental) — turn transparency off for solid, higher-contrast surfaces app-wide, a Compact density that tightens spacing, and a reduce-motion toggle
  • Dashboard widgets, per device — show or hide each dashboard widget independently on desktop and mobile; the layout reflows to use the freed space
  • No more theme flash — a pre-paint boot script applies your saved appearance before the first frame
  • One-click reset — back to stock TREK anytime

Alongside it, settings got a spring clean: the old Display tab is now General (split into "Language & region" and "Travel & map"), and the eleven flat admin tabs are grouped into Users, Configuration, Integrations and Maintenance sections.


In-App Help Centre

The TREK wiki is now built into the app: open Help from the profile menu (or /help) to browse the full documentation without leaving TREK. (#1373)

  • Full docs, TREK-styled — section navigation, search, themed markdown rendering; wiki links open in-app
  • Always current — your server fetches the wiki from GitHub and caches it, so documentation updates appear without a redeploy; if GitHub is unreachable, the last cached copy is served
  • Private by design — your browser never talks to GitHub; help pages and images are proxied through your own instance

Robust Offline Mode

Offline support graduates from a passive cache to something you control: go offline on purpose, decide what each device stores, and resolve sync conflicts instead of silently losing edits. (#1135)

  • Force offline mode — a new switch under Settings → Offline downloads everything first, then runs the whole app from local cache and queues every change; the override survives app restarts, and flipping it off replays the queue
  • Prepare for offline — a one-tap, progress-tracked download of trip data, documents and map tiles that waits for every download to actually finish before reporting "ready"
  • Choose what to store — turn map-tile storage off to keep only trip data and documents, and toggle offline storage per trip; evicting a trip keeps its unsynced edits
  • Conflict detection instead of silent overwrites — offline edits to places and packing items carry the version they were based on; if someone changed the item in the meantime, the edit surfaces as a conflict instead of clobbering the newer change
  • Keep mine / keep theirs — resolve each conflict side by side in Settings → Offline, or set a default rule (ask, always mine, always server)
  • Smarter status pill — the connectivity indicator now distinguishes forced offline, queued changes, unresolved conflicts and failed syncs

Docs: Offline Mode and PWA


Video Support

TREK's memories are no longer photos-only: upload and play videos in the journey gallery and the trip file manager, and link videos straight from your Immich library. (#823)

  • Video upload in the journey gallery — mp4, m4v, webm and mov up to 500 MB per clip; a poster frame and duration are captured in your browser, and the clip is stored as-is (no server-side transcoding)
  • Plyr video player — videos open in the lightbox with a clean, consistent player; the grid shows the poster with a play badge
  • Smooth seeking — local and linked videos stream with HTTP Range support, so jumping around the timeline is instant
  • Immich videos — the Immich picker (timeline and albums) now lists videos alongside photos; linked videos stream through Immich's transcoded playback endpoint with full seek support
  • Videos in the trip file manager — attach clips to places and reservations like any other file, with the same player; documents keep their own 50 MB limit
  • Shared journeys included — public journey share links show and play videos too

Community Feature Pack

Six of the most-requested features from GitHub Discussions land in one pack. (#1384, #1387)

  • Booking links — reservations get a dedicated Link field; save the booking URL once and open it straight from the reservation card (#935)
  • Markdown files render inline.md files open as a formatted (and sanitized) preview right in the file manager, tables and all (#1345)
  • Reorder packing & to-do lists — drag items into any order; the order saves instantly and syncs to the whole trip (#969)
  • Three-tier packing sharing — every packing item is Common (the group pool), Personal (only you see it) or Shared with specific people; a new Shared / My list switch separates the group pool from your own packing (#858)
  • "I can bring that too" — pledge to co-bring a common item, or copy it onto your personal list with one click; every item shows who's bringing it (#858)
  • Transfer trip ownership — hand a trip over to any member from the members dialog; the former owner stays on as a regular member (#973)
  • Guest members — add travel companions who don't have a TREK account: guests can be assigned to costs, packing, to-dos and activities like any member, but can never sign in, never receive notifications and never appear outside their trip (#1362, #1291)

Costs — Split Modes & Filters

The Costs addon gains proper Splitwise-style split modes — contributed by @Zorth — and quicker ways through long expense lists. (#1338, #1407)

  • Equally / Custom / Ticket splits — split equally, enter exact per-traveler amounts that must balance to the total, or itemize a receipt line by line and assign each line to specific travelers, with cent-perfect shares (#1338)
  • Fair rounding — equal splits distribute leftover cents deterministically and rotate who pays the extra cent, so nobody is systematically overcharged across a trip
  • Filter by category and day — two new dropdowns narrow the ledger to one category and/or a single day, with a per-day total banner, composing with search and the all/mine/owed filters (#1407)
  • Existing "paid by" expenses keep working and settle exactly as before

Docs: Budget Tracking


Invites & Joining Trips

Getting companions into a trip no longer requires adding them by hand. (#1143, #1402, #1405)

  • Trip invite links — every trip's Share panel can hold one rotating invite link (/join/<token>); anyone with a TREK account who opens it joins as a member, signed-out visitors log in first and land back on the invite
  • Regenerate or disable anytime — rotating the link instantly invalidates the old URL; managing it requires the trip's share permission
  • Trip-bound registration invites — an admin registration invite can be bound to a trip: whoever registers through it (password or SSO) is automatically added to that trip

Docs: Invite Links · Trip Members and Sharing · Admin: Users and Invites


Subscribable Calendar Feeds

TREK trips can now live in your calendar. Alongside the one-time .ics download, every trip — or all your trips at once — can expose a secret, revocable feed URL that Google Calendar, Apple Calendar and Outlook keep in sync as your plan changes. Contributed by @michael-bohr. (#1307)

  • Per-trip feed — the ICS button in the planner is now a menu: Download ICS for the classic export, Subscribe to calendar for a live feed
  • All-trips feed — one combined feed for every trip you own, reachable from the dashboard; archived and long-finished trips drop out automatically
  • One-click subscribeAdd to Google Calendar, a webcal:// handoff for Apple Calendar / Outlook, and copyable links for everything else
  • Private by default, fully revocable — no feed exists until you enable it; regenerate the secret link (invalidating the old URL) or turn it off entirely at any time
  • Full itinerary — the trip span, timed activities with locations, day notes and reservations — flights with their real local departure and arrival times and the full multi-leg route

Maps & Planner

  • Multi-leg train bookings — a long-distance rail trip is usually several trains on one ticket, so trains get the same multi-leg route editor as flights: an ordered chain of stations with an Add stop button, and per-leg train number, platform, seat and departure/arrival day + time. The whole station chain draws on the map, and each leg slots into its own day in the plan (independently reorderable). Single-station and pre-existing trains keep working unchanged (#1150)
  • Real road routes for car, bus, taxi & bicycle bookings — these transport bookings now follow actual roads on the map instead of a straight line. Geometry is fetched on demand from the public OSRM router (driving for car/bus/taxi, cycling for bicycle); the straight line shows until it loads and stays if routing fails, very long hops (~2000 km+) skip routing, and trains/cruises/ferries keep their straight line. Works on both map renderers
  • Marker clustering on the GL map — place markers on the Mapbox/MapLibre renderer now group into count bubbles on zoom-out, matching the Leaflet map (#1385)
  • Consistent hover card on the GL map — hovering a place shows the same slim name/category/address card as the Leaflet map (#1388)
  • Day selection fits the whole route — selecting a day zooms the map to the day's route as well as its stops, so a detour or ferry leg stays in view (#1128)
  • Bulk "Change category" — select several places and apply one category to all of them from the selection toolbar, with undo (#1168)
  • Bulk place updates via MCP — the new bulk_update_places tool applies the same field values to up to 500 places in one call (#1117) — see MCP Tools and Resources
  • Open in OpenStreetMap — the place inspector gains an OpenStreetMap button next to Google Maps — a handy hand-off to OSM-based apps like Organic Maps (#880)
  • Route distances inline on mobile — the per-day Route button in the mobile plan sheet shows that day's leg distances in place (#1374)
  • Year on trip dates — dashboard cards, the boarding-pass hero and planner day headers include the year whenever it isn't the current one (#1323)
  • Context-aware "+" button — the mobile bottom-nav "+" now matches the active trip tab: Bookings adds a booking, Transports a transport, Costs an expense, everywhere else a place (#1349)

Trips & Quality of Life

  • Unsplash cover search — find a trip cover by keyword right in the create/edit dialog, with photographer attribution and no API key; chosen photos are downloaded into your instance's uploads, so covers can't link-rot. Contributed by @hykilpikonna (#1277)
  • Faster date picking — the date picker now drills down from days to months to years for quick jumps, and a keyboard mode lets you type the date in your locale's format. Contributed by @gcettuzz (#1170)
  • OIDC profile pictures — SSO users who never uploaded an avatar get their identity provider's picture claim as avatar; an uploaded avatar always wins (#1399, #1403)

Internationalization

  • Tiếng Việt — TREK now ships a complete Vietnamese translation, bringing the total to 22 languages. Contributed by @leeduc (#1368)

Self-Hosting & Ops

  • Helm: bring your own storagepersistence.data.existingClaim / persistence.uploads.existingClaim bind the chart to PVCs you manage yourself, and persistence.enabled: false now falls back to an ephemeral emptyDir. Contributed by @yael-tramier (#1355)
  • No more silent admin-credential ignoresADMIN_EMAIL/ADMIN_PASSWORD only apply on the first boot of an empty database; the server now logs a clear warning when they're set but ignored (#1339, #1344)
  • Admin recovery script — locked out? docker exec -it trek node server/reset-admin.js resets (or creates) the admin account with a generated one-time password (#1339)
  • Plain-HTTP login, explained — the most common install trap (production build over plain http:// silently dropping the secure session cookie) now shows an explanation and the fix right on the login page instead of a dead end (#1373)
  • Troubleshooting guides — new wiki sections for the can't-log-in-after-setup scenario and the snap-Docker no-new-privileges startup failure (#1343, #1344): Troubleshooting
  • README refresh — all eight gallery screenshots re-captured on the current UI, including Collections

Developer & API

  • OpenAPI / Swagger API docs — TREK now ships an interactive REST API reference. Set TREK_API_DOCS_ENABLED=true and browse /api/docs for a full Swagger UI with "try it out"; the raw spec is at /api/docs-json (OpenAPI 3) and /api/docs-yaml for generating typed clients or importing into Postman. Request bodies are derived automatically from the same Zod validators the routes enforce, so the docs never drift. Off by default — the spec enumerates the whole surface including admin routes, so it's an explicit opt-in; authorize once with a session JWT via the Bearer button (#1412)

Fixes

A broad pass over community-reported bugs across the planner, map, bookings, costs, Atlas, AirTrail sync, the PWA and mobile.

  • No phantom routes between flights — two transports on the same day no longer draw a bogus airport-to-airport driving route between them (#1394)
  • Per-day Route button — on mobile, tapping a day's Route button computes that day's route, not the previously selected day's (#1392)
  • Google Maps route includes hotels — "open in Google Maps" now bookends the day with its accommodation, matching the drawn route (#1372)
  • Multi-day accommodation scroll — selecting a multi-day accommodation no longer yanks the plan list from day to day (#1375)
  • Compass on small screens — the reset-orientation compass now shows on mobile too (#1377)
  • Stable cost settlement — balances are netted in the trip's currency and converted once, so exchange-rate changes no longer drift balances or invent phantom micro-payments (#1382)
  • Transport-only countries count as visited — a country reached only by a flight or train booking now counts as visited on the dashboard and in Atlas (#1366)
  • Hotel booking dates — a hotel linked to an accommodation shows just its stay range, and the range stays correct after edits (#1383)
  • Link a place to any booking — every non-hotel booking type can link an existing trip place, pre-filling title and address (#1353)
  • Touch drag-and-drop — dragging places and days in the planner now works on Android and iOS (#1265)
  • AirTrail: manually-entered flights — flights without scheduled times now import their departure/arrival times, and already-imported flights pick them up on the next sync (#1336)
  • PWA starts offline again — opening the installed app without a connection loads the cached app instead of the browser's "no internet" page, while auth walls (Cloudflare Access, Pangolin) are still detected for re-login (#1346)
  • Mobile GPS button — the locate button sits above the day-detail panel instead of hiding behind it (#1348)
  • Place search autofocus — the search field focuses automatically when the add-place dialog opens — thanks @jufy111 (#1340)
  • Polish translation — travel buddies are now "Współpodróżnicy" instead of "Towarzysze" (#1390)
  • MCP streams stay connected — the SSE stream now sends a keep-alive ping (every 25 s by default) so reverse proxies with idle timeouts stop dropping it between tool calls, and ordinary admin saves no longer invalidate active MCP sessions (#1414)
  • Date-line routes draw as one arc — transpacific flights and any route crossing the antimeridian no longer split into two disconnected polylines at the map edges, on both renderers (#1411)
  • Map hover card no longer sticks — clicking an off-center place recenters the map, so the hover card is now cleared on marker click and camera moves instead of hanging around (#1404)
  • Add a place by long-press / right-click on GL maps — the Mapbox/MapLibre map now opens the Add-Place form on a touch long-press and on right-click, so mobile and Macs (no middle button) can drop a place anywhere (#1398)
  • KGS currency — the Kyrgyzstani som is now selectable as a trip, default and expense currency (#1400)

Contributors

Thanks to everyone who contributed to 3.2.0:


Stats

Metric Value
Commits 220
Merged PRs 39
Files changed 1,052
Lines added 61,000+
Contributors 9
New wiki pages 6

Upgrading

docker pull mauriceboe/trek:3.2.0
docker compose up -d

All 19 database migrations run automatically on startup — no manual steps, no breaking changes. Worth knowing:

  • Plugins are on by default — the Admin → Plugins panel is available out of the box (installed plugins still need per-plugin activation before anything runs); set TREK_PLUGINS_ENABLED=false to switch the system off. See Plugins
  • Collections and AI Parsing ship disabled — enable them under Admin → Addons
  • API docs are off by default — set TREK_API_DOCS_ENABLED=true to expose the interactive OpenAPI/Swagger reference at /api/docs; leave it off in production, since the spec includes admin endpoints
  • Large video uploads — if TREK sits behind a reverse proxy, raise its request-body limit (e.g. nginx client_max_body_size) to make use of the 500 MB video cap
  • Markdown uploadsmd/markdown were added to the default upload allowlist; if you overrode the allowed file types in the admin panel, add them there yourself
  • Behavior change — map booking-route endpoint labels now default to off; re-enable them in Settings
  • Calendar feed links — set APP_URL behind a reverse proxy so subscribable feed URLs are canonical
  • All new environment variables (TRANSIT_API_URL, TREK_PLUGINS_*, TREK_API_DOCS_ENABLED, and the MCP_SSE_KEEPALIVE / MCP_SESSION_TTL tunables) are optional and have sensible defaults

What's Changed

All 39 merged pull requests

PR #1425 is a rebase-merged batch that also folds in multi-leg train bookings (#1150), the real road-route booking overlays, the OpenAPI/Swagger docs (#1412) and the per-collection custom labels — those shipped as commits, not separate PRs.

New Contributors

Full Changelog: v3.1.4...v3.2.0