Skip to content

Draw list routes from indexed polylines instead of downloading GPX files - #1168

Open
mfortini wants to merge 5 commits into
open-wanderer:devfrom
mfortini:pr/lists-map-from-polylines
Open

Draw list routes from indexed polylines instead of downloading GPX files#1168
mfortini wants to merge 5 commits into
open-wanderer:devfrom
mfortini:pr/lists-map-from-polylines

Conversation

@mfortini

Copy link
Copy Markdown
Contributor

The lists overview map is empty or very slow because it required downloading every trail GPX sequentially before rendering.

  • Index each list's bounding box and trail polylines in Meilisearch
  • Render simplified preview routes on the overview map from polylines
  • Fit the viewport to the combined trail bounds with padding
  • Load full GPX only when a single trail is opened inside a list

The lists overview map was empty because it required downloading every
trail GPX sequentially before rendering.

- Index each list's bounding box and trail polylines in Meilisearch
- Render simplified preview routes on the overview map from polylines
- Fit the viewport to the combined trail bounds with padding
- Load full GPX only when a single trail is opened inside a list

@slothful-vassal slothful-vassal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this — I agree with the goal of making the list view load quickly without pulling every GPX file up front.

Up front: I don't think this indexing approach should be merged as it stands, mainly because of trail permissions. A public list can currently expose the geometry and bounds of private trails it contains. I left a blocking inline comment on the geometry aggregation with the concrete code path and reproduction. And that isn't something tighter sync logic can fix — it follows from list documents owning trail geometry in the first place.

Related issues from the same root:

  • Trail updates, deletions, and visibility changes don't reliably propagate to the derived list geometry, and removed geometry can linger in Meilisearch.
  • The per-list polyline limit doesn't respect the global map limit, so the total amount of geometry can grow well past it across several lists.

What I'd suggest instead: keep geometry in the trail index and compose list previews server-side — resolve the trails visible in each list, batch-fetch their geometry from the trail index, enforce permissions in one place, deduplicate trails shared across lists, and apply a single global polyline budget. Meilisearch can't join the two indices itself, but a bounded server-side composition avoids both the duplication and N+1 requests, and leaves room for caching later if measurements show it's needed.

For what it's worth, I ran into the same bottleneck a while back in #555 and approached it from the lazy-loading side instead. I never finished it, but it's a reminder that this has been a real problem for a while.

There are also smaller implementation issues — the frontend typecheck is currently failing, plus a few map interaction and state-management regressions. Worth addressing in the rework, but secondary to the ownership and permission questions.

The UI work here is worth keeping either way. Up to you whether you adapt this PR or open a fresh one and carry it over. Happy to sketch out the endpoint shape or look at an early draft if that would help.

Comment thread db/util/meilisearch.go Outdated
"iri": r.GetString("iri"),
}

expandedTrails := r.ExpandedAll("trails")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: this can expose private trail geometry through a public list.
expandedTrails is populated server-side and is not scoped to the current viewer. The code below derives the list center, bounds, and polylines from every expanded trail without checking the trail’s visibility.
Anonymous Meilisearch tokens only restrict the lists index to public = true (db/routes/search_token.go:13-16); they do not reapply the referenced trails’ permissions. At the same time, the list editor explicitly allows making a list public while keeping its trails private (web/src/routes/lists/edit/[id]/+page.svelte, the keep-private path).
Reproduction:

  1. Create a private trail and add it to a list.
  2. Make the list public and choose to keep the trails private.
  3. Log out.
  4. Search for the list through POST /api/v1/search/lists.
  5. The result still contains trail_polylines, lat/lon, and min_/max_ derived from the private trail.
    Filtering only public trails while indexing would not fully solve this either: the owner, shared users, and anonymous users can have different access to the trails, while the list has only one shared Meilisearch document. The geometry therefore needs to remain behind trail-level permissions.

mfortini and others added 4 commits August 27, 2026 13:23
List documents now store trail_ids only so overview map geometry
can be composed from the trail index under each viewer's token.
Add a viewer-scoped preview endpoint with a global polyline budget,
wire the lists overview map to it, and fix polylineToGeoJSON typing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants