Skip to content
GuidesBlogPlaygroundDashboard

Build an EV Road Trip Planner

A Go CLI that plans charging stops along a route based on your EV's range, finding compatible stations and estimating where you'll need to stop.

Give this CLI two cities and your EV’s range in kilometers, and it plans the route, finds charging stations along the way, and tells you where to stop before your battery dies.

  • Geocoding to resolve origin and destination
  • Routing to calculate the driving route with distance and geometry
  • PlazaQL to find EV charging stations along the route corridor

After getting a route, we sample points every 30km along the geometry and search for chargers near each one:

samples := planner.SampleRoute(routeCoords, 30.0) // every 30km
for _, sp := range samples {
chargers, _ := client.FindChargers(sp.Lat, sp.Lng)
allChargers = append(allChargers, chargers...)
}
allChargers = planner.DeduplicateChargers(allChargers)

The PlazaQL query for each sample point finds charging stations within 5km:

query := fmt.Sprintf(
`$$ = search(node, amenity: "charging_station").around(distance: 5000, geometry: point(%f, %f));`,
lat, lng,
)

The stop planning algorithm is a greedy approach — drive until you’ve used 60% of range, then stop at the farthest reachable charger. A 15% buffer means you never plan to arrive at a charger on fumes:

bufferKm := maxRangeKm * 0.15
stopThreshold := maxRangeKm * 0.40
for i := range taggedChargers {
legDist := c.DistAlongRoute - lastStopDist
arrivalRange := currentRange - legDist
if arrivalRange < bufferKm {
continue // can't reach safely
}
if arrivalRange <= stopThreshold {
// Good candidate — we're getting low, stop here
}
}

Each charger gets tagged with its distance along the route by finding the nearest point on the route geometry, so we can reason about “km 295 along route” rather than raw coordinates.

  1. Geocode both cities, then route between them to get a LineString geometry with total distance.
  2. Sample the route every 30km and search a 5km buffer around each point via PlazaQL. One query per sample point since the full corridor could span thousands of km. Results are deduplicated by coordinate.
  3. Plan stops with a greedy algorithm: drive until range drops below 40%, then pick the farthest reachable charger. After each stop, assume a full charge.
  4. Print the plan showing each stop with operator, connector types, power output, and distance along route.

OSM charging data uses the amenity=charging_station tag with socket types in sub-tags: socket:type2, socket:type2_combo (CCS), socket:chademo. Coverage varies by region — Europe is well-mapped, the US is growing fast.

The complete working app is at github.com/plazafyi/example-apps/ev-trip-planner. It’s a Go CLI with separate packages for the Plaza API client and the route planning logic.

Terminal window
git clone https://github.com/plazafyi/example-apps
cd example-apps/ev-trip-planner
export PLAZA_API_KEY=your-key-here
go run . "San Francisco" "Los Angeles" 300

Filter by connector type. If your car only takes CCS, filter the results before planning: chargers = filterByCCS(chargers). You don’t want to plan a stop at a CHAdeMO-only station.

Adjust the buffer. Change the 15% buffer to 20% if you want more safety margin, or 10% if you like living on the edge.

Add elevation. Hit the elevation profile endpoint with the route geometry. Uphill segments drain more battery — a proper energy model would adjust range based on elevation gain.

Export to GeoJSON. Dump the route geometry and charger locations to a .geojson file, then open it in geojson.io to see the whole plan on a map.