Skip to content

πŸ“‚ Feature 03: Track Library & GPX Mechanics ​

NOTE

🧭 Navigation: 🧩 Features Index | 🚲 Wiki Home

The Track Library is the database repository and file processor for all saved cycling paths, user loops, and custom travel folders. It governs spatial data persistence, automatic folder sorting, and high-fidelity importing/exporting of industry-standard GPX files.


πŸ” How it Works (Product perspective) ​

  1. Seamless Save Flow:
    • Once a path is calculated on the map canvas, the user clicks Save Route (Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ). A dialog prompts for a title, optional description, and folder tags.
  2. Catalog and Search Panel:
    • Clicking the Library (Мои ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Ρ‹) button slides open a high-density, searchable catalog of all saved tracks, showing details like distance badges, elevation profiles, surface types, and date stamps.
  3. GPX File Imports:
    • Riders can drag and drop GPX files (Garmin, Strava, Wahoo) directly onto the map canvas. The system parses the coordinates, interpolates gaps, and draws the route overlay instantly.
  4. GPX XML Export:
    • Clicking Export GPX converts the client-side GeoJSON path on the fly into a standard GPX XML schema. The generated stream contains exact spatial trackpoints (<trkpt>), elevation tags (<ele>), timestamps, and total cumulative distance metrics, triggering a local browser download.
  5. Collections & Folders:
    • Tracks can be grouped into custom colored folders for search, filtering, and organization.

πŸ—οΈ Technical Architecture & Key Files ​

πŸ–₯️ Frontend State & UI Components ​

  • UI Widgets:
    • apps/web/src/features/track-library/ (library widgets, list filters, collection managers).
    • apps/web/src/widgets/library-sidebar/ & apps/web/src/widgets/library-grid/ (dashboard grid layout container).
  • Zustand State Store: useLibraryStore in apps/web/src/features/track-library/model/libraryStore.ts.
    • Slice Fields:
      • tracks: Track[] (list of saved tracks loaded from the database).
      • collections: Collection[] (folders configured by the user).
      • selectedTrackId: string | null (currently active track in the catalog).
      • searchQuery: string (text search criteria for active filtering).
  • GPX Serialization Utils: apps/web/src/shared/utils/gpx-serializer.ts (converts GeoJSON formats to standard GPX XML and vice versa).

πŸ”Œ API Integration & Core Services ​

  • Hono API Routers:
    • GET /api/tracks (loads active track list with bounding box coordinate parses).
    • POST /api/tracks (persists track geometry, waypoints lists, and cues).
    • DELETE /api/tracks/:id (archives or purges a track).
    • GET /api/collections & POST /api/collections & DELETE /api/collections/:id (manages custom folder categories).

πŸ’Ύ Database Schema (Drizzle & PostgreSQL) ​

Spatial persistence is handled by three interconnected Drizzle schemas in apps/api/src/db/schema.ts:

  1. tracks (Mapped in Feature 01):
    • Stores the PostGIS spatial geography line geometry (routeGeometry: geometry('route_geometry', { type: 'line_string', srid: 4326 })), distance, waypoints array, and custom metadata.
  2. collections:
    • id: uuid (PK)
    • userId: text (references users.id cascade)
    • name: text
    • colorHex: text
    • folder metadata fields for color, naming, and ordering.
  3. track_collections (Join Table):
    • trackId: uuid (references tracks.id cascade)
    • collectionId: uuid (references collections.id cascade)
    • sortOrder: integer (preserves display order inside collections)

πŸ§ͺ Test Suite Coverage & Regressions ​

πŸ”¬ Vitest Unit Tests ​

  • apps/web/src/entities/track/model/__tests__/trackApi.test.ts
  • apps/api/src/routes/__tests__/track.router.test.ts & collection.router.test.ts
    • Verifies GPX parsing, distance thresholds, spatial geometry conversions, and folder CRUD endpoints.

🎭 Playwright E2E Tests ​

  • apps/web/tests/save-track.spec.ts (Asserts that saving route renders a new database entry).
  • apps/web/tests/library-safety.spec.ts (Asserts deletion warnings and archiving validations).
  • apps/web/tests/project-smart-folders.spec.ts (Asserts smart folder query filters).
  • apps/web/tests/collections-screenshot.spec.ts & collections-visuals.spec.ts (Validates folder colored grids).

🐞 Known Issues & Resolved Bugs ​

  • GPX Null Elevation Bounds (Resolved): Some GPX files from old devices do not contain coordinate elevation tags (<ele>).
    • The Fix: The parser was upgraded to dynamically fallback to 0 or interpolate the missing elevation curves using neighboring waypoint nodes instead of throwing parse/null array pointer exceptions.
  • Sidebar Layout Overflow (Resolved): Long track names previously caused layout stretching on mobile screens.
    • The Fix: Added absolute ellipsis truncations and dynamic layout wrapping inside the library catalog.

πŸ‘£ Step-by-Step Manual Verification ​

  1. Start the server and create a simple route on the map canvas by clicking two spots.
  2. Click Save Route in the toolbar. Give it the name "My Custom Loop" and click Save.
  3. Confirm the save toast alerts appear.
  4. Slide open the Library panel and confirm "My Custom Loop" is successfully displayed with the exact distance in kilometers.
  5. Click Export GPX on the route. Select the download options, and click Download.
  6. Check your downloads folder to verify that a file named like route-2026-05-20.gpx was downloaded successfully, and can be read by text editors as valid XML.

πŸ“Έ Interface Artifacts ​