Alpha stage commit
This commit is contained in:
43
docs/00_executive_summary.md
Normal file
43
docs/00_executive_summary.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Executive Summary
|
||||
|
||||
## Product
|
||||
|
||||
A specialized bikepacking planner and riding companion for multi-day trips. It should combine route planning, daily stages, route-corridor logistics, local rules, offline use, and bikepacking-specific route suitability.
|
||||
|
||||
## Positioning
|
||||
|
||||
**BikepackPilot** is for riders who need answers beyond “which road/path connects A to B?”
|
||||
|
||||
It answers:
|
||||
|
||||
- Can I ride this with a loaded bike?
|
||||
- Where can I sleep tonight?
|
||||
- How far to the next reliable water?
|
||||
- Is there food before shops close?
|
||||
- What if this forest road is closed?
|
||||
- Where is the nearest bike shop or bailout train?
|
||||
- Can the plan still work offline?
|
||||
|
||||
## Primary users
|
||||
|
||||
1. **Weekend bikepacker**: 2–3 days, wants low stress, legal sleep options, reliable water/food.
|
||||
2. **Long-distance tourer**: multi-week trip, needs offline maps, resupply, device export, budget sleep.
|
||||
3. **Gravel/adventure rider**: wants maximum dirt but still rideable on a loaded bike.
|
||||
4. **Remote-route rider**: needs dry-stretch warnings, bailout options, weather exposure, repair planning.
|
||||
5. **E-bikepacker**: needs charging points, range-aware stages, charger-friendly overnight stops.
|
||||
|
||||
## Differentiation from general route planners
|
||||
|
||||
The differentiator is not access to a secret map dataset. Major outdoor planners often use OpenStreetMap as a foundation. The differentiator is the proprietary layer built on top:
|
||||
|
||||
- bikepacking suitability score,
|
||||
- rideability with loaded bike,
|
||||
- water/food/sleep gaps,
|
||||
- local rules confidence,
|
||||
- trusted local reports,
|
||||
- offline route-corridor intelligence,
|
||||
- multi-day staging optimized around logistics.
|
||||
|
||||
## MVP outcome
|
||||
|
||||
A user should be able to plan a 3–7 day trip, inspect stage cards, see critical POIs, export a route, and save an offline pack.
|
||||
133
docs/01_product_requirements.md
Normal file
133
docs/01_product_requirements.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Product Requirements Document
|
||||
|
||||
## Vision
|
||||
|
||||
Build the best planning and riding tool for self-supported bikepacking trips.
|
||||
|
||||
## Core promise
|
||||
|
||||
Plan a rideable, legal, enjoyable, and logistically safe route for a loaded bike over multiple days, including sleep, water, food, repair, local rules, weather, and bailout options.
|
||||
|
||||
## Non-goals for MVP
|
||||
|
||||
- Do not build a social network first.
|
||||
- Do not build full turn-by-turn voice navigation first.
|
||||
- Do not build a complete global legal camping database first.
|
||||
- Do not depend on one commercial booking/routing API.
|
||||
- Do not attempt global correctness for local rules. Use confidence levels.
|
||||
|
||||
## Functional requirements
|
||||
|
||||
### Trip planning
|
||||
|
||||
Users can create a trip with:
|
||||
|
||||
- start/end locations or imported GPX,
|
||||
- start date and optional end date,
|
||||
- bike type,
|
||||
- load level,
|
||||
- rider fitness preference,
|
||||
- daily target distance range,
|
||||
- daily target climbing range,
|
||||
- maximum loaded-bike grade,
|
||||
- preferred surface mix,
|
||||
- sleep preference,
|
||||
- water interval limit,
|
||||
- resupply interval limit,
|
||||
- bailout preference.
|
||||
|
||||
### Bikepacking routing
|
||||
|
||||
The planner returns:
|
||||
|
||||
- route geometry,
|
||||
- elevation profile,
|
||||
- distance and climb,
|
||||
- surface breakdown,
|
||||
- traffic/access confidence,
|
||||
- steep segment warnings,
|
||||
- long no-water/no-food warnings,
|
||||
- possible hike-a-bike warnings,
|
||||
- stage suggestions.
|
||||
|
||||
### Multi-day staging
|
||||
|
||||
The app divides the route into daily stages based on:
|
||||
|
||||
- daily distance/climb targets,
|
||||
- daylight window,
|
||||
- sleep options,
|
||||
- food/water availability,
|
||||
- bailout access,
|
||||
- weather risk if available,
|
||||
- user preference for indoor/outdoor nights.
|
||||
|
||||
Each stage has:
|
||||
|
||||
- distance,
|
||||
- ascent/descent,
|
||||
- expected riding time range,
|
||||
- surface mix,
|
||||
- sleep candidates,
|
||||
- food/water critical points,
|
||||
- warnings,
|
||||
- Plan A and Plan B endpoint.
|
||||
|
||||
### Route-corridor logistics
|
||||
|
||||
The app supports corridor queries around the route:
|
||||
|
||||
- water,
|
||||
- supermarkets,
|
||||
- bakeries,
|
||||
- cafés/restaurants,
|
||||
- gas stations,
|
||||
- campsites,
|
||||
- shelters,
|
||||
- huts,
|
||||
- hostels/hotels,
|
||||
- Warmshowers-style hosts via partnership/deep link if available,
|
||||
- bike shops,
|
||||
- repair stations,
|
||||
- train/bus/ferry bailout.
|
||||
|
||||
### Offline
|
||||
|
||||
Offline packs should include:
|
||||
|
||||
- route geometry,
|
||||
- map tiles/vector map region,
|
||||
- route-corridor POIs,
|
||||
- stage plan,
|
||||
- elevation profile,
|
||||
- rule cards,
|
||||
- emergency/bailout points,
|
||||
- saved notes,
|
||||
- exports.
|
||||
|
||||
### Community/local intelligence
|
||||
|
||||
Users can report:
|
||||
|
||||
- water available/unavailable,
|
||||
- surface mismatch,
|
||||
- locked gate,
|
||||
- access restriction,
|
||||
- dangerous dogs,
|
||||
- mud/sand/washout,
|
||||
- bridge/ferry closure,
|
||||
- good/bad sleep option,
|
||||
- bike shop availability,
|
||||
- reroute recommendation.
|
||||
|
||||
Reports must be dated, location-bound, typed, confidence-scored, and expire unless reconfirmed.
|
||||
|
||||
## Non-functional requirements
|
||||
|
||||
- Offline-first for riding-critical functions.
|
||||
- Clear attribution for OSM-derived data.
|
||||
- Explicit uncertainty indicators for legal/safety information.
|
||||
- Fast route-corridor search.
|
||||
- Provider abstraction to avoid lock-in.
|
||||
- Export support for GPX first, then TCX/FIT.
|
||||
- Privacy-conscious location handling.
|
||||
71
docs/02_mvp_scope.md
Normal file
71
docs/02_mvp_scope.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# MVP Scope
|
||||
|
||||
## MVP goal
|
||||
|
||||
Deliver a planner that is useful before the ride and minimally useful during the ride.
|
||||
|
||||
## MVP features
|
||||
|
||||
### Must have
|
||||
|
||||
1. Trip request form.
|
||||
2. Routing adapter using a configurable provider.
|
||||
3. Bikepacking route scoring summary.
|
||||
4. Stage planner.
|
||||
5. Route-corridor POIs for water, food, sleep, and bike repair.
|
||||
6. Critical-gap warnings.
|
||||
7. GPX export.
|
||||
8. Offline-pack manifest and cached trip data.
|
||||
9. Text-based local rule cards.
|
||||
10. Structured report submission.
|
||||
|
||||
### Should have
|
||||
|
||||
1. Map layer toggles.
|
||||
2. Surface/elevation/stage chart.
|
||||
3. Bailout POI detection.
|
||||
4. Weather overlay and wind/rain warnings.
|
||||
5. TCX export.
|
||||
6. Deep links to accommodation/search platforms.
|
||||
|
||||
### Could have
|
||||
|
||||
1. FIT export.
|
||||
2. Garmin Courses API integration.
|
||||
3. Wahoo integration.
|
||||
4. In-app booking.
|
||||
5. AI route explanation.
|
||||
6. Trusted-local reputation system.
|
||||
|
||||
### Not in MVP
|
||||
|
||||
1. Full global offline routing.
|
||||
2. Real-time social feed.
|
||||
3. Payments marketplace.
|
||||
4. Full legal advice engine.
|
||||
5. Fully automated OSM editing.
|
||||
|
||||
## MVP success criteria
|
||||
|
||||
A test user can plan a 5-day gravel bikepacking route and identify:
|
||||
|
||||
- daily endpoints,
|
||||
- longest water gap,
|
||||
- last shop before remote section,
|
||||
- sleep options each night,
|
||||
- bike repair options,
|
||||
- uncertain access segments,
|
||||
- bailout points,
|
||||
- exported GPX.
|
||||
|
||||
## Target regions for MVP validation
|
||||
|
||||
Pick one or two data-rich regions first, for example:
|
||||
|
||||
- Germany/Austria/Switzerland,
|
||||
- Netherlands/Belgium/Germany,
|
||||
- UK,
|
||||
- Pacific Northwest,
|
||||
- Colorado/Utah.
|
||||
|
||||
Data quality varies heavily by region. Start where OSM and POI data are strong and bikepacking demand exists.
|
||||
120
docs/03_system_architecture.md
Normal file
120
docs/03_system_architecture.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# System Architecture
|
||||
|
||||
## Recommended stack
|
||||
|
||||
### Apps
|
||||
|
||||
- `apps/web`: trip planning interface.
|
||||
- `apps/mobile`: mobile riding/offline interface.
|
||||
|
||||
Recommended technologies:
|
||||
|
||||
- TypeScript.
|
||||
- React for web.
|
||||
- React Native for mobile.
|
||||
- MapLibre-compatible rendering.
|
||||
|
||||
### Backend
|
||||
|
||||
- API service: FastAPI or equivalent.
|
||||
- Database: PostgreSQL + PostGIS.
|
||||
- Queue: Redis + worker for imports/scoring/offline-pack jobs.
|
||||
- Object storage: S3-compatible bucket for generated exports/offline manifests.
|
||||
|
||||
### Routing
|
||||
|
||||
Routing must be accessed through a provider interface. Supported target providers:
|
||||
|
||||
- openrouteservice for prototype/API-based routing,
|
||||
- GraphHopper for self-hosted or API routing,
|
||||
- Valhalla for self-hosted routing and isochrones,
|
||||
- BRouter-inspired offline routing later.
|
||||
|
||||
### Map display
|
||||
|
||||
- MapLibre-compatible client.
|
||||
- Vector tiles from self-hosted OpenMapTiles, Protomaps/PMTiles, MapTiler, or equivalent.
|
||||
- Do not rely on public OSM tile servers for production app traffic.
|
||||
|
||||
### Data pipeline
|
||||
|
||||
Pipeline jobs:
|
||||
|
||||
1. Download OSM extracts.
|
||||
2. Normalize bikepacking-relevant tags.
|
||||
3. Build route graph or send extract to routing engine.
|
||||
4. Import POIs.
|
||||
5. Attach elevation.
|
||||
6. Import protected areas/rules.
|
||||
7. Generate derived segment scores.
|
||||
8. Build offline pack manifests.
|
||||
|
||||
## Services
|
||||
|
||||
```text
|
||||
Client Apps
|
||||
|-- Web planner
|
||||
|-- Mobile rider app
|
||||
|
||||
Backend API
|
||||
|-- Auth/session
|
||||
|-- Trip planner
|
||||
|-- Stage planner
|
||||
|-- Route scorer
|
||||
|-- POI corridor service
|
||||
|-- Offline pack service
|
||||
|-- Export service
|
||||
|-- Community report service
|
||||
|-- Rules service
|
||||
|
||||
Provider Layer
|
||||
|-- Routing provider
|
||||
|-- Elevation provider
|
||||
|-- POI provider
|
||||
|-- Weather provider
|
||||
|-- Accommodation provider
|
||||
|-- Device export provider
|
||||
|
||||
Data Stores
|
||||
|-- PostGIS
|
||||
|-- Object storage
|
||||
|-- Cache/queue
|
||||
```
|
||||
|
||||
## Provider interfaces
|
||||
|
||||
Every external dependency should be swappable.
|
||||
|
||||
```ts
|
||||
interface RoutingProvider {
|
||||
planRoute(request: RoutePlanRequest): Promise<RouteGeometryResult>;
|
||||
reroute(request: RerouteRequest): Promise<RouteGeometryResult>;
|
||||
}
|
||||
|
||||
interface PoiProvider {
|
||||
searchCorridor(request: CorridorPoiRequest): Promise<Poi[]>;
|
||||
}
|
||||
|
||||
interface ElevationProvider {
|
||||
samplePolyline(polyline: Coordinate[]): Promise<ElevationSample[]>;
|
||||
}
|
||||
|
||||
interface WeatherProvider {
|
||||
forecastAlongRoute(request: WeatherRouteRequest): Promise<RouteWeatherRisk[]>;
|
||||
}
|
||||
|
||||
interface RulesProvider {
|
||||
getRuleCards(request: RuleCardRequest): Promise<RuleCard[]>;
|
||||
}
|
||||
```
|
||||
|
||||
## MVP architecture simplification
|
||||
|
||||
For first implementation:
|
||||
|
||||
- use a hosted routing provider or mock routing fixture;
|
||||
- use OSM-derived POI fixtures in PostGIS;
|
||||
- implement stage planning and scoring locally;
|
||||
- render a route and stage cards;
|
||||
- export GPX;
|
||||
- define offline pack manifest without full tile download implementation.
|
||||
124
docs/04_data_sources.md
Normal file
124
docs/04_data_sources.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Data Sources
|
||||
|
||||
Verified source links are listed in `docs/source_references.md`.
|
||||
|
||||
## Core principle
|
||||
|
||||
The raw route network can be built from OpenStreetMap. The competitive advantage comes from derived intelligence:
|
||||
|
||||
- route segment suitability,
|
||||
- loaded-bike rideability,
|
||||
- route-corridor logistics,
|
||||
- water/food/sleep reliability,
|
||||
- local rules confidence,
|
||||
- trusted local reports,
|
||||
- actual ride feedback.
|
||||
|
||||
## Data-source matrix
|
||||
|
||||
| Domain | Source candidates | MVP use | Production use | Caveats |
|
||||
|---|---|---|---|---|
|
||||
| Base map/network | OpenStreetMap extracts via Geofabrik or planet.osm | Road/path graph, surfaces, access, POIs | Full regional/global ingestion | ODbL obligations; data quality varies |
|
||||
| Routing engine | openrouteservice, GraphHopper, Valhalla, BRouter | Hosted API or local engine adapter | Self-hosted customized profiles | Requires tuning; public APIs have limits |
|
||||
| Elevation | Copernicus DEM GLO-30/GLO-90, NASA SRTM | Elevation profile and grade warnings | Segment-level grade/hike-a-bike modeling | DEM artifacts; bridges/tunnels need handling |
|
||||
| Vector maps | OpenMapTiles, Protomaps/PMTiles, MapTiler, custom tiles | Web/mobile map display | Offline vector packs | Attribution and tile generation costs |
|
||||
| POIs | OSM POIs, Overture Places, partner APIs | Water/food/sleep/repair corridor | Reliability scoring and deduplication | POIs stale/incomplete; licensing varies |
|
||||
| Protected areas | Protected Planet WDPA/WDPCA, national/regional open data | Rule warnings | Rule confidence engine | Rules are jurisdiction-specific |
|
||||
| Weather | Open-Meteo, MET Norway/Yr, national weather services, commercial APIs | Forecast along route | Weather-aware rerouting | Forecast uncertainty; API licensing |
|
||||
| Accommodation | OSM campsites/shelters, Booking Demand API, direct campsite/hut partners, Warmshowers-style partnerships | Deep links and search cards | Reservation/check availability where allowed | API access/partner terms |
|
||||
| Bike devices | GPX/TCX/FIT export, Garmin Courses API, Wahoo Cloud API | GPX export | Direct sync | API approval required |
|
||||
|
||||
## OSM tags to prioritize
|
||||
|
||||
### Route network
|
||||
|
||||
- `highway=*`
|
||||
- `bicycle=*`
|
||||
- `access=*`
|
||||
- `surface=*`
|
||||
- `smoothness=*`
|
||||
- `tracktype=*`
|
||||
- `sac_scale=*`
|
||||
- `mtb:scale=*`
|
||||
- `incline=*`
|
||||
- `ford=*`
|
||||
- `bridge=*`
|
||||
- `tunnel=*`
|
||||
- `barrier=*`
|
||||
- `route=bicycle`
|
||||
- `network=*`
|
||||
|
||||
### Water
|
||||
|
||||
- `amenity=drinking_water`
|
||||
- `drinking_water=yes/no`
|
||||
- `natural=spring`
|
||||
- `man_made=water_well`
|
||||
- `amenity=fountain`
|
||||
|
||||
### Food and resupply
|
||||
|
||||
- `shop=supermarket`
|
||||
- `shop=convenience`
|
||||
- `shop=bakery`
|
||||
- `amenity=cafe`
|
||||
- `amenity=restaurant`
|
||||
- `amenity=fast_food`
|
||||
- `amenity=fuel`
|
||||
|
||||
### Sleep
|
||||
|
||||
- `tourism=camp_site`
|
||||
- `tourism=caravan_site`
|
||||
- `tourism=alpine_hut`
|
||||
- `tourism=wilderness_hut`
|
||||
- `tourism=hostel`
|
||||
- `tourism=hotel`
|
||||
- `amenity=shelter`
|
||||
|
||||
### Bike repair
|
||||
|
||||
- `shop=bicycle`
|
||||
- `amenity=bicycle_repair_station`
|
||||
- `service:bicycle:repair=yes`
|
||||
- `service:bicycle:pump=yes`
|
||||
|
||||
### Bailout
|
||||
|
||||
- `railway=station`
|
||||
- `public_transport=station`
|
||||
- `amenity=bus_station`
|
||||
- `route=ferry`
|
||||
|
||||
## Data ingestion notes
|
||||
|
||||
### OSM
|
||||
|
||||
Use regional PBF extracts for development. Do not query public Overpass for production-scale route-corridor POI needs. Import regional extracts into PostGIS or a search index.
|
||||
|
||||
### POI deduplication
|
||||
|
||||
POIs may appear in multiple sources. Use a deduplication key based on:
|
||||
|
||||
- geohash proximity,
|
||||
- normalized name,
|
||||
- category,
|
||||
- phone/website if available,
|
||||
- source reliability.
|
||||
|
||||
### Reliability scoring
|
||||
|
||||
Each POI should have:
|
||||
|
||||
- `source`,
|
||||
- `last_seen_at`,
|
||||
- `last_confirmed_by_user_at`,
|
||||
- `seasonality`,
|
||||
- `opening_hours`,
|
||||
- `confidence`,
|
||||
- `bikepacker_notes_count`,
|
||||
- `negative_reports_count`.
|
||||
|
||||
### Rules
|
||||
|
||||
Rules must be jurisdiction-specific and confidence-scored. Never present legal/camping rules as absolute unless sourced from official/local authority data and current.
|
||||
156
docs/05_routing_and_scoring.md
Normal file
156
docs/05_routing_and_scoring.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Routing and Scoring Model
|
||||
|
||||
## Goal
|
||||
|
||||
Optimize for a loaded bikepacking trip, not a generic bike route.
|
||||
|
||||
## Route cost model
|
||||
|
||||
A candidate route is scored by segment and by whole-trip logistics.
|
||||
|
||||
```text
|
||||
segment_cost =
|
||||
distance_cost
|
||||
+ climb_cost
|
||||
+ steepness_cost
|
||||
+ poor_surface_cost
|
||||
+ traffic_stress_cost
|
||||
+ access_uncertainty_cost
|
||||
+ hike_a_bike_risk_cost
|
||||
+ remoteness_cost
|
||||
+ weather_sensitivity_cost
|
||||
- official_cycle_route_bonus
|
||||
- confirmed_good_segment_bonus
|
||||
- scenic_bonus
|
||||
```
|
||||
|
||||
```text
|
||||
stage_cost =
|
||||
ride_effort_cost
|
||||
+ sleep_risk_cost
|
||||
+ water_gap_cost
|
||||
+ food_gap_cost
|
||||
+ daylight_risk_cost
|
||||
+ weather_risk_cost
|
||||
+ bailout_gap_cost
|
||||
+ repair_gap_cost
|
||||
```
|
||||
|
||||
## Segment attributes
|
||||
|
||||
Each segment should carry:
|
||||
|
||||
- distance meters,
|
||||
- ascent/descent,
|
||||
- max grade,
|
||||
- average grade,
|
||||
- surface,
|
||||
- smoothness,
|
||||
- OSM highway class,
|
||||
- bicycle/access tags,
|
||||
- traffic stress proxy,
|
||||
- cycle route membership,
|
||||
- protected-area overlap,
|
||||
- POI distance to next water/food/repair/sleep,
|
||||
- community report score,
|
||||
- confidence score.
|
||||
|
||||
## Bikepacking profiles
|
||||
|
||||
### Loaded gravel
|
||||
|
||||
- Prefer gravel/compact dirt and low-traffic roads.
|
||||
- Penalize technical MTB trails.
|
||||
- Penalize grades above 12% more heavily when loaded.
|
||||
- Penalize unknown surfaces in remote areas.
|
||||
|
||||
### Hardtail bikepacking
|
||||
|
||||
- Allow more rough surfaces.
|
||||
- Allow singletrack where bicycle access and difficulty are acceptable.
|
||||
- Penalize sustained paved highways and high traffic.
|
||||
|
||||
### Road touring
|
||||
|
||||
- Prefer paved low-traffic roads and official cycle routes.
|
||||
- Avoid rough surfaces, tracks, and paths with unknown rideability.
|
||||
|
||||
### E-bikepacking
|
||||
|
||||
- Add range and charging constraints.
|
||||
- Penalize long remote stretches without accommodation/charging.
|
||||
- Respect local e-bike access distinctions where available.
|
||||
|
||||
### Beginner-safe
|
||||
|
||||
- Strongly prefer known surfaces and legal certainty.
|
||||
- Avoid high traffic, remote stretches, long dry gaps, and steep grades.
|
||||
|
||||
## Confidence model
|
||||
|
||||
The app should show both recommendation and confidence.
|
||||
|
||||
Example route summary:
|
||||
|
||||
```text
|
||||
Distance: 382 km
|
||||
Ascent: 5,420 m
|
||||
Known surface: 88%
|
||||
Unpaved: 42%
|
||||
Longest water gap: 36 km
|
||||
Longest food gap: 58 km
|
||||
Access confidence: Medium-high
|
||||
Sleep certainty: 4/5 nights confirmed options
|
||||
Bailout gap: Max 71 km from train/ferry/bus
|
||||
Warnings: 2 steep loaded-bike climbs, 1 uncertain access segment
|
||||
```
|
||||
|
||||
## Hike-a-bike risk
|
||||
|
||||
Estimate using:
|
||||
|
||||
- steep grade,
|
||||
- poor smoothness,
|
||||
- `mtb:scale`,
|
||||
- `sac_scale`,
|
||||
- surface type,
|
||||
- trail width if available,
|
||||
- rider profile,
|
||||
- actual ride speed reports,
|
||||
- user reports.
|
||||
|
||||
A route can include hike-a-bike if the profile allows it, but it must be visible.
|
||||
|
||||
## Critical gap detection
|
||||
|
||||
Calculate gaps along the route:
|
||||
|
||||
- water gap,
|
||||
- food gap,
|
||||
- sleep gap,
|
||||
- repair gap,
|
||||
- bailout gap,
|
||||
- charging gap for e-bike.
|
||||
|
||||
Warnings should be generated when a gap exceeds profile thresholds.
|
||||
|
||||
## Stage planning algorithm
|
||||
|
||||
1. Generate candidate endpoints every 5–15 km around the daily target window.
|
||||
2. Score each endpoint by sleep options, water/food, daylight fit, safety, and bailout.
|
||||
3. Prefer endpoints with at least one high-confidence sleep option.
|
||||
4. Add Plan B endpoints before and after Plan A.
|
||||
5. Rebalance subsequent stages to avoid one impossible day.
|
||||
6. Surface warnings for stages where no good endpoint exists.
|
||||
|
||||
## Example thresholds
|
||||
|
||||
| Profile | Target km/day | Max grade warning | Max water gap | Max food gap |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Beginner-safe | 40–70 | 10% | 25 km | 40 km |
|
||||
| Loaded gravel | 60–100 | 12% | 40 km | 70 km |
|
||||
| Hardtail remote | 50–90 | 15% | 55 km | 90 km |
|
||||
| Road touring | 70–130 | 10% | 40 km | 70 km |
|
||||
| E-bikepacking | 50–100 | 12% | 40 km | 60 km + charging |
|
||||
|
||||
Thresholds should be configurable per user.
|
||||
89
docs/06_offline_strategy.md
Normal file
89
docs/06_offline_strategy.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Offline Strategy
|
||||
|
||||
## Offline requirement
|
||||
|
||||
Offline use must cover riding-critical information, not only maps.
|
||||
|
||||
## Offline pack contents
|
||||
|
||||
A trip offline pack should include:
|
||||
|
||||
- route geometry,
|
||||
- route alternatives,
|
||||
- daily stages,
|
||||
- elevation profile,
|
||||
- selected vector/raster map area,
|
||||
- route-corridor POIs,
|
||||
- emergency/bailout POIs,
|
||||
- local rule cards,
|
||||
- cached weather forecast at departure,
|
||||
- saved bookings/deep links/addresses,
|
||||
- user notes,
|
||||
- GPX/TCX/FIT exports,
|
||||
- report queue for later upload.
|
||||
|
||||
## Pack scope
|
||||
|
||||
Use a corridor-based pack:
|
||||
|
||||
```text
|
||||
primary corridor: 5 km on either side of route
|
||||
logistics corridor: 20 km around stage endpoints and bailout towns
|
||||
map context: bounding box with simplification by zoom level
|
||||
```
|
||||
|
||||
## Offline modes
|
||||
|
||||
### MVP offline mode
|
||||
|
||||
- Download planned route, POIs, stage plan, rules, and GPX.
|
||||
- Allow map viewing if tile pack is present.
|
||||
- Allow report capture and sync later.
|
||||
- Allow basic distance-to-next-critical-thing calculation from cached data.
|
||||
|
||||
### Production offline mode
|
||||
|
||||
- Offline rerouting using a compact regional routing graph.
|
||||
- Offline POI search.
|
||||
- Offline rule lookup.
|
||||
- Offline elevation sampling.
|
||||
- Offline exports.
|
||||
|
||||
## Storage model
|
||||
|
||||
Mobile app storage:
|
||||
|
||||
- SQLite for structured trip data and POIs.
|
||||
- File storage for tile packs and exports.
|
||||
- Key-value storage for user preferences and sync state.
|
||||
|
||||
## Pack versioning
|
||||
|
||||
Each offline pack should include:
|
||||
|
||||
```json
|
||||
{
|
||||
"pack_id": "pack_123",
|
||||
"trip_id": "trip_123",
|
||||
"created_at": "2026-06-30T00:00:00Z",
|
||||
"data_versions": {
|
||||
"osm_extract": "geofabrik-europe-germany-2026-06-29",
|
||||
"poi_index": "2026-06-29",
|
||||
"rules": "2026-06-01",
|
||||
"weather_cached_at": "2026-06-30T06:00:00Z"
|
||||
},
|
||||
"bbox": [6.0, 47.0, 15.0, 55.0],
|
||||
"route_buffer_km": 5,
|
||||
"expires_at": "2026-07-14T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## User-facing warnings
|
||||
|
||||
Before departure, show:
|
||||
|
||||
- which items are available offline,
|
||||
- which items are stale,
|
||||
- which route sections lack cached POIs,
|
||||
- whether offline rerouting is available,
|
||||
- which exports are saved.
|
||||
108
docs/07_ux_flows.md
Normal file
108
docs/07_ux_flows.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# UX Flows
|
||||
|
||||
## Main app surfaces
|
||||
|
||||
### 1. Trip planner
|
||||
|
||||
Map plus side panel:
|
||||
|
||||
- start/end/import GPX,
|
||||
- dates,
|
||||
- bike/load type,
|
||||
- daily target,
|
||||
- surface preference,
|
||||
- sleep preference,
|
||||
- water/food interval,
|
||||
- routing strictness,
|
||||
- bailout preference.
|
||||
|
||||
Output:
|
||||
|
||||
- route line,
|
||||
- stage cards,
|
||||
- warnings,
|
||||
- POI layer toggles,
|
||||
- export/offline actions.
|
||||
|
||||
### 2. Stage timeline
|
||||
|
||||
A vertical list of days:
|
||||
|
||||
```text
|
||||
Day 1 — 74 km — 1,150 m climb — 38% unpaved
|
||||
Sleep: campsite at km 72, hostel at km 78
|
||||
Water: km 18, 51, 69
|
||||
Food: supermarket km 42, bakery km 63
|
||||
Warning: last reliable water before 11 km climb
|
||||
Bailout: train station +5 km from route at km 58
|
||||
```
|
||||
|
||||
### 3. Riding mode
|
||||
|
||||
Large simple panel:
|
||||
|
||||
```text
|
||||
Next water: 12.4 km
|
||||
Next food: 28.0 km, closes 18:00
|
||||
Sleep Plan A: 31.5 km
|
||||
Daylight left: 3h 40m
|
||||
Bailout: train station 9.1 km detour
|
||||
Warning: remote section starts in 6 km
|
||||
```
|
||||
|
||||
Actions:
|
||||
|
||||
- reroute to water,
|
||||
- reroute to sleep,
|
||||
- skip climb,
|
||||
- find bike shop,
|
||||
- find bailout,
|
||||
- report issue.
|
||||
|
||||
### 4. POI detail card
|
||||
|
||||
For a water point:
|
||||
|
||||
```text
|
||||
Village fountain
|
||||
Type: drinking water
|
||||
Distance: 12.4 km on route
|
||||
Confidence: Medium
|
||||
Last confirmed: 18 days ago
|
||||
Notes: Tap on cemetery wall; sometimes locked after 20:00
|
||||
Actions: Navigate / Save / Report unavailable
|
||||
```
|
||||
|
||||
### 5. Rule card
|
||||
|
||||
```text
|
||||
Wild camping rule — Bavaria, Germany
|
||||
Status: Restricted / unclear
|
||||
Summary: Overnight camping outside designated sites may be restricted. Bivouac rules vary by land type and protected areas.
|
||||
Confidence: Medium
|
||||
Source: official/regional source URL
|
||||
Last reviewed: 2026-06-01
|
||||
App advice: prefer listed campsites/shelters; avoid protected-area bivouac unless locally permitted.
|
||||
```
|
||||
|
||||
## Map layers
|
||||
|
||||
- Route/stages.
|
||||
- Surface and roughness.
|
||||
- Legal/access confidence.
|
||||
- Water.
|
||||
- Food/resupply.
|
||||
- Sleep.
|
||||
- Repair.
|
||||
- Bailout.
|
||||
- Local reports.
|
||||
- Weather risk.
|
||||
- Protected areas/local rules.
|
||||
|
||||
## Interaction principles
|
||||
|
||||
- Always show confidence and stale data indicators.
|
||||
- Optimize for quick decisions during riding.
|
||||
- Avoid hiding critical logistics behind filters.
|
||||
- Default to route-corridor relevance instead of global POI clutter.
|
||||
- Explain routing choices with concrete reasons.
|
||||
181
docs/08_data_model.md
Normal file
181
docs/08_data_model.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Data Model
|
||||
|
||||
The authoritative DDL is in `schemas/database.sql`. This document explains the domain model.
|
||||
|
||||
## Core entities
|
||||
|
||||
### User
|
||||
|
||||
Stores account, preferences, privacy settings, and default bikepacking profile.
|
||||
|
||||
### Trip
|
||||
|
||||
A planned multi-day journey.
|
||||
|
||||
Fields:
|
||||
|
||||
- id,
|
||||
- owner_id,
|
||||
- title,
|
||||
- start/end coordinates,
|
||||
- date range,
|
||||
- profile,
|
||||
- status,
|
||||
- created_at,
|
||||
- updated_at.
|
||||
|
||||
### Route
|
||||
|
||||
A route generated for a trip.
|
||||
|
||||
Fields:
|
||||
|
||||
- id,
|
||||
- trip_id,
|
||||
- provider,
|
||||
- geometry,
|
||||
- distance,
|
||||
- ascent/descent,
|
||||
- surface breakdown,
|
||||
- access confidence,
|
||||
- warnings.
|
||||
|
||||
### Route segment
|
||||
|
||||
A normalized route chunk with scoring attributes.
|
||||
|
||||
Fields:
|
||||
|
||||
- geometry,
|
||||
- distance,
|
||||
- grade,
|
||||
- surface,
|
||||
- smoothness,
|
||||
- highway class,
|
||||
- access tags,
|
||||
- risk scores,
|
||||
- confidence.
|
||||
|
||||
### Stage
|
||||
|
||||
A daily ride slice.
|
||||
|
||||
Fields:
|
||||
|
||||
- day_index,
|
||||
- route_start_m,
|
||||
- route_end_m,
|
||||
- distance,
|
||||
- ascent,
|
||||
- estimated_time,
|
||||
- endpoint,
|
||||
- sleep candidates,
|
||||
- warnings,
|
||||
- Plan A/B.
|
||||
|
||||
### POI
|
||||
|
||||
A point of interest for logistics.
|
||||
|
||||
Categories:
|
||||
|
||||
- water,
|
||||
- food,
|
||||
- sleep,
|
||||
- repair,
|
||||
- bailout,
|
||||
- charging,
|
||||
- emergency.
|
||||
|
||||
### Service gap
|
||||
|
||||
A computed gap between relevant POIs along the route.
|
||||
|
||||
Fields:
|
||||
|
||||
- type,
|
||||
- start_m,
|
||||
- end_m,
|
||||
- distance,
|
||||
- severity,
|
||||
- explanation.
|
||||
|
||||
### Local report
|
||||
|
||||
A typed, dated user/local report.
|
||||
|
||||
Fields:
|
||||
|
||||
- report type,
|
||||
- geometry/point,
|
||||
- route segment optional,
|
||||
- payload,
|
||||
- trust score,
|
||||
- expiry date,
|
||||
- moderation status.
|
||||
|
||||
### Rule card
|
||||
|
||||
A localized advisory card about riding/camping/access/fire/protected areas.
|
||||
|
||||
Fields:
|
||||
|
||||
- jurisdiction,
|
||||
- rule type,
|
||||
- summary,
|
||||
- status,
|
||||
- confidence,
|
||||
- source URL,
|
||||
- last reviewed,
|
||||
- geometry.
|
||||
|
||||
### Offline pack
|
||||
|
||||
A generated set of data for a trip.
|
||||
|
||||
Fields:
|
||||
|
||||
- trip,
|
||||
- bbox,
|
||||
- corridor buffer,
|
||||
- included layers,
|
||||
- version metadata,
|
||||
- file references,
|
||||
- status.
|
||||
|
||||
## Important modeling choices
|
||||
|
||||
### Route distance index
|
||||
|
||||
Store positions along a route as `meters_from_start`. This allows POIs, warnings, reports, and stage boundaries to attach to the route even when coordinates are simplified.
|
||||
|
||||
### Confidence levels
|
||||
|
||||
Use a normalized enum:
|
||||
|
||||
- `known_good`,
|
||||
- `high`,
|
||||
- `medium`,
|
||||
- `low`,
|
||||
- `unknown`,
|
||||
- `restricted`,
|
||||
- `conflicting`.
|
||||
|
||||
### Warning severity
|
||||
|
||||
Use:
|
||||
|
||||
- `info`,
|
||||
- `notice`,
|
||||
- `warning`,
|
||||
- `critical`.
|
||||
|
||||
### Report expiration
|
||||
|
||||
Most local reports should expire unless reconfirmed:
|
||||
|
||||
- water status: 30–90 days,
|
||||
- closure: 7–60 days depending source,
|
||||
- surface condition: 14–90 days,
|
||||
- access/legal: reviewed manually,
|
||||
- sleep hints: 90–365 days.
|
||||
121
docs/09_api_contract.md
Normal file
121
docs/09_api_contract.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# API Contract
|
||||
|
||||
The machine-readable OpenAPI draft is in `schemas/openapi.yaml`.
|
||||
|
||||
## Core endpoints
|
||||
|
||||
### Create trip
|
||||
|
||||
`POST /v1/trips`
|
||||
|
||||
Creates a trip shell from user inputs.
|
||||
|
||||
### Plan route
|
||||
|
||||
`POST /v1/routes/plan`
|
||||
|
||||
Input:
|
||||
|
||||
- start/end/imported GPX,
|
||||
- profile,
|
||||
- constraints,
|
||||
- preferred providers.
|
||||
|
||||
Output:
|
||||
|
||||
- route id,
|
||||
- geometry,
|
||||
- distance/elevation,
|
||||
- scores,
|
||||
- warnings,
|
||||
- candidate alternatives.
|
||||
|
||||
### Plan stages
|
||||
|
||||
`POST /v1/stages/plan`
|
||||
|
||||
Input:
|
||||
|
||||
- route id,
|
||||
- day count/date range,
|
||||
- daily constraints,
|
||||
- sleep preferences.
|
||||
|
||||
Output:
|
||||
|
||||
- stage cards,
|
||||
- Plan A/B endpoints,
|
||||
- sleep/food/water/repair/bailout candidates,
|
||||
- stage warnings.
|
||||
|
||||
### Corridor POIs
|
||||
|
||||
`GET /v1/routes/{route_id}/pois?category=water&buffer_km=5`
|
||||
|
||||
Returns route-relevant POIs with distance along route, detour distance, confidence, and source.
|
||||
|
||||
### Critical gaps
|
||||
|
||||
`GET /v1/routes/{route_id}/gaps`
|
||||
|
||||
Returns computed gaps for water, food, sleep, repair, bailout, and charging.
|
||||
|
||||
### Rule cards
|
||||
|
||||
`GET /v1/rules?bbox=minLon,minLat,maxLon,maxLat&route_id=...`
|
||||
|
||||
Returns route- or area-specific advisory cards.
|
||||
|
||||
### Offline pack
|
||||
|
||||
`POST /v1/offline-packs`
|
||||
|
||||
Generates a manifest and download URLs for cached trip data.
|
||||
|
||||
### Export
|
||||
|
||||
`GET /v1/routes/{route_id}/export?format=gpx`
|
||||
|
||||
MVP: GPX. Later: TCX and FIT.
|
||||
|
||||
### Local report
|
||||
|
||||
`POST /v1/reports`
|
||||
|
||||
Submits a dated, location-bound structured report. The MVP response includes `moderationStatus`, `trustScore`, and `queuedOffline` when an offline client id is supplied.
|
||||
|
||||
### Report sync
|
||||
|
||||
`POST /v1/reports/sync`
|
||||
|
||||
Future endpoint. The current MVP queues reports client-side while offline and resubmits them through `POST /v1/reports`.
|
||||
|
||||
## Error handling
|
||||
|
||||
Errors should include:
|
||||
|
||||
- machine-readable code,
|
||||
- human-readable message,
|
||||
- remediation suggestion,
|
||||
- provider/source if relevant.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "PROVIDER_UNAVAILABLE",
|
||||
"message": "routing provider \"openrouteservice\" is not available in this MVP runtime. Set ROUTING_PROVIDER=mock for fixture mode or configure the selected provider adapter and credentials.",
|
||||
"details": {
|
||||
"providerName": "openrouteservice",
|
||||
"providerType": "routing",
|
||||
"setupHint": "Set ROUTING_PROVIDER=mock for fixture mode or configure the selected provider adapter and credentials."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Current MVP notes
|
||||
|
||||
- `schemas/openapi.yaml` reflects implemented response fields including route segments, surface breakdown, attribution, stage POI buckets, offline manifest metadata, and report queue ids.
|
||||
- `format=gpx` is implemented. TCX/FIT are reserved for future `DeviceExportProvider` adapters.
|
||||
- Mock providers are deterministic and require no external keys.
|
||||
- Rule cards and access/protected-area warnings are advisory and confidence-scored.
|
||||
70
docs/10_integrations.md
Normal file
70
docs/10_integrations.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Integrations
|
||||
|
||||
## Routing integrations
|
||||
|
||||
Use provider adapters.
|
||||
|
||||
### Prototype
|
||||
|
||||
- openrouteservice API adapter.
|
||||
- Mock adapter for tests.
|
||||
|
||||
### Production
|
||||
|
||||
- GraphHopper or Valhalla self-hosted adapter.
|
||||
- Custom bikepacking profile layer on top of base routing.
|
||||
- Offline routing adapter later.
|
||||
|
||||
## Map integrations
|
||||
|
||||
- MapLibre-compatible rendering.
|
||||
- Vector tiles from OpenMapTiles, Protomaps/PMTiles, MapTiler, or self-hosted pipeline.
|
||||
- OSM attribution must be visible.
|
||||
|
||||
## Accommodation integrations
|
||||
|
||||
MVP should use:
|
||||
|
||||
- OSM campsites/shelters/huts/hostels/hotels,
|
||||
- deep links to search platforms,
|
||||
- manual entries/imports for partner datasets.
|
||||
|
||||
Later:
|
||||
|
||||
- Booking.com Demand API if accepted as partner,
|
||||
- direct campsite/hut reservation systems,
|
||||
- Warmshowers-style partner/deep links if official access exists.
|
||||
|
||||
## Weather integrations
|
||||
|
||||
MVP:
|
||||
|
||||
- forecast at stage endpoints and exposed segments.
|
||||
- warnings for heat, rain, wind, storms, freezing nights.
|
||||
|
||||
Later:
|
||||
|
||||
- route-time weather simulation,
|
||||
- weather-aware rerouting,
|
||||
- mud risk after rainfall.
|
||||
|
||||
## Device integrations
|
||||
|
||||
MVP:
|
||||
|
||||
- GPX export.
|
||||
|
||||
Next:
|
||||
|
||||
- TCX export with course points.
|
||||
- FIT export.
|
||||
|
||||
Later:
|
||||
|
||||
- Garmin Courses API subject to approval.
|
||||
- Wahoo Cloud API subject to approval and use-case fit.
|
||||
- Hammerhead/Karoo sync if public/partner APIs allow.
|
||||
|
||||
## Authentication and partnerships
|
||||
|
||||
Do not assume public access to commercial APIs. Use deep links first and provider interfaces so partner integrations can be added without changing the domain model.
|
||||
78
docs/11_local_rules_and_liability.md
Normal file
78
docs/11_local_rules_and_liability.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Local Rules and Liability
|
||||
|
||||
## Principle
|
||||
|
||||
Rules must be shown as advisory information with source, date, jurisdiction, confidence, and limits.
|
||||
|
||||
Do not claim legal certainty unless the rule comes from a current official source and the geographic/jurisdiction match is clear.
|
||||
|
||||
## Rule categories
|
||||
|
||||
- cycling access,
|
||||
- trail access,
|
||||
- private land,
|
||||
- protected area,
|
||||
- wild camping,
|
||||
- bivouac,
|
||||
- fire bans,
|
||||
- e-bike access/class,
|
||||
- ferry/border constraints,
|
||||
- seasonal closures,
|
||||
- hunting/forestry closures,
|
||||
- drone restrictions if relevant.
|
||||
|
||||
## Confidence states
|
||||
|
||||
- `known_allowed`,
|
||||
- `known_restricted`,
|
||||
- `seasonal_or_conditional`,
|
||||
- `likely_allowed`,
|
||||
- `likely_restricted`,
|
||||
- `unclear`,
|
||||
- `conflicting_sources`,
|
||||
- `needs_local_confirmation`.
|
||||
|
||||
## Source hierarchy
|
||||
|
||||
Prefer:
|
||||
|
||||
1. official authority datasets/pages,
|
||||
2. protected-area authority pages,
|
||||
3. national/regional open data portals,
|
||||
4. OSM access tags,
|
||||
5. partner/local expert data,
|
||||
6. user reports.
|
||||
|
||||
## User-facing copy examples
|
||||
|
||||
### Access warning
|
||||
|
||||
```text
|
||||
Access uncertainty ahead
|
||||
This forest track has incomplete bicycle access data and crosses a protected-area boundary. Use caution and follow local signs.
|
||||
```
|
||||
|
||||
### Camping warning
|
||||
|
||||
```text
|
||||
Wild-camping rules unclear
|
||||
This area may restrict overnight camping outside designated sites. Prefer listed campsite/shelter options unless you have local permission.
|
||||
```
|
||||
|
||||
### Seasonal closure
|
||||
|
||||
```text
|
||||
Possible seasonal restriction
|
||||
This segment overlaps a protected area. Check local signs and current authority notices before entering.
|
||||
```
|
||||
|
||||
## Liability mitigations
|
||||
|
||||
- Show source and review date.
|
||||
- Show uncertainty.
|
||||
- Provide alternatives.
|
||||
- Let users report errors.
|
||||
- Avoid routing through known restricted/private segments by default.
|
||||
- Keep critical legal rules server-updatable.
|
||||
- Do not monetize illegal camping hints.
|
||||
- Moderate sensitive reports.
|
||||
80
docs/12_community_intel.md
Normal file
80
docs/12_community_intel.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Community and Local Intelligence
|
||||
|
||||
## Objective
|
||||
|
||||
Turn field reports into a structured, trust-scored, time-aware route quality layer.
|
||||
|
||||
## Report types
|
||||
|
||||
- `water_available`
|
||||
- `water_unavailable`
|
||||
- `surface_wrong`
|
||||
- `rough_loaded_bike`
|
||||
- `hike_a_bike`
|
||||
- `locked_gate`
|
||||
- `private_access`
|
||||
- `closure`
|
||||
- `dangerous_dogs`
|
||||
- `mud_sand_washout`
|
||||
- `bridge_out`
|
||||
- `ferry_issue`
|
||||
- `sleep_option_good`
|
||||
- `sleep_option_bad`
|
||||
- `shop_closed_or_missing`
|
||||
- `repair_available`
|
||||
- `reroute_recommended`
|
||||
|
||||
## Report payload example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "water_unavailable",
|
||||
"location": { "lat": 47.1234, "lon": 11.5678 },
|
||||
"route_id": "route_123",
|
||||
"meters_from_start": 84231,
|
||||
"observed_at": "2026-06-30T14:30:00Z",
|
||||
"details": "Tap locked; no public access after 18:00.",
|
||||
"photo_optional": true
|
||||
}
|
||||
```
|
||||
|
||||
## Trust model
|
||||
|
||||
Signals:
|
||||
|
||||
- account age,
|
||||
- number of confirmed reports,
|
||||
- local status,
|
||||
- photo/GPS evidence,
|
||||
- agreement with other riders,
|
||||
- recency,
|
||||
- conflict count.
|
||||
|
||||
## Expiry model
|
||||
|
||||
Reports should not live forever.
|
||||
|
||||
Default expiration:
|
||||
|
||||
- water status: 60 days,
|
||||
- closures: 30 days,
|
||||
- mud/surface condition: 30 days,
|
||||
- locked gate: 90 days,
|
||||
- shop status: 90 days,
|
||||
- legal/access reports: manual review,
|
||||
- local hints: 180 days.
|
||||
|
||||
## Moderation
|
||||
|
||||
Moderate:
|
||||
|
||||
- illegal camping instructions,
|
||||
- private property entry hints,
|
||||
- sensitive locations,
|
||||
- abuse/harassment,
|
||||
- unsafe advice,
|
||||
- business defamation.
|
||||
|
||||
## OSM feedback loop
|
||||
|
||||
Objective, verifiable corrections can be contributed back to OSM by trained editors following OSM community norms. Subjective suitability, safety, and camping hints should remain in the app layer unless they map to accepted OSM tags and are verifiable.
|
||||
54
docs/13_security_privacy.md
Normal file
54
docs/13_security_privacy.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Security and Privacy
|
||||
|
||||
## Sensitive data
|
||||
|
||||
The app may process:
|
||||
|
||||
- location history,
|
||||
- planned travel dates,
|
||||
- sleep locations,
|
||||
- emergency contacts,
|
||||
- account identity,
|
||||
- API tokens,
|
||||
- community reports,
|
||||
- booking/deep-link actions.
|
||||
|
||||
## Privacy requirements
|
||||
|
||||
- Default trips to private.
|
||||
- Let users delete trips and reports where legally possible.
|
||||
- Do not share exact sleep plans publicly by default.
|
||||
- Minimize continuous location collection.
|
||||
- Allow offline use without constant tracking.
|
||||
- Separate analytics from precise route history.
|
||||
- Hash/anonymize telemetry where possible.
|
||||
|
||||
## Security requirements
|
||||
|
||||
- Store secrets in environment variables or secret manager.
|
||||
- Use short-lived signed URLs for offline-pack downloads.
|
||||
- Validate GPX uploads.
|
||||
- Sanitize user-generated content.
|
||||
- Rate-limit report submission.
|
||||
- Protect against route/POI scraping if commercial data is included.
|
||||
- Keep provider API keys server-side.
|
||||
|
||||
## Compliance notes
|
||||
|
||||
For EU users, assume GDPR obligations:
|
||||
|
||||
- explicit consent for location tracking,
|
||||
- data export/deletion,
|
||||
- purpose limitation,
|
||||
- retention policy,
|
||||
- processor agreements for analytics/cloud vendors.
|
||||
|
||||
## Safety disclaimers
|
||||
|
||||
Show concise warnings:
|
||||
|
||||
- route data may be wrong,
|
||||
- access rules can change,
|
||||
- weather forecasts are uncertain,
|
||||
- users must obey signs and local laws,
|
||||
- remote riding requires judgment and preparation.
|
||||
63
docs/14_testing_plan.md
Normal file
63
docs/14_testing_plan.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Testing Plan
|
||||
|
||||
## Unit tests
|
||||
|
||||
### Scoring
|
||||
|
||||
- penalizes steep loose climbs for loaded gravel profile;
|
||||
- allows rougher segments for hardtail profile;
|
||||
- penalizes unknown access;
|
||||
- rewards official cycle routes;
|
||||
- increases severity for long water gaps;
|
||||
- detects no sleep options near target endpoint.
|
||||
|
||||
### Staging
|
||||
|
||||
- splits route into daily ranges;
|
||||
- avoids impossible climbing days;
|
||||
- chooses endpoints with sleep candidates;
|
||||
- produces Plan B endpoints;
|
||||
- rebalances when one day exceeds constraints.
|
||||
|
||||
### POI corridor
|
||||
|
||||
- finds POIs within buffer;
|
||||
- sorts by distance along route;
|
||||
- deduplicates overlapping sources;
|
||||
- computes detour distance;
|
||||
- respects category filters.
|
||||
|
||||
### Offline manifest
|
||||
|
||||
- includes required layers;
|
||||
- records source versions;
|
||||
- flags stale data;
|
||||
- supports report sync queue.
|
||||
|
||||
## Integration tests
|
||||
|
||||
- route planning provider returns normalized geometry;
|
||||
- stage planner consumes route geometry and POIs;
|
||||
- GPX export round-trips with common viewers;
|
||||
- API returns consistent warnings from fixtures;
|
||||
- map renders route/stages/POIs.
|
||||
|
||||
## Fixture tests
|
||||
|
||||
Use sample fixtures in `examples/`:
|
||||
|
||||
- simple 2-day route,
|
||||
- remote route with water gap,
|
||||
- route with uncertain access,
|
||||
- route with sleep endpoints,
|
||||
- route with steep rough segment.
|
||||
|
||||
## Manual QA scenarios
|
||||
|
||||
1. Plan 3-day trip with campsites only.
|
||||
2. Plan 5-day trip with indoor sleep every third night.
|
||||
3. Import GPX and ask app to stage it.
|
||||
4. Download offline pack and simulate airplane mode.
|
||||
5. Submit water-unavailable report offline and sync later.
|
||||
6. Export GPX and import into Garmin Connect or another route viewer.
|
||||
7. Check that legal/rule warnings show source and uncertainty.
|
||||
58
docs/15_roadmap.md
Normal file
58
docs/15_roadmap.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Roadmap
|
||||
|
||||
## Phase 0 — Repository and design foundation
|
||||
|
||||
- Create monorepo.
|
||||
- Implement shared domain types.
|
||||
- Add mock data fixtures.
|
||||
- Add scoring/staging unit tests.
|
||||
|
||||
## Phase 1 — Web planner MVP
|
||||
|
||||
- Map UI.
|
||||
- Trip request form.
|
||||
- Route rendering.
|
||||
- Stage cards.
|
||||
- POI corridor display.
|
||||
- Critical gap warnings.
|
||||
- GPX export.
|
||||
|
||||
## Phase 2 — Backend MVP
|
||||
|
||||
- Route planning endpoint.
|
||||
- Provider abstraction.
|
||||
- Stage planner endpoint.
|
||||
- POI corridor endpoint.
|
||||
- Offline manifest endpoint.
|
||||
- Report endpoint.
|
||||
|
||||
## Phase 3 — Real data integration
|
||||
|
||||
- OSM extract import.
|
||||
- POI normalization.
|
||||
- Elevation enrichment.
|
||||
- Hosted/self-hosted routing engine adapter.
|
||||
- Rule card ingestion for one pilot region.
|
||||
|
||||
## Phase 4 — Mobile/offline MVP
|
||||
|
||||
- Mobile route/stage viewer.
|
||||
- Offline trip cache.
|
||||
- Next-critical-thing panel.
|
||||
- Offline report queue.
|
||||
- Basic reroute to cached POI or external navigation deep link.
|
||||
|
||||
## Phase 5 — Advanced bikepacking intelligence
|
||||
|
||||
- Segment-level suitability scoring from ridden data.
|
||||
- Trusted local reports.
|
||||
- Weather-aware warnings.
|
||||
- Sleep reliability score.
|
||||
- Adaptive route planning based on actual rider speed.
|
||||
|
||||
## Phase 6 — Partnerships and device sync
|
||||
|
||||
- Accommodation partner APIs/deep links.
|
||||
- Garmin/Wahoo integration subject to approval.
|
||||
- Hut/campsite partner feeds.
|
||||
- Regional tourism board routes and rules.
|
||||
91
docs/source_references.md
Normal file
91
docs/source_references.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Source References
|
||||
|
||||
Verified on 2026-06-30. Check terms again before production use.
|
||||
|
||||
## Baseline map/routing data
|
||||
|
||||
- Komoot support: the Komoot map is based on OpenStreetMap data for map display, route planning, and POIs.
|
||||
https://support.komoot.com/hc/en-us/articles/10194668255258-Improve-the-komoot-Map
|
||||
|
||||
- OpenStreetMap ODbL license information.
|
||||
https://wiki.openstreetmap.org/wiki/Open_Database_License
|
||||
https://osmfoundation.org/wiki/Licence/Licence_and_Legal_FAQ
|
||||
|
||||
- OSM tile usage policy: OSM data is free; public tile servers are capacity-limited and not for heavy production app traffic.
|
||||
https://operations.osmfoundation.org/policies/tiles/
|
||||
|
||||
- Geofabrik regional OSM extracts.
|
||||
https://download.geofabrik.de/
|
||||
https://www.geofabrik.de/data/download.html
|
||||
|
||||
- Planet OSM weekly full database dump.
|
||||
https://planet.openstreetmap.org/
|
||||
https://wiki.openstreetmap.org/wiki/Planet.osm
|
||||
|
||||
- Overpass API.
|
||||
https://wiki.openstreetmap.org/wiki/Overpass_API
|
||||
|
||||
## Routing engines
|
||||
|
||||
- openrouteservice API and backend docs.
|
||||
https://openrouteservice.org/
|
||||
https://giscience.github.io/openrouteservice/api-reference/endpoints/directions/
|
||||
|
||||
- GraphHopper routing engine.
|
||||
https://github.com/graphhopper/graphhopper
|
||||
|
||||
- Valhalla routing engine.
|
||||
https://github.com/valhalla/valhalla
|
||||
https://valhalla.github.io/valhalla/api/turn-by-turn/overview/
|
||||
|
||||
- BRouter offline bicycle routing.
|
||||
https://brouter.de/brouter/
|
||||
https://brouter.de/brouter/offline.html
|
||||
|
||||
## Elevation
|
||||
|
||||
- Copernicus DEM GLO-30/GLO-90.
|
||||
https://dataspace.copernicus.eu/explore-data/data-collections/copernicus-contributing-missions/collections-description/COP-DEM
|
||||
|
||||
- NASA SRTM.
|
||||
https://www.earthdata.nasa.gov/data/instruments/srtm
|
||||
|
||||
## Map display and offline map options
|
||||
|
||||
- MapLibre GL JS.
|
||||
https://maplibre.org/
|
||||
https://www.maplibre.org/maplibre-gl-js/docs/
|
||||
|
||||
- OpenMapTiles.
|
||||
https://openmaptiles.org/
|
||||
|
||||
- Protomaps / PMTiles.
|
||||
https://protomaps.com/
|
||||
https://docs.protomaps.com/guide/getting-started
|
||||
|
||||
## POIs, rules, weather, accommodation
|
||||
|
||||
- Overture Maps Places.
|
||||
https://docs.overturemaps.org/guides/places/
|
||||
|
||||
- Protected Planet / WDPA/WDPCA.
|
||||
https://www.protectedplanet.net/en/thematic-areas/wdpa
|
||||
https://www.protectedplanet.net/en
|
||||
|
||||
- Open-Meteo Forecast API.
|
||||
https://open-meteo.com/en/docs
|
||||
|
||||
- Booking.com Demand API.
|
||||
https://developers.booking.com/demand
|
||||
https://developers.booking.com/demand/docs/getting-started/overview
|
||||
|
||||
## Device integrations
|
||||
|
||||
- Garmin Courses API.
|
||||
https://developer.garmin.com/gc-developer-program/courses-api/
|
||||
|
||||
- Garmin Connect course file import.
|
||||
https://support.garmin.com/en-US/?faq=wKuZXCaZRP4mWPX5aRz5h5
|
||||
|
||||
- Wahoo Cloud API.
|
||||
https://developers.wahooligan.com/cloud
|
||||
Reference in New Issue
Block a user