12 KiB
12 KiB
Open Mapping Project
Overview
Open Mapping is a collaborative route planning module for canvas-website that provides advanced mapping functionality beyond traditional tools like Google Maps. Built on open-source foundations (OpenStreetMap, OSRM, Valhalla, MapLibre), it integrates seamlessly with the tldraw canvas environment.
Vision
Create a "living map" that exists as a layer within the collaborative canvas, enabling teams to:
- Plan multi-destination trips with optimized routing
- Compare alternative routes visually
- Share and collaborate on itineraries in real-time
- Track budgets and schedules alongside geographic planning
- Work offline with cached map data
Core Features
1. Map Canvas Integration
- MapLibre GL JS as the rendering engine
- Seamless embedding within tldraw canvas
- Pan/zoom synchronized with canvas viewport
- Map shapes that can be annotated like any canvas object
2. Multi-Path Routing
- Support for multiple routing profiles (car, bike, foot, transit)
- Side-by-side route comparison
- Alternative route suggestions
- Turn-by-turn directions with elevation profiles
3. Collaborative Editing
- Real-time waypoint sharing via Y.js/CRDT
- Cursor presence on map (see where collaborators are looking)
- Concurrent route editing without conflicts
- Share links for view-only or edit access
4. Layer Management
- Multiple basemap options (OSM, satellite, terrain)
- Custom overlay layers (GeoJSON import)
- Route-specific layers (cycling, hiking trails)
- POI layers with filtering
5. Calendar Integration
- Attach time windows to waypoints
- Visualize itinerary timeline
- Sync with external calendars (iCal export)
- Travel time estimation between events
6. Budget Tracking
- Cost estimates per route (fuel, tolls)
- Per-waypoint expense tracking
- Trip budget aggregation
- Currency conversion
7. Offline Capability
- Tile caching for offline use
- Route pre-computation and storage
- PWA support for mobile
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Canvas Website │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ tldraw Canvas │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ Open Mapping Layer │ │ │
│ │ │ ┌─────────────┐ ┌─────────────────────────┐ │ │ │
│ │ │ │ MapLibre GL │ │ Route Visualization │ │ │ │
│ │ │ │ (basemap) │ │ (polylines/markers) │ │ │ │
│ │ │ └─────────────┘ └─────────────────────────┘ │ │ │
│ │ │ ┌─────────────┐ ┌─────────────────────────┐ │ │ │
│ │ │ │ Layers │ │ Collaboration │ │ │ │
│ │ │ │ Panel │ │ Cursors/Presence │ │ │ │
│ │ │ └─────────────┘ └─────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌───────────┐ ┌─────────────────┐
│ Routing API │ │ Y.js │ │ Tile Server │
│ (OSRM/Valhalla)│ │ (collab) │ │ (MapLibre) │
└─────────────────┘ └───────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ VROOM │
│ (optimization) │
└─────────────────┘
Technology Stack
| Component | Technology | License | Notes |
|---|---|---|---|
| Map Renderer | MapLibre GL JS | BSD-3 | Open-source Mapbox fork |
| Base Maps | OpenStreetMap | ODbL | Free, community-maintained |
| Routing Engine | OSRM / Valhalla | BSD-2 / MIT | Self-hosted, fast |
| Multi-Route | GraphHopper | Apache 2.0 | Custom profiles |
| Optimization | VROOM | BSD | TSP/VRP solver |
| Collaboration | Y.js | MIT | CRDT-based sync |
| State Management | Jotai | MIT | Already in use |
| Tile Caching | Service Worker | - | PWA standard |
Routing Provider Comparison
| Feature | OSRM | Valhalla | GraphHopper | ORS |
|---|---|---|---|---|
| Speed | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Profiles | 3 | 6+ | 10+ | 8+ |
| Alternatives | ✅ | ✅ | ✅ | ✅ |
| Isochrones | ❌ | ✅ | ✅ | ✅ |
| Transit | ❌ | ✅ | ⚠️ | ❌ |
| License | BSD-2 | MIT | Apache | GPL |
| Docker Ready | ✅ | ✅ | ✅ | ✅ |
Recommendation: Start with OSRM for simplicity and speed, add Valhalla for transit/isochrones.
Implementation Phases
Phase 1: Foundation (MVP)
- MapLibre GL JS integration with tldraw
- Basic waypoint placement and rendering
- Single-route calculation via OSRM
- Route polyline display
- Simple UI for profile selection (car/bike/foot)
Phase 2: Multi-Route & Comparison
- Alternative routes visualization
- Route comparison panel (distance, time, cost)
- Profile-based coloring
- Elevation profile display
- Drag-to-reroute functionality
Phase 3: Collaboration
- Y.js integration for real-time sync
- Cursor presence on map
- Concurrent waypoint editing
- Share link generation
- Permission management (view/edit)
Phase 4: Layers & Customization
- Layer panel UI
- Multiple basemap options
- Overlay layer support (GeoJSON)
- Custom marker icons
- Style customization
Phase 5: Calendar & Budget
- Time window attachment to waypoints
- Itinerary timeline view
- Budget tracking per waypoint
- Cost estimation for routes
- iCal export
Phase 6: Optimization & Offline
- VROOM integration for TSP/VRP
- Multi-stop optimization
- Tile caching via Service Worker
- Offline route storage
- PWA manifest
File Structure
src/open-mapping/
├── index.ts # Public exports
├── types/
│ └── index.ts # TypeScript definitions
├── components/
│ ├── index.ts
│ ├── MapCanvas.tsx # Main map component
│ ├── RouteLayer.tsx # Route polyline rendering
│ ├── WaypointMarker.tsx # Interactive markers
│ └── LayerPanel.tsx # Layer management UI
├── hooks/
│ ├── index.ts
│ ├── useMapInstance.ts # MapLibre instance management
│ ├── useRouting.ts # Route calculation
│ ├── useCollaboration.ts # Y.js sync
│ └── useLayers.ts # Layer state
├── services/
│ ├── index.ts
│ ├── RoutingService.ts # Multi-provider routing
│ ├── TileService.ts # Tile management/caching
│ └── OptimizationService.ts # VROOM integration
└── utils/
└── index.ts # Helper functions
Docker Deployment
The open-mapping backend services will be deployed to /opt/apps/open-mapping/ on Netcup RS 8000.
Services
-
OSRM - Primary routing engine
- Pre-processed OSM data for region (Europe/Germany)
- HTTP API on internal port
-
Valhalla (optional) - Extended routing
- Transit integration via GTFS
- Isochrone calculations
-
Tile Server - Vector tiles
- OpenMapTiles-based
- Serves tiles for offline caching
-
VROOM - Route optimization
- Solves complex multi-stop problems
- REST API
Docker Compose Preview
version: '3.8'
services:
osrm:
image: osrm/osrm-backend:latest
volumes:
- ./data/osrm:/data
command: osrm-routed --algorithm mld /data/region.osrm
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.osrm.rule=Host(`routing.jeffemmett.com`)"
tileserver:
image: maptiler/tileserver-gl:latest
volumes:
- ./data/tiles:/data
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.tiles.rule=Host(`tiles.jeffemmett.com`)"
networks:
traefik-public:
external: true
Data Requirements
OSM Data
- Download PBF files from Geofabrik
- For Europe: ~30GB (full), ~5GB (Germany only)
- Pre-process with
osrm-extract,osrm-partition,osrm-customize
Vector Tiles
- Generate from OSM data using OpenMapTiles
- Or download pre-built from MapTiler
- Storage: ~50GB for detailed regional tiles
API Endpoints
Routing API (/api/route)
POST /api/route
{
waypoints: [{ lat: number, lng: number }],
profile: 'car' | 'bike' | 'foot',
alternatives: number,
}
Response: Route[]
Optimization API (/api/optimize)
POST /api/optimize
{
waypoints: Waypoint[],
constraints: OptimizationConstraints,
}
Response: OptimizationResult
Isochrone API (/api/isochrone)
POST /api/isochrone
{
center: { lat: number, lng: number },
minutes: number[],
profile: string,
}
Response: GeoJSON.FeatureCollection
Dependencies to Add
{
"dependencies": {
"maplibre-gl": "^4.x",
"@maplibre/maplibre-gl-geocoder": "^1.x",
"geojson": "^0.5.x"
}
}
Related Projects & Inspiration
- Mapus - Real-time collaborative mapping
- uMap - OpenStreetMap-based map maker
- Organic Maps - Offline-first navigation
- Komoot - Outdoor route planning
- Rome2Rio - Multi-modal journey planner
- Wandrer.earth - Exploration tracking
Success Metrics
- Route Calculation < 500ms for typical queries
- Collaboration Sync < 100ms latency
- Offline Coverage Entire planned region cached
- Budget Accuracy ±15% for fuel estimates
- User Satisfaction Preferred over Google Maps for trip planning
Open Questions
- Should we integrate transit data (GTFS feeds)?
- What regions should we pre-process initially?
- How to handle very long routes (cross-country)?
- Should routes be persisted separately from canvas?
- Integration with existing canvas tools (markdown notes on waypoints)?