Logistics
The route planner plans a day's deliveries or visits. Set out the depots; the stops, with what each takes from a vehicle (in kilograms, crates, cubic metres - as many measures as you use), how long it takes and when it may be served; and the vehicles, with their capacities, shifts, a break, skills such as a tail lift or a fridge, and what they cost per kilometre, per hour and per day.
Optimise, and the routes are worked out on a background thread: every stop served at the lowest cost within every limit, optional stops left out when they cost more than they are worth, locked routes left alone. The routes are drawn over your own map; each vehicle's day is a timeline and a table; drag a stop to another route and the change in distance and cost is shown as you drag. Distances are the straight line times a road factor, or the table your own routing service gives - no road network is shipped or fetched. Driver sheets print as a PDF.
Try it with your own stops in confidence: the plan is kept in your browser, on your device. Nothing is uploaded, no copy reaches us or anyone else, and nothing is kept once you close this tab unless you export it.
A market town's deliveries
An invented town, placed out at sea so it cannot be mistaken for anywhere real, with a made-up map: 28 shops, schools and cafés to deliver to, some in a morning or afternoon window, two needing a fridge and one only if there is room; three vans and a chiller van. Plan the routes, then drag a stop from one route to another - on the map or in the list - and watch the cost change.
// Node 18 or later, from the Gold package: plan tomorrow's routes overnight from the order export.
import { readFileSync, writeFileSync } from 'node:fs';
import { planFromJson, stopsFromCsv, solvePlan, checkPlan, routesToCsv, driverSheetsPdf } from './dist/node/bmx-route-planner.mjs';
const fleet = planFromJson(readFileSync('fleet.json', 'utf8'));
const { plan: withStops, skipped } = stopsFromCsv(fleet, readFileSync('exports/orders-tomorrow.csv', 'utf8'));
if (skipped.length) console.log(`Rows without a place: ${skipped.join(', ')}`);
const { plan } = solvePlan(withStops, { timeMs: 20000 });
for (const issue of checkPlan(plan)) console.log(issue.severity, issue.message);
writeFileSync('out/routes.csv', routesToCsv(plan));
writeFileSync('out/driver-sheets.pdf', await driverSheetsPdf(plan));
Field engineers' appointments
Three made-up engineers who start and finish at home, one qualified for gas, one for electrical work and one for both, with morning and afternoon appointments and some routine services that can wait if the day is full. Plan the day, then let an urgent job come in and fit it in without moving everyone.
Get the code
<script src="/assets/bmx-components.min.js"></script> <bmx-route-planner id="lg-eng" currency="£" label="Engineers, Thursday" style="inline-size: 100%; --bmx-route-planner-height: 32rem"></bmx-route-planner>