Feature spec
AdvancedCategory
maps-location
Build with AI
8–14 hours with Lovable (web) or FlutterFlow (mobile) + manual Edge Function work
Custom build
2–4 weeks custom dev
Running cost
$0/mo up to ~1K users · $25–75/mo at 10K users
Works on
Everything it takes to ship a Dynamic Map Route Planner — parts, prompts, and real costs.
A dynamic route planner needs four pieces: a waypoint input with address autocomplete, a Directions API call proxied through an Edge Function to hide your key, a route polyline drawn on the map, and an optional turn-by-turn instruction panel. With Lovable or V0 you can ship a working A-to-B web planner in 8–14 hours. The Mapbox Directions API is free up to 100K requests per month — costs only appear past 10K active users.
What a Dynamic Map Route Planner Actually Is
A route planner turns your map from a static display into a navigation tool: users enter an origin and destination, the app draws a coloured polyline showing the fastest path, and a panel lists every turn they need to make. The feature lives on top of a base map (Mapbox or Google Maps) and calls a Directions API to compute the route geometry. The real product decisions are multi-stop support, travel mode (driving, walking, cycling), re-routing when the user goes off-course, and whether routes should be saved to user history. AI tools handle the A-to-B case well; re-routing and waypoint reordering are where they need manual help.
What users consider table stakes in 2026
- Route polyline appears on the map within 2 seconds of entering a destination, not after a full page reload
- Estimated time and distance shown before the user commits — never surprise them after tapping 'Go'
- Multiple waypoints supported with drag-to-reorder, not just a fixed origin and destination
- Driving, walking, and cycling mode toggle that recalculates the route instantly when switched
- Shareable deeplink URL that encodes all waypoints so users can send the exact route to someone else
- Mobile app recalculates automatically when GPS position deviates more than 50 metres from the planned route
Anatomy of the Feature
Six components — the waypoint input and API proxy are where AI builds most often fall short. Get those right and everything else assembles quickly.
Waypoint input with autocomplete
UIOrigin, destination, and optional intermediate stop fields with address autocomplete. On web: shadcn/ui Combobox wired to the Mapbox Search Box JS SDK or Google Places Autocomplete JS library. On Flutter: TypeAheadField widget (flutter_typeahead package) with a debounced HTTP call to the autocomplete endpoint — debounce at 300ms so you are not firing on every keystroke.
Note: Autocomplete is bundled in Mapbox and Google billing — no separate service needed, but each suggestion counts toward API usage.
Directions API proxy (Edge Function)
BackendA Supabase Edge Function that receives sanitised waypoints from the frontend, calls the Mapbox Directions API (or Google Maps Directions API) using a secret key stored in Deno.env.get('MAPBOX_SECRET_TOKEN'), and returns the GeoJSON LineString response. Profiles supported: mapbox/driving, mapbox/walking, mapbox/cycling. Never expose the secret key in client-side code — network tab inspection takes seconds.
Note: This is the most common gap in AI-generated route planners. The prompt must explicitly say 'proxy via Edge Function' or the AI will call the API directly from the browser.
Route renderer
UIDraws the route polyline over the base map tiles. On web with Mapbox GL JS: addSource() with a GeoJSON LineString, then addLayer() with a line type — colour, width, and optional dash pattern set here. On Flutter with flutter_map: PolylineLayer that accepts a list of LatLng coordinates decoded from the Directions API response. The route line should be visually distinct from the base map — 5px width, brand colour.
Note: Animate the polyline with a moving dash effect to communicate active navigation; Mapbox GL JS supports this via line-dasharray and a requestAnimationFrame loop.
Turn-by-turn instruction panel
UIAn ordered list of maneuver steps from the Directions API 'legs[].steps[]' response. Each step has a maneuver type (turn-left, turn-right, straight, arrive), distance, and instruction text. On Flutter: ListView.builder with an icon from a maneuver-type → icon map. On web: a scrollable React list. The current active step should highlight as the user progresses along the route.
Note: The Mapbox Directions API returns human-readable instruction strings ready to display — no custom string formatting needed.
Route state store
DataClient-side state holding: origin (name + lat/lng), destination (name + lat/lng), waypoints array, selected travel mode, the fetched route GeoJSON, and the decoded steps array. In React: useState or Zustand. In Flutter: Provider or Riverpod page state. Optionally persisted to Supabase 'saved_routes' table so the user can revisit past routes from their history screen.
Note: Do not store the full GeoJSON in Supabase — extract only the essential fields (origin_name, destination_name, waypoints jsonb, distance_m, duration_s) for the saved record.
Re-routing engine (mobile)
BackendMobile-only: a Dart stream from the geolocator package compares the user's current LatLng to the nearest point on the route polyline. When deviation exceeds 50 metres, the app calls the Edge Function again with the current GPS position as the new origin and the remaining waypoints. The geodesy package provides the Haversine distance calculation. On web, re-routing is not applicable.
Note: This component requires a custom Dart action in FlutterFlow — it cannot be wired visually. Do not promise re-routing on a FlutterFlow build without custom code block budget.
The data model
The data model is optional — a basic route planner works entirely with client-side state. Add the 'saved_routes' table if users need route history. Run this SQL in the Supabase SQL editor (Database → SQL Editor → New query):
1create table public.saved_routes (2 id uuid primary key default gen_random_uuid(),3 user_id uuid references auth.users(id) on delete cascade not null,4 origin_name text not null,5 destination_name text not null,6 waypoints jsonb not null default '[]'::jsonb,7 mode text not null default 'driving' check (mode in ('driving','walking','cycling')),8 distance_m int,9 duration_s int,10 created_at timestamptz not null default now()11);1213alter table public.saved_routes enable row level security;1415create policy "Users can view own saved routes"16 on public.saved_routes for select17 using (auth.uid() = user_id);1819create policy "Users can insert own saved routes"20 on public.saved_routes for insert21 with check (auth.uid() = user_id);2223create policy "Users can delete own saved routes"24 on public.saved_routes for delete25 using (auth.uid() = user_id);2627create index saved_routes_user_recent_idx28 on public.saved_routes (user_id, created_at desc);Heads up: The waypoints column stores intermediate stops as a JSONB array of {name, lat, lng} objects. The index on (user_id, created_at desc) keeps the history screen fast even after a user accumulates hundreds of saved routes.
Build it — pick your path
Each tool fits this feature differently. Switch tabs to compare fit, time, the exact steps, and a copy-paste prompt.
Required when routing is the core product: fleet tracking with live deviation alerts, isochrone maps, route optimisation across 10+ waypoints, or offline route caching for expeditions and fieldwork.
Step by step
- 1Flutter app: flutter_map + Mapbox Directions API + geodesy package for Haversine deviation checks; geolocator stream for real-time GPS; Workmanager for background position tracking so re-routing continues when the app is backgrounded
- 2Supabase saved_routes table with full GeoJSON stored as jsonb for route replay; PostGIS for spatial queries like 'find all routes that pass through this bounding box'
- 3For 10+ waypoint optimisation: Mapbox Optimization API (not the standard Directions API) or a custom TSP solver on the server — reduces driving distance by 20–40% for delivery runs
- 4Offline route caching: download and store MBTiles for a bounding box via Mapbox Offline Downloads SDK; store route GeoJSON in local SQLite so navigation continues with no connectivity
Where this path bites
- Re-routing with smooth polyline transition requires careful state management — naively replacing the source causes a flash
- App Store and Google Play review is more thorough for apps using background location — budget 2–4 additional weeks for the review cycle
- Mapbox Optimization API costs more than the Directions API and has a 12-waypoint limit per request
Third-party services you'll need
Route planning requires at least one mapping service. The Mapbox Directions API is the most cost-effective starting point — 100K free requests per month covers most early-stage apps.
| Service | What it does | Free tier | Paid from |
|---|---|---|---|
| Mapbox Directions API | Route polyline + turn-by-turn instructions for driving, walking, and cycling profiles | 100K requests/mo free | $1.00 per 1K requests after free tier (approx) |
| Google Maps Directions API | Alternative routing engine with transit mode support; required for transit (bus/subway) routing | $200/mo credit (~40K requests) | $5 per 1K requests after credit (approx) |
| Mapbox Search Box API / Google Places Autocomplete | Address autocomplete for origin and destination fields | Bundled with Mapbox/Google Maps billing | See Mapbox or Google Maps Platform pricing |
| Supabase | Saved route storage + Edge Function to proxy Directions API key | Free tier (500MB DB, 2 Edge Functions) | Pro $25/mo |
Swipe the table sideways to see pricing.
What it costs to run
Drag through the tiers to see how your monthly bill scales with users — no surprises later.
Estimated monthly running cost
Mapbox 100K free requests/mo comfortably covers 100 users averaging fewer than 1K route lookups/mo each. Supabase free tier covers saved routes and Edge Function invocations.
Estimates use verified 2026 pricing and assume typical usage per user. Your real bill depends on activity, storage, and third-party plans.
What breaks when AI tools build this
The failures people actually hit on their first build — the symptom, why it happens, and the exact fix.
Mapbox API key exposed in browser network requests
Symptom: AI tools frequently generate a direct fetch to api.mapbox.com or maps.googleapis.com from client-side React or Flutter code. The secret API key appears in the browser's DevTools network tab and in the compiled app binary, and can be extracted and abused by anyone who inspects the page.
Fix: Always route Directions API calls through a Supabase Edge Function. The frontend sends only the sanitised waypoint list; the Edge Function reads the secret key from Deno.env.get('MAPBOX_SECRET_TOKEN') and returns the route GeoJSON. Say 'proxy via Edge Function, never call Mapbox from the frontend' explicitly in your prompt.
Route polyline renders blank in Lovable preview
Symptom: Lovable's preview runs inside a cross-origin iframe. Mapbox GL JS requires a real DOM container with a known width and height to initialise the WebGL canvas. Inside the iframe the container collapses to 0px height, the WebGL context fails to create, and the map renders as a blank white box with no error in the console.
Fix: Add an explicit height (e.g. height: 500px) to the map container div in your CSS. Then publish to the production URL and test there — the map and route polyline will render correctly on the published HTTPS domain.
FlutterFlow HTTP action returns 200 but the polyline is empty
Symptom: The Mapbox Directions API returns a deeply nested JSON structure: routes[0].geometry.coordinates is an array of [lng, lat] pairs. FlutterFlow's built-in JSON path extractor cannot reliably navigate this nesting, so the PolylineLayer points variable stays empty and nothing draws on the map — and no error is thrown.
Fix: Use a Custom Action (Dart) for the response parsing step. Call jsonDecode on the raw response body, navigate routes[0].geometry.coordinates manually, convert each [lng, lat] pair to a LatLng object (note: Mapbox returns longitude first), and set the result into a Page State variable bound to your PolylineLayer.
Multi-waypoint reordering breaks the route order
Symptom: When users drag to reorder intermediate stops, AI-generated code often fires the Directions API call before the waypoints state has been re-indexed, sending the old order. The route displayed no longer matches the waypoint list the user sees, which is confusing and potentially dangerous for navigation.
Fix: Rebuild the full waypoints array from the new sort order before triggering the Edge Function call. Use a keyed list (React key or Flutter ValueKey) to track identity across reorders, and debounce the API call by 500ms so rapid drags don't fire multiple requests.
V0 generates localStorage for saved routes, crashing on Next.js SSR
Symptom: V0 sometimes reaches for localStorage to cache saved routes between sessions. On Next.js, any component that accesses localStorage during server render throws 'ReferenceError: localStorage is not defined', breaking the entire page for all users who don't have a client-side hydration yet.
Fix: Replace localStorage with Supabase Server Action persistence (the data model above) or guard every localStorage access with 'if (typeof window !== undefined)'. The prompt in this page's V0 path explicitly specifies this guard — check the generated code to confirm it was applied.
Best practices
Always proxy the Directions API through a server-side Edge Function or Server Action — exposing a secret key in client code is a billing risk and a potential ban from the mapping provider
Fetch only the current viewport's route — do not preload alternate routes in the background unless the user explicitly requests them
Fit the map viewport to the route bounding box automatically after render so users never have to pan to find their route
Show estimated time and distance in human-readable form (23 min, 4.2 km) above the turn list — users make go/no-go decisions on this information
Debounce autocomplete keystrokes at 300ms — firing a search request on every character is wasteful and creates visual jitter in the suggestion list
Encode the full route (origin, destination, waypoints, mode) in the URL query string on every change so the back button and link sharing work without a save action
Handle the no-route-found error explicitly — certain origin/destination pairs (e.g. islands with no road bridge) return an empty routes array; display a friendly message rather than a blank map or a JavaScript exception
Cache Directions API responses client-side for the session — if a user toggles between driving and walking mode and then back, the driving route should not require a second API call
When You Need Custom Development
AI tools handle A-to-B route planning on web and basic mobile well. These workloads outgrow what Lovable, V0, or FlutterFlow can produce without significant manual intervention:
- Real-time fleet tracking where multiple vehicles' GPS positions stream in and route deviation alerts fire via push notification — requires WebSocket connections and server-side geofence evaluation, not just a one-shot Directions API call
- Route optimisation across 10 or more waypoints (delivery runs, field service) where visit order matters for total distance — requires the Mapbox Optimization API or a custom TSP solver, not the standard Directions API
- Offline route caching for expeditions, field workers, or mountaineering apps where users need navigation with zero connectivity — requires MBTiles download management and local SQLite storage, not achievable in FlutterFlow without extensive custom code
- Custom routing graph for private roads, campus paths, or warehouse aisles that do not exist on any public map — requires a self-hosted routing engine (OSRM or Valhalla) fed your own road network data
- Isochrone maps that show all areas reachable within X minutes from a starting point — a common logistics feature that uses a different API endpoint and a completely different rendering approach than a standard route polyline
RapidDev builds these features for production
Real auth, database, and payments — fixed price, delivered in weeks. You own 100% of the code.
Frequently asked questions
How do I add route planning to a mobile app with FlutterFlow?
Use flutter_map with a PolylineLayer for the map, and wire an HTTP action to a Supabase Edge Function that calls the Mapbox Directions API. The critical step most FlutterFlow builds miss is using a Custom Action (Dart) to extract the nested geometry.coordinates array from the API response — FlutterFlow's built-in JSON path extractor cannot reliably navigate it. Set the extracted LatLng list into a Page State variable and bind it to your PolylineLayer.
What is the difference between the Mapbox Directions API and Google Maps Directions API?
Both return route polylines and turn-by-turn steps, but they differ on price and coverage. Mapbox offers 100K free requests per month ($1/1K after); Google gives a $200/mo credit (~40K requests) then charges $5/1K. Google has better transit (bus/subway) routing. Mapbox has more flexible map styling and a simpler GL JS integration. For most driving/walking/cycling apps, Mapbox is the more cost-effective choice at early scale.
How do I secure my Mapbox API key in a Lovable or V0 app?
Store the secret key in Lovable's Cloud tab Secrets (or V0's Vars panel as a non-NEXT_PUBLIC_ variable) and proxy every Directions API call through a Supabase Edge Function or Next.js Server Action. The frontend only sends waypoints; the server reads the key from environment variables and returns the route. Your public (publishable) map token for tile rendering can go in a NEXT_PUBLIC_ or VITE_ variable — it is safe to expose. The secret Directions API key must never reach the browser.
Can I add multiple stops to a route planner built with AI tools?
Yes, up to 3–5 waypoints is achievable in a Lovable or V0 build. The prompt in this page's build paths specifies the waypoint array structure explicitly. Beyond 5 waypoints, or when the order of stops needs to be optimised (not just specified), you will need the Mapbox Optimization API and custom server logic — that is outside what a single AI-generated prompt reliably covers.
How do I draw a route polyline on a Mapbox map?
Call map.addSource() with a GeoJSON source containing the LineString from the Directions API response, then call map.addLayer() with type: 'line' and your paint properties (line-color, line-width). On Flutter with flutter_map, pass the decoded LatLng list to a PolylineLayer widget. In both cases, use map.fitBounds() or flutter_map's fitBounds controller method to auto-zoom the viewport to the full route extent.
Does route planning work offline?
Not with AI-generated builds. Offline route caching requires downloading map tile packages (MBTiles) and caching the route GeoJSON in local SQLite storage before the user loses connectivity. This is achievable with the Mapbox Offline Downloads SDK in a custom Flutter build, but it adds significant complexity — plan for 1–2 extra weeks of custom development and a more thorough App Store review due to the background data usage.
How much does the Mapbox Directions API cost?
The first 100,000 requests per month are free. After that, Mapbox charges approximately $1.00 per 1,000 requests. Each route calculation — regardless of the number of waypoints — counts as one request. At 10,000 active users making an average of 10 route requests each per month, you are at 100K requests and just crossing into the paid tier. The Supabase Edge Function that proxies the calls also stays within the free invocation limit at this scale.
How do I let users save their planned routes?
Insert a row into the saved_routes table (schema in this page's data model section) via a Server Action or Edge Function when the user taps 'Save Route'. Store origin_name, destination_name, the waypoints array as jsonb, mode, and the distance and duration from the Directions API response. Do not store the full GeoJSON — recalculate the route on load from the stored waypoints. RLS ensures each user sees only their own saved routes.
Need this feature production-ready?
RapidDev builds a dynamic map route planner into real apps — auth, database, payments — at $13K–$25K.
Book a free consultation30-min call. No commitment.