* feat: meilisearch bounding box intersection and map filtering
* feat: tiered clustering and polyline filtering based on bounding box diagonal
Addressing review comments with optimized performance and data accuracy:
- Implemented a two-tiered search strategy (Summary vs. Detailed) to provide 100% accurate cluster counts while minimizing metadata traffic.
- Added a client-side ID-based cache to eliminate redundant network requests for trails already in memory.
- Introduced tiered 'detail shedding' that dynamically hides small trail lines when zooming out to maintain smooth panning performance.
- Fixed Svelte 5 reactivity issues to ensure clusters reappear instantly when trail detail is shed.
- Consolidated zoom thresholds into centralized constants for system-wide consistency.
- Updated Meilisearch configuration to support efficient ID-based filtering.
* feat: implement server-side map clustering using Meilisearch and Supercluster
- Implemented SvelteKit server-side clustering route at `/api/v1/search/trails/cluster` using the `supercluster` library.
- Integrated backend search results with the new clustering endpoint to improve performance for large trail datasets.
- Fixed Svelte 5 reactivity in `MapWithElevationMaplibre.svelte` by making `mapLoaded` reactive and fixing destructuring of `` map data.
- Removed obsolete client-side zoom constraints (`minzoom`/`maxzoom`) from `TrailLayer`, `PreviewLayer`, and `ClusterLayer` to allow dynamic visibility controlled by backend attributes.
- Fixed a bug where unauthenticated users generated invalid Meilisearch filters.
- Optimized map page performance by caching bounding box and filter values in the route loader.
- Updated `ClusterLayer` font to `Noto Sans Regular` to match available tileserver resources.
* feat: implement dynamic polyline visibility based on result density
- Replaced static zoom-based diagonal thresholds with a dynamic "Top N" approach for polyline visibility.
- Updated `/api/v1/search/trails/cluster` to mark only the top `MAP_MAX_POLYLINES` (default 100) trails by bounding box diagonal as "large".
- Modified `trails_search_bounding_box` store function to always fetch polylines for trails marked as large, regardless of zoom level.
- Removed obsolete `MAP_*_ZOOM_DIAGONAL_LIMIT` constants and simplified map layer constructors by removing tier-based filtering.
- Updated environment configurations and documentation to use the new `PUBLIC_MAP_MAX_POLYLINES` variable.
* refactor: remove obsolete zoom-based map clustering thresholds
Following the transition to dynamic server-side clustering based on result density (Top N polylines), this commit removes all remaining zoom-based thresholds and logic.
- Removed PUBLIC_MAP_LOW_ZOOM_THRESHOLD, PUBLIC_MAP_MEDIUM_ZOOM_THRESHOLD, and PUBLIC_MAP_HIGH_ZOOM_THRESHOLD environment variables.
- Removed the 'mapClusterMinZoom' user setting from the schema, models, and settings UI.
- Simplified the map component and MapLibre layer managers by removing unused 'clusterMinZoom', 'minZoom', and 'maxZoom' parameters.
- Cleaned up obsolete 'map-cluster-zoom-level' translation keys across all locales.
- Updated documentation to reflect the removal of these variables.
* chore: remove map clustering debug logs
* docs: update changelog and fix global zoom feature disappearance
* fix: address PR reviews and refine map cluster/preview visuals
* feat: implement configurable map cluster zoom and trail start marker settings
* feat: render single unclustered shedded trails as start markers instead of cluster circles
* minor fixes
* minor ui changes
* fix missing entries in map list
* remove redundant map clustering zoom clamp
* fix merge issues
* fix merge issues
* fixes
* hide popup for trails without details
* several improvements
* prevent import of client trail_store in server cluster code
* update changelog
---------
Co-authored-by: slothful-vassal <89943360+slothful-vassal@users.noreply.github.com>
* initial commit
* add remote trail/list
* fix errors
* update to use new IRIs
* use origin in migration instead
* use UnsafeWithoutHooks
* fix trail/list order of operations
* fix remote trail/list fetch
* fixes list document update
* fix errors
---------
Co-authored-by: Christian Beutel <>
* optimize db view queries
* add more indices
* appease gofmt
---------
Co-authored-by: Flomp <Flomp@users.noreply.github.com>
Co-authored-by: Christian Beutel <>
Three bugs caused partial imports:
1. Type filter halted pagination: if a page contained only tours of the
excluded type (planned vs. recorded), syncTrailWithTours returned false
and the loop stopped even though later pages might have matching tours.
Fixed by tracking allAlreadySynced separately - only tours already in the
DB count toward early termination, not type-filtered ones.
2. continue on error never incremented page: a fetch or sync error called
continue on the outer for loop, so page stayed the same and hasNewTours
was never updated, causing an infinite retry on the failing page. Changed
to break so a failed page aborts the current sync cycle cleanly.
3. Pagination ignored TotalPages: the loop used a fragile stop heuristic
instead of the TotalPages value returned by the Komoot API. fetchTours
now returns TotalPages and the loop uses it as the upper bound, with the
allAlreadySynced early-exit kept as an optimization for incremental syncs.
Closes#570
Co-authored-by: slothful-vassal <89943360+slothful-vassal@users.noreply.github.com>
* new setting: begin drawing a new trail from current location
* apply only when drawing
* fix application when editing an existing route
* documentation
* ignore pointer events on location circles
* fix i18n
---------
Co-authored-by: Flomp <Flomp@users.noreply.github.com>
Co-authored-by: Christian Beutel <>